tmf: Add collapse, expand and hide category buttons on marker axis
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / TimeGraphViewer.java
1 /*****************************************************************************
2 * Copyright (c) 2007, 2016 Intel Corporation, Ericsson, others
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel Corporation - Initial API and implementation
10 * Ruslan A. Scherbakov, Intel - Initial API and implementation
11 * Alexander N. Alexeev, Intel - Add monitors statistics support
12 * Alvaro Sanchez-Leon - Adapted for TMF
13 * Patrick Tasse - Refactoring
14 * Geneviève Bastien - Add event links between entries
15 *****************************************************************************/
16
17 package org.eclipse.tracecompass.tmf.ui.widgets.timegraph;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.eclipse.jface.action.Action;
28 import org.eclipse.jface.action.ActionContributionItem;
29 import org.eclipse.jface.action.IAction;
30 import org.eclipse.jface.action.IMenuCreator;
31 import org.eclipse.jface.action.IMenuListener;
32 import org.eclipse.jface.action.IMenuManager;
33 import org.eclipse.jface.action.MenuManager;
34 import org.eclipse.jface.dialogs.IDialogSettings;
35 import org.eclipse.jface.resource.ImageDescriptor;
36 import org.eclipse.jface.viewers.AbstractTreeViewer;
37 import org.eclipse.jface.viewers.ISelectionProvider;
38 import org.eclipse.jface.viewers.ITableLabelProvider;
39 import org.eclipse.jface.viewers.ITreeContentProvider;
40 import org.eclipse.jface.viewers.ViewerFilter;
41 import org.eclipse.jface.window.Window;
42 import org.eclipse.swt.SWT;
43 import org.eclipse.swt.events.ControlAdapter;
44 import org.eclipse.swt.events.ControlEvent;
45 import org.eclipse.swt.events.DisposeEvent;
46 import org.eclipse.swt.events.DisposeListener;
47 import org.eclipse.swt.events.KeyAdapter;
48 import org.eclipse.swt.events.KeyEvent;
49 import org.eclipse.swt.events.MenuDetectListener;
50 import org.eclipse.swt.events.MouseEvent;
51 import org.eclipse.swt.events.MouseWheelListener;
52 import org.eclipse.swt.events.SelectionAdapter;
53 import org.eclipse.swt.events.SelectionEvent;
54 import org.eclipse.swt.events.SelectionListener;
55 import org.eclipse.swt.graphics.RGBA;
56 import org.eclipse.swt.graphics.Rectangle;
57 import org.eclipse.swt.layout.FillLayout;
58 import org.eclipse.swt.layout.GridData;
59 import org.eclipse.swt.layout.GridLayout;
60 import org.eclipse.swt.widgets.Composite;
61 import org.eclipse.swt.widgets.Control;
62 import org.eclipse.swt.widgets.Display;
63 import org.eclipse.swt.widgets.Event;
64 import org.eclipse.swt.widgets.Listener;
65 import org.eclipse.swt.widgets.Menu;
66 import org.eclipse.swt.widgets.Slider;
67 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
68 import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
69 import org.eclipse.tracecompass.internal.tmf.ui.Messages;
70 import org.eclipse.tracecompass.internal.tmf.ui.dialogs.AddBookmarkDialog;
71 import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
72 import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
73 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ShowFilterDialogAction;
74 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TimeGraphLegend;
75 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
76 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
77 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
78 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
79 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
80 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.IMarkerAxisListener;
81 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.ITimeDataProvider;
82 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeDataProviderCyclesConverter;
83 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphColorScheme;
84 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
85 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphMarkerAxis;
86 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphScale;
87 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphTooltipHandler;
88 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
89 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
90 import org.eclipse.ui.PlatformUI;
91
92 /**
93 * Generic time graph viewer implementation
94 *
95 * @author Patrick Tasse, and others
96 */
97 public class TimeGraphViewer implements ITimeDataProvider, IMarkerAxisListener, SelectionListener {
98
99 /** Constant indicating that all levels of the time graph should be expanded */
100 public static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
101
102 private static final int DEFAULT_NAME_WIDTH = 200;
103 private static final int MIN_NAME_WIDTH = 6;
104 private static final int MAX_NAME_WIDTH = 1000;
105 private static final int DEFAULT_HEIGHT = 22;
106 private static final String HIDE_ARROWS_KEY = "hide.arrows"; //$NON-NLS-1$
107 private static final long DEFAULT_FREQUENCY = 1000000000L;
108 private static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1;
109
110 private static final ImageDescriptor ADD_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ADD_BOOKMARK);
111 private static final ImageDescriptor NEXT_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_BOOKMARK);
112 private static final ImageDescriptor PREVIOUS_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREVIOUS_BOOKMARK);
113 private static final ImageDescriptor REMOVE_BOOKMARK = Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_REMOVE_BOOKMARK);
114
115 private long fMinTimeInterval;
116 private ITimeGraphEntry fSelectedEntry;
117 private long fBeginTime = SWT.DEFAULT; // The user-specified bounds start time
118 private long fEndTime = SWT.DEFAULT; // The user-specified bounds end time
119 private long fTime0 = SWT.DEFAULT; // The current window start time
120 private long fTime1 = SWT.DEFAULT; // The current window end time
121 private long fSelectionBegin = SWT.DEFAULT;
122 private long fSelectionEnd = SWT.DEFAULT;
123 private long fTime0Bound = SWT.DEFAULT; // The bounds start time
124 private long fTime1Bound = SWT.DEFAULT; // The bounds end time
125 private long fTime0ExtSynch = SWT.DEFAULT;
126 private long fTime1ExtSynch = SWT.DEFAULT;
127 private boolean fTimeRangeFixed;
128 private int fNameWidthPref = DEFAULT_NAME_WIDTH;
129 private int fMinNameWidth = MIN_NAME_WIDTH;
130 private int fNameWidth;
131 private Composite fDataViewer;
132
133 private TimeGraphControl fTimeGraphCtrl;
134 private TimeGraphScale fTimeScaleCtrl;
135 private TimeGraphMarkerAxis fMarkerAxisCtrl;
136 private Slider fHorizontalScrollBar;
137 private Slider fVerticalScrollBar;
138 private @NonNull TimeGraphColorScheme fColorScheme = new TimeGraphColorScheme();
139 private Object fInputElement;
140 private ITimeGraphContentProvider fTimeGraphContentProvider;
141 private ITimeGraphPresentationProvider fTimeGraphProvider;
142 private @NonNull ITimeDataProvider fTimeDataProvider = this;
143 private TimeGraphTooltipHandler fToolTipHandler;
144
145 private List<ITimeGraphSelectionListener> fSelectionListeners = new ArrayList<>();
146 private List<ITimeGraphTimeListener> fTimeListeners = new ArrayList<>();
147 private List<ITimeGraphRangeListener> fRangeListeners = new ArrayList<>();
148 private List<ITimeGraphBookmarkListener> fBookmarkListeners = new ArrayList<>();
149
150 // Time format, using Epoch reference, Relative time format(default),
151 // Number, or Cycles
152 private TimeFormat fTimeFormat = TimeFormat.RELATIVE;
153 // Clock frequency to use for Cycles time format
154 private long fClockFrequency = DEFAULT_FREQUENCY;
155 private int fBorderWidth = 0;
156 private int fTimeScaleHeight = DEFAULT_HEIGHT;
157
158 private Action fResetScaleAction;
159 private Action fShowLegendAction;
160 private Action fNextEventAction;
161 private Action fPrevEventAction;
162 private Action fNextItemAction;
163 private Action fPreviousItemAction;
164 private Action fZoomInAction;
165 private Action fZoomOutAction;
166 private Action fHideArrowsAction;
167 private Action fFollowArrowFwdAction;
168 private Action fFollowArrowBwdAction;
169 private ShowFilterDialogAction fShowFilterDialogAction;
170 private Action fToggleBookmarkAction;
171 private Action fNextMarkerAction;
172 private Action fPreviousMarkerAction;
173 private MenuManager fMarkersMenu;
174
175 /** The list of bookmarks */
176 private final List<IMarkerEvent> fBookmarks = new ArrayList<>();
177
178 /** The list of marker categories */
179 private final List<String> fMarkerCategories = new ArrayList<>();
180
181 /** The set of hidden marker categories */
182 private final Set<String> fHiddenMarkerCategories = new HashSet<>();
183
184 /** The set of skipped marker categories */
185 private final Set<String> fSkippedMarkerCategories = new HashSet<>();
186
187 /** The list of markers */
188 private final List<IMarkerEvent> fMarkers = new ArrayList<>();
189
190 private ListenerNotifier fListenerNotifier;
191
192 private Composite fTimeAlignedComposite;
193
194 private class ListenerNotifier extends Thread {
195 private static final long DELAY = 400L;
196 private static final long POLLING_INTERVAL = 10L;
197 private long fLastUpdateTime = Long.MAX_VALUE;
198 private boolean fSelectionChanged = false;
199 private boolean fTimeRangeUpdated = false;
200 private boolean fTimeSelected = false;
201
202 @Override
203 public void run() {
204 while ((System.currentTimeMillis() - fLastUpdateTime) < DELAY) {
205 try {
206 Thread.sleep(POLLING_INTERVAL);
207 } catch (Exception e) {
208 return;
209 }
210 }
211 Display.getDefault().asyncExec(new Runnable() {
212 @Override
213 public void run() {
214 if (fListenerNotifier != ListenerNotifier.this) {
215 return;
216 }
217 fListenerNotifier = null;
218 if (ListenerNotifier.this.isInterrupted() || fDataViewer.isDisposed()) {
219 return;
220 }
221 if (fSelectionChanged) {
222 fireSelectionChanged(fSelectedEntry);
223 }
224 if (fTimeRangeUpdated) {
225 fireTimeRangeUpdated(fTime0, fTime1);
226 }
227 if (fTimeSelected) {
228 fireTimeSelected(fSelectionBegin, fSelectionEnd);
229 }
230 }
231 });
232 }
233
234 public void selectionChanged() {
235 fSelectionChanged = true;
236 fLastUpdateTime = System.currentTimeMillis();
237 }
238
239 public void timeRangeUpdated() {
240 fTimeRangeUpdated = true;
241 fLastUpdateTime = System.currentTimeMillis();
242 }
243
244 public void timeSelected() {
245 fTimeSelected = true;
246 fLastUpdateTime = System.currentTimeMillis();
247 }
248
249 public boolean hasSelectionChanged() {
250 return fSelectionChanged;
251 }
252
253 public boolean hasTimeRangeUpdated() {
254 return fTimeRangeUpdated;
255 }
256
257 public boolean hasTimeSelected() {
258 return fTimeSelected;
259 }
260 }
261
262 private final static class MarkerComparator implements Comparator<IMarkerEvent> {
263 @Override
264 public int compare(IMarkerEvent o1, IMarkerEvent o2) {
265 int res = Long.compare(o1.getTime(), o2.getTime());
266 if (res != 0) {
267 return res;
268 }
269 return Long.compare(o1.getDuration(), o2.getDuration());
270 }
271 }
272
273 /**
274 * Standard constructor.
275 * <p>
276 * The default timegraph content provider accepts an ITimeGraphEntry[] as input element.
277 *
278 * @param parent
279 * The parent UI composite object
280 * @param style
281 * The style to use
282 */
283 public TimeGraphViewer(Composite parent, int style) {
284 createDataViewer(parent, style);
285 fTimeGraphContentProvider = new TimeGraphContentProvider();
286 }
287
288 /**
289 * Sets the timegraph content provider used by this timegraph viewer.
290 *
291 * @param timeGraphContentProvider
292 * the timegraph content provider
293 */
294 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
295 fTimeGraphContentProvider = timeGraphContentProvider;
296 }
297
298 /**
299 * Gets the timegraph content provider used by this timegraph viewer.
300 *
301 * @return the timegraph content provider
302 */
303 public ITimeGraphContentProvider getTimeGraphContentProvider() {
304 return fTimeGraphContentProvider;
305 }
306
307 /**
308 * Sets the timegraph presentation provider used by this timegraph viewer.
309 *
310 * @param timeGraphProvider
311 * the timegraph provider
312 */
313 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {
314 fTimeGraphProvider = timeGraphProvider;
315 fTimeGraphCtrl.setTimeGraphProvider(timeGraphProvider);
316 fToolTipHandler = new TimeGraphTooltipHandler(fTimeGraphProvider, fTimeDataProvider);
317 fToolTipHandler.activateHoverHelp(fTimeGraphCtrl);
318 }
319
320 /**
321 * Sets the tree columns for this time graph combo's filter dialog.
322 *
323 * @param columnNames the tree column names
324 * @since 2.0
325 */
326 public void setFilterColumns(String[] columnNames) {
327 getShowFilterDialogAction().getFilterDialog().setColumnNames(columnNames);
328 }
329
330 /**
331 * Sets the tree content provider used by the filter dialog
332 *
333 * @param contentProvider the tree content provider
334 * @since 2.0
335 */
336 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
337 getShowFilterDialogAction().getFilterDialog().setContentProvider(contentProvider);
338 }
339
340 /**
341 * Sets the tree label provider used by the filter dialog
342 *
343 * @param labelProvider the tree label provider
344 * @since 2.0
345 */
346 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
347 getShowFilterDialogAction().getFilterDialog().setLabelProvider(labelProvider);
348 }
349
350 /**
351 * Sets or clears the input for this time graph viewer.
352 *
353 * @param inputElement
354 * The input of this time graph viewer, or <code>null</code> if
355 * none
356 */
357 public void setInput(Object inputElement) {
358 fInputElement = inputElement;
359 ITimeGraphEntry[] input = fTimeGraphContentProvider.getElements(inputElement);
360 fListenerNotifier = null;
361 if (fTimeGraphCtrl != null) {
362 setTimeRange(input);
363 setTopIndex(0);
364 fSelectionBegin = SWT.DEFAULT;
365 fSelectionEnd = SWT.DEFAULT;
366 updateMarkerActions();
367 fSelectedEntry = null;
368 refreshAllData(input);
369 }
370 }
371
372 /**
373 * Gets the input for this time graph viewer.
374 *
375 * @return The input of this time graph viewer, or <code>null</code> if none
376 */
377 public Object getInput() {
378 return fInputElement;
379 }
380
381 /**
382 * Sets (or clears if null) the list of links to display on this combo
383 *
384 * @param links
385 * the links to display in this time graph combo
386 */
387 public void setLinks(List<ILinkEvent> links) {
388 if (fTimeGraphCtrl != null) {
389 fTimeGraphCtrl.refreshArrows(links);
390 }
391 }
392
393 /**
394 * Refresh the view
395 */
396 public void refresh() {
397 ITimeGraphEntry[] input = fTimeGraphContentProvider.getElements(fInputElement);
398 setTimeRange(input);
399 refreshAllData(input);
400 }
401
402 /**
403 * Callback for when the control is moved
404 *
405 * @param e
406 * The caller event
407 */
408 public void controlMoved(ControlEvent e) {
409 }
410
411 /**
412 * Callback for when the control is resized
413 *
414 * @param e
415 * The caller event
416 */
417 public void controlResized(ControlEvent e) {
418 resizeControls();
419 }
420
421 /**
422 * @return The string representing the view type
423 */
424 protected String getViewTypeStr() {
425 return "viewoption.threads"; //$NON-NLS-1$
426 }
427
428 int getMarginWidth() {
429 return 0;
430 }
431
432 int getMarginHeight() {
433 return 0;
434 }
435
436 void loadOptions() {
437 fMinTimeInterval = 1;
438 fSelectionBegin = SWT.DEFAULT;
439 fSelectionEnd = SWT.DEFAULT;
440 fNameWidth = Utils.loadIntOption(getPreferenceString("namewidth"), //$NON-NLS-1$
441 fNameWidthPref, fMinNameWidth, MAX_NAME_WIDTH);
442 }
443
444 void saveOptions() {
445 Utils.saveIntOption(getPreferenceString("namewidth"), fNameWidth); //$NON-NLS-1$
446 }
447
448 /**
449 * Create a data viewer.
450 *
451 * @param parent
452 * Parent composite
453 * @param style
454 * Style to use
455 * @return The new data viewer
456 */
457 protected Control createDataViewer(Composite parent, int style) {
458 loadOptions();
459 fDataViewer = new Composite(parent, style) {
460 @Override
461 public void redraw() {
462 fTimeScaleCtrl.redraw();
463 fTimeGraphCtrl.redraw();
464 fMarkerAxisCtrl.redraw();
465 super.redraw();
466 }
467 };
468 fDataViewer.addDisposeListener(new DisposeListener() {
469 @Override
470 public void widgetDisposed(DisposeEvent e) {
471 if (fMarkersMenu != null) {
472 fMarkersMenu.dispose();
473 }
474 }
475 });
476 GridLayout gl = new GridLayout(2, false);
477 gl.marginHeight = fBorderWidth;
478 gl.marginWidth = 0;
479 gl.verticalSpacing = 0;
480 gl.horizontalSpacing = 0;
481 fDataViewer.setLayout(gl);
482
483 fTimeAlignedComposite = new Composite(fDataViewer, style) {
484 @Override
485 public void redraw() {
486 fDataViewer.redraw();
487 super.redraw();
488 }
489 };
490 GridLayout gl2 = new GridLayout(1, false);
491 gl2.marginHeight = fBorderWidth;
492 gl2.marginWidth = 0;
493 gl2.verticalSpacing = 0;
494 gl2.horizontalSpacing = 0;
495 fTimeAlignedComposite.setLayout(gl2);
496 fTimeAlignedComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
497
498 fTimeScaleCtrl = new TimeGraphScale(fTimeAlignedComposite, fColorScheme);
499 fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
500 fTimeScaleCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
501 fTimeScaleCtrl.setHeight(fTimeScaleHeight);
502 fTimeScaleCtrl.addMouseWheelListener(new MouseWheelListener() {
503 @Override
504 public void mouseScrolled(MouseEvent e) {
505 fTimeGraphCtrl.zoom(e.count > 0);
506 }
507 });
508
509 fTimeGraphCtrl = createTimeGraphControl(fTimeAlignedComposite, fColorScheme);
510
511 fTimeGraphCtrl.setTimeProvider(this);
512 fTimeGraphCtrl.setTimeGraphScale(fTimeScaleCtrl);
513 fTimeGraphCtrl.addSelectionListener(this);
514 fTimeGraphCtrl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
515 fTimeGraphCtrl.addMouseWheelListener(new MouseWheelListener() {
516 @Override
517 public void mouseScrolled(MouseEvent e) {
518 adjustVerticalScrollBar();
519 }
520 });
521 fTimeGraphCtrl.addKeyListener(new KeyAdapter() {
522 @Override
523 public void keyPressed(KeyEvent e) {
524 if ((e.character == '+' || e.character == '=') && ((e.stateMask & SWT.CTRL) == 0)) {
525 zoomIn();
526 } else if (e.character == '-' && ((e.stateMask & SWT.CTRL) == 0)) {
527 zoomOut();
528 } else if (e.keyCode == '.') {
529 boolean extend = (e.stateMask & SWT.SHIFT) != 0;
530 if (extend) {
531 extendToNextMarker();
532 } else {
533 selectNextMarker();
534 }
535 } else if (e.keyCode == ',') {
536 boolean extend = (e.stateMask & SWT.SHIFT) != 0;
537 if (extend) {
538 extendToPrevMarker();
539 } else {
540 selectPrevMarker();
541 }
542 }
543 adjustVerticalScrollBar();
544 }
545 });
546
547 fMarkerAxisCtrl = createTimeGraphMarkerAxis(fTimeAlignedComposite, fColorScheme, this);
548 fMarkerAxisCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
549 fMarkerAxisCtrl.addMarkerAxisListener(this);
550 fMarkerAxisCtrl.addMouseWheelListener(new MouseWheelListener() {
551 @Override
552 public void mouseScrolled(MouseEvent e) {
553 fTimeGraphCtrl.zoom(e.count > 0);
554 }
555 });
556
557 fVerticalScrollBar = new Slider(fDataViewer, SWT.VERTICAL | SWT.NO_FOCUS);
558 fVerticalScrollBar.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false, true, 1, 1));
559 fVerticalScrollBar.addSelectionListener(new SelectionAdapter() {
560 @Override
561 public void widgetSelected(SelectionEvent e) {
562 setTopIndex(fVerticalScrollBar.getSelection());
563 }
564 });
565
566 fHorizontalScrollBar = new Slider(fDataViewer, SWT.HORIZONTAL | SWT.NO_FOCUS);
567 fHorizontalScrollBar.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
568 fHorizontalScrollBar.addListener(SWT.MouseWheel, new Listener() {
569 @Override
570 public void handleEvent(Event event) {
571 if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL) {
572 getTimeGraphControl().zoom(event.count > 0);
573 } else {
574 getTimeGraphControl().horizontalScroll(event.count > 0);
575 }
576 // don't handle the immediately following SWT.Selection event
577 event.doit = false;
578 }
579 });
580 fHorizontalScrollBar.addListener(SWT.Selection, new Listener() {
581 @Override
582 public void handleEvent(Event event) {
583 int start = fHorizontalScrollBar.getSelection();
584 long time0 = getTime0();
585 long time1 = getTime1();
586 long timeMin = getMinTime();
587 long timeMax = getMaxTime();
588 long delta = timeMax - timeMin;
589
590 long range = time1 - time0;
591 time0 = timeMin + Math.round(delta * ((double) start / H_SCROLLBAR_MAX));
592 time1 = time0 + range;
593
594 setStartFinishTimeNotify(time0, time1);
595 }
596 });
597
598 Composite filler = new Composite(fDataViewer, SWT.NONE);
599 GridData gd = new GridData(SWT.DEFAULT, SWT.DEFAULT, false, false);
600 gd.heightHint = fHorizontalScrollBar.getSize().y;
601 filler.setLayoutData(gd);
602 filler.setLayout(new FillLayout());
603
604 fTimeGraphCtrl.addControlListener(new ControlAdapter() {
605 @Override
606 public void controlResized(ControlEvent event) {
607 resizeControls();
608 }
609 });
610 resizeControls();
611 fDataViewer.update();
612 adjustHorizontalScrollBar();
613 adjustVerticalScrollBar();
614 return fDataViewer;
615 }
616
617 /**
618 * Dispose the view.
619 */
620 public void dispose() {
621 saveOptions();
622 fTimeGraphCtrl.dispose();
623 fDataViewer.dispose();
624 fColorScheme.dispose();
625 }
626
627 /**
628 * Create a new time graph control.
629 *
630 * @param parent
631 * The parent composite
632 * @param colors
633 * The color scheme
634 * @return The new TimeGraphControl
635 */
636 protected TimeGraphControl createTimeGraphControl(Composite parent,
637 TimeGraphColorScheme colors) {
638 return new TimeGraphControl(parent, colors);
639 }
640
641 /**
642 * Create a new time graph marker axis.
643 *
644 * @param parent
645 * The parent composite object
646 * @param colorScheme
647 * The color scheme to use
648 * @param timeProvider
649 * The time data provider
650 * @return The new TimeGraphMarkerAxis
651 * @since 2.0
652 */
653 protected TimeGraphMarkerAxis createTimeGraphMarkerAxis(Composite parent,
654 @NonNull TimeGraphColorScheme colorScheme, @NonNull ITimeDataProvider timeProvider) {
655 return new TimeGraphMarkerAxis(parent, colorScheme, timeProvider);
656 }
657
658 /**
659 * Resize the controls
660 */
661 public void resizeControls() {
662 Rectangle r = fDataViewer.getClientArea();
663 if (r.isEmpty()) {
664 return;
665 }
666
667 int width = r.width;
668 if (fNameWidth > width - fMinNameWidth) {
669 fNameWidth = width - fMinNameWidth;
670 }
671 if (fNameWidth < fMinNameWidth) {
672 fNameWidth = fMinNameWidth;
673 }
674 adjustHorizontalScrollBar();
675 adjustVerticalScrollBar();
676 }
677
678 /**
679 * Recalculate the time bounds based on the time graph entries,
680 * if the user-specified bound is set to SWT.DEFAULT.
681 *
682 * @param entries
683 * The root time graph entries in the model
684 */
685 public void setTimeRange(ITimeGraphEntry entries[]) {
686 fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime);
687 fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime);
688 if (fBeginTime != SWT.DEFAULT && fEndTime != SWT.DEFAULT) {
689 return;
690 }
691 if (entries == null || entries.length == 0) {
692 return;
693 }
694 if (fTime0Bound == SWT.DEFAULT) {
695 fTime0Bound = Long.MAX_VALUE;
696 }
697 if (fTime1Bound == SWT.DEFAULT) {
698 fTime1Bound = Long.MIN_VALUE;
699 }
700 for (ITimeGraphEntry entry : entries) {
701 setTimeRange(entry);
702 }
703 }
704
705 private void setTimeRange(ITimeGraphEntry entry) {
706 if (fBeginTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getStartTime() != SWT.DEFAULT) {
707 fTime0Bound = Math.min(entry.getStartTime(), fTime0Bound);
708 }
709 if (fEndTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getEndTime() != SWT.DEFAULT) {
710 fTime1Bound = Math.max(entry.getEndTime(), fTime1Bound);
711 }
712 if (entry.hasChildren()) {
713 for (ITimeGraphEntry child : entry.getChildren()) {
714 setTimeRange(child);
715 }
716 }
717 }
718
719 /**
720 * Set the time bounds to the provided values.
721 *
722 * @param beginTime
723 * The bounds begin time, or SWT.DEFAULT to use the input bounds
724 * @param endTime
725 * The bounds end time, or SWT.DEFAULT to use the input bounds
726 */
727 public void setTimeBounds(long beginTime, long endTime) {
728 fBeginTime = beginTime;
729 fEndTime = endTime;
730 fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime);
731 fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime);
732 if (fTime0Bound > fTime1Bound) {
733 // only possible if both are not default
734 fBeginTime = endTime;
735 fEndTime = beginTime;
736 fTime0Bound = fBeginTime;
737 fTime1Bound = fEndTime;
738 }
739 adjustHorizontalScrollBar();
740 }
741
742 /**
743 * Recalculate the current time window when bounds have changed.
744 */
745 public void setTimeBounds() {
746 if (!fTimeRangeFixed) {
747 fTime0 = fTime0Bound;
748 fTime1 = fTime1Bound;
749 }
750 fTime0 = Math.max(fTime0Bound, Math.min(fTime0, fTime1Bound));
751 fTime1 = Math.max(fTime0Bound, Math.min(fTime1, fTime1Bound));
752 if (fTime1 - fTime0 < fMinTimeInterval) {
753 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
754 }
755 }
756
757 /**
758 * @param traces
759 */
760 private void refreshAllData(ITimeGraphEntry[] traces) {
761 setTimeBounds();
762 if (fSelectionBegin < fBeginTime) {
763 fSelectionBegin = fBeginTime;
764 } else if (fSelectionBegin > fEndTime) {
765 fSelectionBegin = fEndTime;
766 }
767 if (fSelectionEnd < fBeginTime) {
768 fSelectionEnd = fBeginTime;
769 } else if (fSelectionEnd > fEndTime) {
770 fSelectionEnd = fEndTime;
771 }
772 fTimeGraphCtrl.refreshData(traces);
773 fTimeScaleCtrl.redraw();
774 fMarkerAxisCtrl.redraw();
775 updateMarkerActions();
776 adjustVerticalScrollBar();
777 }
778
779 /**
780 * Callback for when this view is focused
781 */
782 public void setFocus() {
783 if (null != fTimeGraphCtrl) {
784 fTimeGraphCtrl.setFocus();
785 }
786 }
787
788 /**
789 * Get the current focus status of this view.
790 *
791 * @return If the view is currently focused, or not
792 */
793 public boolean isInFocus() {
794 return fTimeGraphCtrl.isInFocus();
795 }
796
797 /**
798 * Get the view's current selection
799 *
800 * @return The entry that is selected
801 */
802 public ITimeGraphEntry getSelection() {
803 return fTimeGraphCtrl.getSelectedTrace();
804 }
805
806 /**
807 * Get the index of the current selection
808 *
809 * @return The index
810 */
811 public int getSelectionIndex() {
812 return fTimeGraphCtrl.getSelectedIndex();
813 }
814
815 @Override
816 public long getTime0() {
817 return fTime0;
818 }
819
820 @Override
821 public long getTime1() {
822 return fTime1;
823 }
824
825 @Override
826 public long getMinTimeInterval() {
827 return fMinTimeInterval;
828 }
829
830 @Override
831 public int getNameSpace() {
832 return fNameWidth;
833 }
834
835 @Override
836 public void setNameSpace(int width) {
837 fNameWidth = width;
838 int w = fTimeGraphCtrl.getClientArea().width;
839 if (fNameWidth > w - MIN_NAME_WIDTH) {
840 fNameWidth = w - MIN_NAME_WIDTH;
841 }
842 if (fNameWidth < MIN_NAME_WIDTH) {
843 fNameWidth = MIN_NAME_WIDTH;
844 }
845 fTimeGraphCtrl.redraw();
846 fTimeScaleCtrl.redraw();
847 fMarkerAxisCtrl.redraw();
848 /* force update the controls to keep them aligned */
849 fTimeScaleCtrl.update();
850 fMarkerAxisCtrl.update();
851 fTimeGraphCtrl.update();
852 }
853
854 @Override
855 public int getTimeSpace() {
856 int w = fTimeGraphCtrl.getClientArea().width;
857 return w - fNameWidth;
858 }
859
860 @Override
861 public long getBeginTime() {
862 return fBeginTime;
863 }
864
865 @Override
866 public long getEndTime() {
867 return fEndTime;
868 }
869
870 @Override
871 public long getMaxTime() {
872 return fTime1Bound;
873 }
874
875 @Override
876 public long getMinTime() {
877 return fTime0Bound;
878 }
879
880 @Override
881 public long getSelectionBegin() {
882 return fSelectionBegin;
883 }
884
885 @Override
886 public long getSelectionEnd() {
887 return fSelectionEnd;
888 }
889
890 @Override
891 public void setStartFinishTimeNotify(long time0, long time1) {
892 setStartFinishTimeInt(time0, time1);
893 notifyRangeListeners();
894 }
895
896 @Override
897 public void notifyStartFinishTime() {
898 notifyRangeListeners();
899 }
900
901 @Override
902 public void setStartFinishTime(long time0, long time1) {
903 /* if there is a pending time range, ignore this one */
904 if (fListenerNotifier != null && fListenerNotifier.hasTimeRangeUpdated()) {
905 return;
906 }
907 setStartFinishTimeInt(time0, time1);
908 updateExtSynchValues();
909 }
910
911 private void setStartFinishTimeInt(long time0, long time1) {
912 fTime0 = time0;
913 if (fTime0 < fTime0Bound) {
914 fTime0 = fTime0Bound;
915 }
916 if (fTime0 > fTime1Bound) {
917 fTime0 = fTime1Bound;
918 }
919 fTime1 = time1;
920 if (fTime1 < fTime0Bound) {
921 fTime1 = fTime0Bound;
922 }
923 if (fTime1 > fTime1Bound) {
924 fTime1 = fTime1Bound;
925 }
926 if (fTime1 - fTime0 < fMinTimeInterval) {
927 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
928 }
929 fTimeRangeFixed = true;
930 adjustHorizontalScrollBar();
931 fTimeGraphCtrl.redraw();
932 fTimeScaleCtrl.redraw();
933 fMarkerAxisCtrl.redraw();
934 /* force update the controls to keep them aligned */
935 fTimeScaleCtrl.update();
936 fMarkerAxisCtrl.update();
937 fTimeGraphCtrl.update();
938 }
939
940 @Override
941 public void resetStartFinishTime() {
942 setStartFinishTimeNotify(fTime0Bound, fTime1Bound);
943 fTimeRangeFixed = false;
944 }
945
946 @Override
947 public void setSelectedTimeNotify(long time, boolean ensureVisible) {
948 setSelectedTimeInt(time, ensureVisible, true);
949 }
950
951 @Override
952 public void setSelectedTime(long time, boolean ensureVisible) {
953 /* if there is a pending time selection, ignore this one */
954 if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) {
955 return;
956 }
957 setSelectedTimeInt(time, ensureVisible, false);
958 }
959
960 private void setSelectedTimeInt(long time, boolean ensureVisible, boolean doNotify) {
961 setSelectionRangeInt(time, time, ensureVisible, doNotify);
962 }
963
964 /**
965 * @since 2.0
966 */
967 @Override
968 public void setSelectionRangeNotify(long beginTime, long endTime, boolean ensureVisible) {
969 setSelectionRangeInt(beginTime, endTime, ensureVisible, true);
970 }
971
972 /**
973 * @since 2.0
974 */
975 @Override
976 public void setSelectionRange(long beginTime, long endTime, boolean ensureVisible) {
977 /* if there is a pending time selection, ignore this one */
978 if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) {
979 return;
980 }
981 setSelectionRangeInt(beginTime, endTime, ensureVisible, false);
982 }
983
984 private void setSelectionRangeInt(long beginTime, long endTime, boolean ensureVisible, boolean doNotify) {
985 long time0 = fTime0;
986 long time1 = fTime1;
987 long selectionBegin = fSelectionBegin;
988 long selectionEnd = fSelectionEnd;
989 fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
990 fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
991 boolean changed = (selectionBegin != fSelectionBegin || selectionEnd != fSelectionEnd);
992
993 if (ensureVisible) {
994 ensureVisible(selectionBegin != fSelectionBegin ? fSelectionBegin : fSelectionEnd);
995 }
996
997 fTimeGraphCtrl.redraw();
998 fTimeScaleCtrl.redraw();
999 fMarkerAxisCtrl.redraw();
1000 updateMarkerActions();
1001
1002 if ((time0 != fTime0) || (time1 != fTime1)) {
1003 notifyRangeListeners();
1004 }
1005
1006 if (doNotify && changed) {
1007 notifyTimeListeners();
1008 }
1009 }
1010
1011 private void ensureVisible(long time) {
1012 long timeMid = (fTime1 - fTime0) / 2;
1013 if (time < fTime0) {
1014 long dt = fTime0 - time + timeMid;
1015 fTime0 -= dt;
1016 fTime1 -= dt;
1017 } else if (time > fTime1) {
1018 long dt = time - fTime1 + timeMid;
1019 fTime0 += dt;
1020 fTime1 += dt;
1021 }
1022 if (fTime0 < fTime0Bound) {
1023 fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0));
1024 fTime0 = fTime0Bound;
1025 } else if (fTime1 > fTime1Bound) {
1026 fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound));
1027 fTime1 = fTime1Bound;
1028 }
1029 if (fTime1 - fTime0 < fMinTimeInterval) {
1030 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
1031 }
1032 adjustHorizontalScrollBar();
1033 }
1034
1035 @Override
1036 public void widgetDefaultSelected(SelectionEvent e) {
1037 if (fSelectedEntry != getSelection()) {
1038 fSelectedEntry = getSelection();
1039 notifySelectionListeners();
1040 }
1041 }
1042
1043 @Override
1044 public void widgetSelected(SelectionEvent e) {
1045 if (fSelectedEntry != getSelection()) {
1046 fSelectedEntry = getSelection();
1047 notifySelectionListeners();
1048 }
1049 }
1050
1051 /**
1052 * Callback for when the next event is selected
1053 *
1054 * @param extend
1055 * true to extend selection range, false for single selection
1056 * @since 1.0
1057 */
1058 public void selectNextEvent(boolean extend) {
1059 fTimeGraphCtrl.selectNextEvent(extend);
1060 adjustVerticalScrollBar();
1061 }
1062
1063 /**
1064 * Callback for when the previous event is selected
1065 *
1066 * @param extend
1067 * true to extend selection range, false for single selection
1068 * @since 1.0
1069 */
1070 public void selectPrevEvent(boolean extend) {
1071 fTimeGraphCtrl.selectPrevEvent(extend);
1072 adjustVerticalScrollBar();
1073 }
1074
1075 /**
1076 * Callback for when the next item is selected
1077 */
1078 public void selectNextItem() {
1079 fTimeGraphCtrl.selectNextTrace();
1080 adjustVerticalScrollBar();
1081 }
1082
1083 /**
1084 * Callback for when the previous item is selected
1085 */
1086 public void selectPrevItem() {
1087 fTimeGraphCtrl.selectPrevTrace();
1088 adjustVerticalScrollBar();
1089 }
1090
1091 /**
1092 * Callback for the show legend action
1093 */
1094 public void showLegend() {
1095 if (fDataViewer == null || fDataViewer.isDisposed()) {
1096 return;
1097 }
1098
1099 TimeGraphLegend.open(fDataViewer.getShell(), fTimeGraphProvider);
1100 }
1101
1102 /**
1103 * Callback for the Zoom In action
1104 */
1105 public void zoomIn() {
1106 fTimeGraphCtrl.zoomIn();
1107 }
1108
1109 /**
1110 * Callback for the Zoom Out action
1111 */
1112 public void zoomOut() {
1113 fTimeGraphCtrl.zoomOut();
1114 }
1115
1116 private String getPreferenceString(String string) {
1117 return getViewTypeStr() + "." + string; //$NON-NLS-1$
1118 }
1119
1120 /**
1121 * Add a selection listener
1122 *
1123 * @param listener
1124 * The listener to add
1125 */
1126 public void addSelectionListener(ITimeGraphSelectionListener listener) {
1127 fSelectionListeners.add(listener);
1128 }
1129
1130 /**
1131 * Remove a selection listener
1132 *
1133 * @param listener
1134 * The listener to remove
1135 */
1136 public void removeSelectionListener(ITimeGraphSelectionListener listener) {
1137 fSelectionListeners.remove(listener);
1138 }
1139
1140 private void notifySelectionListeners() {
1141 if (fListenerNotifier == null) {
1142 fListenerNotifier = new ListenerNotifier();
1143 fListenerNotifier.start();
1144 }
1145 fListenerNotifier.selectionChanged();
1146 }
1147
1148 private void fireSelectionChanged(ITimeGraphEntry selection) {
1149 TimeGraphSelectionEvent event = new TimeGraphSelectionEvent(this, selection);
1150
1151 for (ITimeGraphSelectionListener listener : fSelectionListeners) {
1152 listener.selectionChanged(event);
1153 }
1154 }
1155
1156 /**
1157 * Add a time listener
1158 *
1159 * @param listener
1160 * The listener to add
1161 */
1162 public void addTimeListener(ITimeGraphTimeListener listener) {
1163 fTimeListeners.add(listener);
1164 }
1165
1166 /**
1167 * Remove a time listener
1168 *
1169 * @param listener
1170 * The listener to remove
1171 */
1172 public void removeTimeListener(ITimeGraphTimeListener listener) {
1173 fTimeListeners.remove(listener);
1174 }
1175
1176 private void notifyTimeListeners() {
1177 if (fListenerNotifier == null) {
1178 fListenerNotifier = new ListenerNotifier();
1179 fListenerNotifier.start();
1180 }
1181 fListenerNotifier.timeSelected();
1182 }
1183
1184 private void fireTimeSelected(long startTime, long endTime) {
1185 TimeGraphTimeEvent event = new TimeGraphTimeEvent(this, startTime, endTime);
1186
1187 for (ITimeGraphTimeListener listener : fTimeListeners) {
1188 listener.timeSelected(event);
1189 }
1190 }
1191
1192 /**
1193 * Add a range listener
1194 *
1195 * @param listener
1196 * The listener to add
1197 */
1198 public void addRangeListener(ITimeGraphRangeListener listener) {
1199 fRangeListeners.add(listener);
1200 }
1201
1202 /**
1203 * Remove a range listener
1204 *
1205 * @param listener
1206 * The listener to remove
1207 */
1208 public void removeRangeListener(ITimeGraphRangeListener listener) {
1209 fRangeListeners.remove(listener);
1210 }
1211
1212 private void notifyRangeListeners() {
1213 if (fListenerNotifier == null) {
1214 fListenerNotifier = new ListenerNotifier();
1215 fListenerNotifier.start();
1216 }
1217 fListenerNotifier.timeRangeUpdated();
1218 }
1219
1220 private void fireTimeRangeUpdated(long startTime, long endTime) {
1221 // Check if the time has actually changed from last notification
1222 if (startTime != fTime0ExtSynch || endTime != fTime1ExtSynch) {
1223 // Notify Time Scale Selection Listeners
1224 TimeGraphRangeUpdateEvent event = new TimeGraphRangeUpdateEvent(this, startTime, endTime);
1225
1226 for (ITimeGraphRangeListener listener : fRangeListeners) {
1227 listener.timeRangeUpdated(event);
1228 }
1229
1230 // update external synch values
1231 updateExtSynchValues();
1232 }
1233 }
1234
1235 /**
1236 * Add a bookmark listener
1237 *
1238 * @param listener
1239 * The listener to add
1240 * @since 2.0
1241 */
1242 public void addBookmarkListener(ITimeGraphBookmarkListener listener) {
1243 fBookmarkListeners.add(listener);
1244 }
1245
1246 /**
1247 * Remove a bookmark listener
1248 *
1249 * @param listener
1250 * The listener to remove
1251 * @since 2.0
1252 */
1253 public void removeBookmarkListener(ITimeGraphBookmarkListener listener) {
1254 fBookmarkListeners.remove(listener);
1255 }
1256
1257 private void fireBookmarkAdded(IMarkerEvent bookmark) {
1258 TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
1259
1260 for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
1261 listener.bookmarkAdded(event);
1262 }
1263 }
1264
1265 private void fireBookmarkRemoved(IMarkerEvent bookmark) {
1266 TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
1267
1268 for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
1269 listener.bookmarkRemoved(event);
1270 }
1271 }
1272
1273 /**
1274 * Set the bookmarks list.
1275 *
1276 * @param bookmarks
1277 * The bookmarks list, or null
1278 * @since 2.0
1279 */
1280 public void setBookmarks(List<IMarkerEvent> bookmarks) {
1281 fBookmarks.clear();
1282 if (bookmarks != null) {
1283 fBookmarks.addAll(bookmarks);
1284 }
1285 updateMarkerList();
1286 updateMarkerActions();
1287 }
1288
1289 /**
1290 * Get the bookmarks list.
1291 *
1292 * @return The bookmarks list
1293 * @since 2.0
1294 */
1295 public List<IMarkerEvent> getBookmarks() {
1296 return Collections.unmodifiableList(fBookmarks);
1297 }
1298
1299 /**
1300 * Set the list of marker categories.
1301 *
1302 * @param categories
1303 * The list of marker categories, or null
1304 * @since 2.0
1305 */
1306 public void setMarkerCategories(List<String> categories) {
1307 fMarkerCategories.clear();
1308 if (categories != null) {
1309 fMarkerCategories.addAll(categories);
1310 }
1311 fMarkerCategories.add(IMarkerEvent.BOOKMARKS);
1312 fMarkerAxisCtrl.setMarkerCategories(fMarkerCategories);
1313 }
1314
1315 /**
1316 * @since 2.0
1317 */
1318 @Override
1319 public void setMarkerCategoryVisible(String category, boolean visible) {
1320 boolean changed = false;
1321 if (visible) {
1322 changed = fHiddenMarkerCategories.remove(category);
1323 } else {
1324 changed = fHiddenMarkerCategories.add(category);
1325 }
1326 if (changed) {
1327 updateMarkerList();
1328 updateMarkerActions();
1329 getControl().redraw();
1330 }
1331 }
1332
1333 /**
1334 * Set the markers list.
1335 *
1336 * @param markers
1337 * The markers list, or null
1338 * @since 2.0
1339 */
1340 public void setMarkers(List<IMarkerEvent> markers) {
1341 fMarkers.clear();
1342 if (markers != null) {
1343 fMarkers.addAll(markers);
1344 }
1345 updateMarkerList();
1346 updateMarkerActions();
1347 }
1348
1349 /**
1350 * Get the markers list.
1351 *
1352 * @return The markers list, or null
1353 * @since 2.0
1354 */
1355 public List<IMarkerEvent> getMarkers() {
1356 return Collections.unmodifiableList(fMarkers);
1357 }
1358
1359 /**
1360 * Callback to set a selected event in the view
1361 *
1362 * @param event
1363 * The event that was selected
1364 * @param source
1365 * The source of this selection event
1366 */
1367 public void setSelectedEvent(ITimeEvent event, Object source) {
1368 if (event == null || source == this) {
1369 return;
1370 }
1371 fSelectedEntry = event.getEntry();
1372 fTimeGraphCtrl.selectItem(fSelectedEntry, false);
1373
1374 setSelectedTimeInt(event.getTime(), true, true);
1375 adjustVerticalScrollBar();
1376 }
1377
1378 /**
1379 * Set the seeked time of a trace
1380 *
1381 * @param trace
1382 * The trace that was seeked
1383 * @param time
1384 * The target time
1385 * @param source
1386 * The source of this seek event
1387 */
1388 public void setSelectedTraceTime(ITimeGraphEntry trace, long time, Object source) {
1389 if (trace == null || source == this) {
1390 return;
1391 }
1392 fSelectedEntry = trace;
1393 fTimeGraphCtrl.selectItem(trace, false);
1394
1395 setSelectedTimeInt(time, true, true);
1396 }
1397
1398 /**
1399 * Callback for a trace selection
1400 *
1401 * @param trace
1402 * The trace that was selected
1403 */
1404 public void setSelection(ITimeGraphEntry trace) {
1405 /* if there is a pending selection, ignore this one */
1406 if (fListenerNotifier != null && fListenerNotifier.hasSelectionChanged()) {
1407 return;
1408 }
1409 fSelectedEntry = trace;
1410 fTimeGraphCtrl.selectItem(trace, false);
1411 adjustVerticalScrollBar();
1412 }
1413
1414 /**
1415 * Callback for a time window selection
1416 *
1417 * @param time0
1418 * Start time of the range
1419 * @param time1
1420 * End time of the range
1421 * @param source
1422 * Source of the event
1423 */
1424 public void setSelectVisTimeWindow(long time0, long time1, Object source) {
1425 if (source == this) {
1426 return;
1427 }
1428
1429 setStartFinishTimeInt(time0, time1);
1430
1431 // update notification time values since we are now in synch with the
1432 // external application
1433 updateExtSynchValues();
1434 }
1435
1436 /**
1437 * update the cache values used to identify the need to send a time window
1438 * update to external registered listeners
1439 */
1440 private void updateExtSynchValues() {
1441 // last time notification cache
1442 fTime0ExtSynch = fTime0;
1443 fTime1ExtSynch = fTime1;
1444 }
1445
1446 @Override
1447 public TimeFormat getTimeFormat() {
1448 return fTimeFormat;
1449 }
1450
1451 /**
1452 * @param tf
1453 * the {@link TimeFormat} used to display timestamps
1454 */
1455 public void setTimeFormat(TimeFormat tf) {
1456 this.fTimeFormat = tf;
1457 if (tf == TimeFormat.CYCLES) {
1458 fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
1459 } else {
1460 fTimeDataProvider = this;
1461 }
1462 fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
1463 if (fToolTipHandler != null) {
1464 fToolTipHandler.setTimeProvider(fTimeDataProvider);
1465 }
1466 }
1467
1468 /**
1469 * Sets the clock frequency. Used when the time format is set to CYCLES.
1470 *
1471 * @param clockFrequency
1472 * the clock frequency in Hz
1473 */
1474 public void setClockFrequency(long clockFrequency) {
1475 fClockFrequency = clockFrequency;
1476 if (fTimeFormat == TimeFormat.CYCLES) {
1477 fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
1478 fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
1479 if (fToolTipHandler != null) {
1480 fToolTipHandler.setTimeProvider(fTimeDataProvider);
1481 }
1482 }
1483 }
1484
1485 /**
1486 * Retrieve the border width
1487 *
1488 * @return The width
1489 */
1490 public int getBorderWidth() {
1491 return fBorderWidth;
1492 }
1493
1494 /**
1495 * Set the border width
1496 *
1497 * @param borderWidth
1498 * The width
1499 */
1500 public void setBorderWidth(int borderWidth) {
1501 if (borderWidth > -1) {
1502 this.fBorderWidth = borderWidth;
1503 GridLayout gl = (GridLayout) fDataViewer.getLayout();
1504 gl.marginHeight = borderWidth;
1505 }
1506 }
1507
1508 /**
1509 * Retrieve the height of the header
1510 *
1511 * @return The height
1512 */
1513 public int getHeaderHeight() {
1514 return fTimeScaleHeight;
1515 }
1516
1517 /**
1518 * Set the height of the header
1519 *
1520 * @param headerHeight
1521 * The height to set
1522 */
1523 public void setHeaderHeight(int headerHeight) {
1524 if (headerHeight > -1) {
1525 this.fTimeScaleHeight = headerHeight;
1526 fTimeScaleCtrl.setHeight(headerHeight);
1527 }
1528 }
1529
1530 /**
1531 * Retrieve the height of an item row
1532 *
1533 * @return The height
1534 */
1535 public int getItemHeight() {
1536 if (fTimeGraphCtrl != null) {
1537 return fTimeGraphCtrl.getItemHeight();
1538 }
1539 return 0;
1540 }
1541
1542 /**
1543 * Set the height of an item row
1544 *
1545 * @param rowHeight
1546 * The height to set
1547 */
1548 public void setItemHeight(int rowHeight) {
1549 if (fTimeGraphCtrl != null) {
1550 fTimeGraphCtrl.setItemHeight(rowHeight);
1551 }
1552 }
1553
1554 /**
1555 * Set the minimum item width
1556 *
1557 * @param width
1558 * The min width
1559 */
1560 public void setMinimumItemWidth(int width) {
1561 if (fTimeGraphCtrl != null) {
1562 fTimeGraphCtrl.setMinimumItemWidth(width);
1563 }
1564 }
1565
1566 /**
1567 * Set the width for the name column
1568 *
1569 * @param width
1570 * The width
1571 */
1572 public void setNameWidthPref(int width) {
1573 fNameWidthPref = width;
1574 if (width == 0) {
1575 fMinNameWidth = 0;
1576 fNameWidth = 0;
1577 }
1578 }
1579
1580 /**
1581 * Retrieve the configure width for the name column
1582 *
1583 * @param width
1584 * Unused?
1585 * @return The width
1586 */
1587 public int getNameWidthPref(int width) {
1588 return fNameWidthPref;
1589 }
1590
1591 /**
1592 * Returns the primary control associated with this viewer.
1593 *
1594 * @return the SWT control which displays this viewer's content
1595 */
1596 public Control getControl() {
1597 return fDataViewer;
1598 }
1599
1600 /**
1601 * Returns the time graph control associated with this viewer.
1602 *
1603 * @return the time graph control
1604 */
1605 public TimeGraphControl getTimeGraphControl() {
1606 return fTimeGraphCtrl;
1607 }
1608
1609 /**
1610 * Returns the time graph scale associated with this viewer.
1611 *
1612 * @return the time graph scale
1613 */
1614 public TimeGraphScale getTimeGraphScale() {
1615 return fTimeScaleCtrl;
1616 }
1617
1618 /**
1619 * Returns the composite containing all the controls that are time aligned,
1620 * i.e. TimeGraphScale, TimeGraphControl.
1621 *
1622 * @return the time based composite
1623 * @since 1.0
1624 */
1625 public Composite getTimeAlignedComposite() {
1626 return fTimeAlignedComposite;
1627 }
1628
1629 /**
1630 * Return the x coordinate corresponding to a time
1631 *
1632 * @param time
1633 * the time
1634 * @return the x coordinate corresponding to the time
1635 */
1636 public int getXForTime(long time) {
1637 return fTimeGraphCtrl.getXForTime(time);
1638 }
1639
1640 /**
1641 * Return the time corresponding to an x coordinate
1642 *
1643 * @param x
1644 * the x coordinate
1645 * @return the time corresponding to the x coordinate
1646 */
1647 public long getTimeAtX(int x) {
1648 return fTimeGraphCtrl.getTimeAtX(x);
1649 }
1650
1651 /**
1652 * Get the selection provider
1653 *
1654 * @return the selection provider
1655 */
1656 public ISelectionProvider getSelectionProvider() {
1657 return fTimeGraphCtrl;
1658 }
1659
1660 /**
1661 * Wait for the cursor
1662 *
1663 * @param waitInd
1664 * Wait indefinitely?
1665 */
1666 public void waitCursor(boolean waitInd) {
1667 fTimeGraphCtrl.waitCursor(waitInd);
1668 }
1669
1670 /**
1671 * Get the horizontal scroll bar object
1672 *
1673 * @return The scroll bar
1674 */
1675 public Slider getHorizontalBar() {
1676 return fHorizontalScrollBar;
1677 }
1678
1679 /**
1680 * Get the vertical scroll bar object
1681 *
1682 * @return The scroll bar
1683 */
1684 public Slider getVerticalBar() {
1685 return fVerticalScrollBar;
1686 }
1687
1688 /**
1689 * Set the given index as the top one
1690 *
1691 * @param index
1692 * The index that will go to the top
1693 */
1694 public void setTopIndex(int index) {
1695 fTimeGraphCtrl.setTopIndex(index);
1696 adjustVerticalScrollBar();
1697 }
1698
1699 /**
1700 * Retrieve the current top index
1701 *
1702 * @return The top index
1703 */
1704 public int getTopIndex() {
1705 return fTimeGraphCtrl.getTopIndex();
1706 }
1707
1708 /**
1709 * Sets the auto-expand level to be used for new entries discovered when
1710 * calling {@link #setInput(Object)} or {@link #refresh()}. The value 0
1711 * means that there is no auto-expand; 1 means that top-level entries are
1712 * expanded, but not their children; 2 means that top-level entries are
1713 * expanded, and their children, but not grand-children; and so on.
1714 * <p>
1715 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1716 * </p>
1717 *
1718 * @param level
1719 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1720 * levels of the tree
1721 */
1722 public void setAutoExpandLevel(int level) {
1723 fTimeGraphCtrl.setAutoExpandLevel(level);
1724 }
1725
1726 /**
1727 * Returns the auto-expand level.
1728 *
1729 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of
1730 * the tree are expanded automatically
1731 * @see #setAutoExpandLevel
1732 */
1733 public int getAutoExpandLevel() {
1734 return fTimeGraphCtrl.getAutoExpandLevel();
1735 }
1736
1737 /**
1738 * Get the expanded state of an entry.
1739 *
1740 * @param entry
1741 * The entry
1742 * @return true if the entry is expanded, false if collapsed
1743 * @since 1.1
1744 */
1745 public boolean getExpandedState(ITimeGraphEntry entry) {
1746 return fTimeGraphCtrl.getExpandedState(entry);
1747 }
1748
1749 /**
1750 * Set the expanded state of an entry
1751 *
1752 * @param entry
1753 * The entry to expand/collapse
1754 * @param expanded
1755 * True for expanded, false for collapsed
1756 */
1757 public void setExpandedState(ITimeGraphEntry entry, boolean expanded) {
1758 fTimeGraphCtrl.setExpandedState(entry, expanded);
1759 adjustVerticalScrollBar();
1760 }
1761
1762 /**
1763 * Collapses all nodes of the viewer's tree, starting with the root.
1764 */
1765 public void collapseAll() {
1766 fTimeGraphCtrl.collapseAll();
1767 adjustVerticalScrollBar();
1768 }
1769
1770 /**
1771 * Expands all entries of the viewer's tree, starting with the root.
1772 */
1773 public void expandAll() {
1774 fTimeGraphCtrl.expandAll();
1775 adjustVerticalScrollBar();
1776 }
1777
1778 /**
1779 * Get the number of expanded (visible) time graph entries. This includes
1780 * leafs and does not include filtered-out entries.
1781 *
1782 * @return The number of expanded (visible) time graph entries
1783 */
1784 public int getExpandedElementCount() {
1785 return fTimeGraphCtrl.getExpandedElementCount();
1786 }
1787
1788 /**
1789 * Get the expanded (visible) time graph entries. This includes leafs and
1790 * does not include filtered-out entries.
1791 *
1792 * @return The array of expanded (visible) time graph entries
1793 */
1794 public ITimeGraphEntry[] getExpandedElements() {
1795 return fTimeGraphCtrl.getExpandedElements();
1796 }
1797
1798 /**
1799 * Add a tree listener
1800 *
1801 * @param listener
1802 * The listener to add
1803 */
1804 public void addTreeListener(ITimeGraphTreeListener listener) {
1805 fTimeGraphCtrl.addTreeListener(listener);
1806 }
1807
1808 /**
1809 * Remove a tree listener
1810 *
1811 * @param listener
1812 * The listener to remove
1813 */
1814 public void removeTreeListener(ITimeGraphTreeListener listener) {
1815 fTimeGraphCtrl.removeTreeListener(listener);
1816 }
1817
1818 /**
1819 * Get the reset scale action.
1820 *
1821 * @return The Action object
1822 */
1823 public Action getResetScaleAction() {
1824 if (fResetScaleAction == null) {
1825 // resetScale
1826 fResetScaleAction = new Action() {
1827 @Override
1828 public void run() {
1829 resetStartFinishTime();
1830 }
1831 };
1832 fResetScaleAction.setText(Messages.TmfTimeGraphViewer_ResetScaleActionNameText);
1833 fResetScaleAction.setToolTipText(Messages.TmfTimeGraphViewer_ResetScaleActionToolTipText);
1834 fResetScaleAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_HOME_MENU));
1835 }
1836 return fResetScaleAction;
1837 }
1838
1839 /**
1840 * Get the show legend action.
1841 *
1842 * @return The Action object
1843 */
1844 public Action getShowLegendAction() {
1845 if (fShowLegendAction == null) {
1846 // showLegend
1847 fShowLegendAction = new Action() {
1848 @Override
1849 public void run() {
1850 showLegend();
1851 }
1852 };
1853 fShowLegendAction.setText(Messages.TmfTimeGraphViewer_LegendActionNameText);
1854 fShowLegendAction.setToolTipText(Messages.TmfTimeGraphViewer_LegendActionToolTipText);
1855 fShowLegendAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_SHOW_LEGEND));
1856 }
1857
1858 return fShowLegendAction;
1859 }
1860
1861 /**
1862 * Get the the next event action.
1863 *
1864 * @return The action object
1865 */
1866 public Action getNextEventAction() {
1867 if (fNextEventAction == null) {
1868 fNextEventAction = new Action() {
1869 @Override
1870 public void runWithEvent(Event event) {
1871 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
1872 selectNextEvent(extend);
1873 }
1874 };
1875
1876 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
1877 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
1878 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
1879 }
1880
1881 return fNextEventAction;
1882 }
1883
1884 /**
1885 * Get the previous event action.
1886 *
1887 * @return The Action object
1888 */
1889 public Action getPreviousEventAction() {
1890 if (fPrevEventAction == null) {
1891 fPrevEventAction = new Action() {
1892 @Override
1893 public void runWithEvent(Event event) {
1894 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
1895 selectPrevEvent(extend);
1896 }
1897 };
1898
1899 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1900 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1901 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
1902 }
1903
1904 return fPrevEventAction;
1905 }
1906
1907 /**
1908 * Get the next item action.
1909 *
1910 * @return The Action object
1911 */
1912 public Action getNextItemAction() {
1913 if (fNextItemAction == null) {
1914
1915 fNextItemAction = new Action() {
1916 @Override
1917 public void run() {
1918 selectNextItem();
1919 }
1920 };
1921 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
1922 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
1923 fNextItemAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_ITEM));
1924 }
1925 return fNextItemAction;
1926 }
1927
1928 /**
1929 * Get the previous item action.
1930 *
1931 * @return The Action object
1932 */
1933 public Action getPreviousItemAction() {
1934 if (fPreviousItemAction == null) {
1935
1936 fPreviousItemAction = new Action() {
1937 @Override
1938 public void run() {
1939 selectPrevItem();
1940 }
1941 };
1942 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
1943 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
1944 fPreviousItemAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_ITEM));
1945 }
1946 return fPreviousItemAction;
1947 }
1948
1949 /**
1950 * Get the zoom in action
1951 *
1952 * @return The Action object
1953 */
1954 public Action getZoomInAction() {
1955 if (fZoomInAction == null) {
1956 fZoomInAction = new Action() {
1957 @Override
1958 public void run() {
1959 zoomIn();
1960 }
1961 };
1962 fZoomInAction.setText(Messages.TmfTimeGraphViewer_ZoomInActionNameText);
1963 fZoomInAction.setToolTipText(Messages.TmfTimeGraphViewer_ZoomInActionToolTipText);
1964 fZoomInAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ZOOM_IN_MENU));
1965 }
1966 return fZoomInAction;
1967 }
1968
1969 /**
1970 * Get the zoom out action
1971 *
1972 * @return The Action object
1973 */
1974 public Action getZoomOutAction() {
1975 if (fZoomOutAction == null) {
1976 fZoomOutAction = new Action() {
1977 @Override
1978 public void run() {
1979 zoomOut();
1980 }
1981 };
1982 fZoomOutAction.setText(Messages.TmfTimeGraphViewer_ZoomOutActionNameText);
1983 fZoomOutAction.setToolTipText(Messages.TmfTimeGraphViewer_ZoomOutActionToolTipText);
1984 fZoomOutAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ZOOM_OUT_MENU));
1985 }
1986 return fZoomOutAction;
1987 }
1988
1989 /**
1990 * Get the hide arrows action
1991 *
1992 * @param dialogSettings
1993 * The dialog settings section where the state should be stored,
1994 * or null
1995 *
1996 * @return The Action object
1997 */
1998 public Action getHideArrowsAction(final IDialogSettings dialogSettings) {
1999 if (fHideArrowsAction == null) {
2000 fHideArrowsAction = new Action(Messages.TmfTimeGraphViewer_HideArrowsActionNameText, IAction.AS_CHECK_BOX) {
2001 @Override
2002 public void run() {
2003 boolean hideArrows = fHideArrowsAction.isChecked();
2004 fTimeGraphCtrl.hideArrows(hideArrows);
2005 refresh();
2006 if (dialogSettings != null) {
2007 dialogSettings.put(HIDE_ARROWS_KEY, hideArrows);
2008 }
2009 if (fFollowArrowFwdAction != null) {
2010 fFollowArrowFwdAction.setEnabled(!hideArrows);
2011 }
2012 if (fFollowArrowBwdAction != null) {
2013 fFollowArrowBwdAction.setEnabled(!hideArrows);
2014 }
2015 }
2016 };
2017 fHideArrowsAction.setToolTipText(Messages.TmfTimeGraphViewer_HideArrowsActionToolTipText);
2018 fHideArrowsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_HIDE_ARROWS));
2019 if (dialogSettings != null) {
2020 boolean hideArrows = dialogSettings.getBoolean(HIDE_ARROWS_KEY);
2021 fTimeGraphCtrl.hideArrows(hideArrows);
2022 fHideArrowsAction.setChecked(hideArrows);
2023 if (fFollowArrowFwdAction != null) {
2024 fFollowArrowFwdAction.setEnabled(!hideArrows);
2025 }
2026 if (fFollowArrowBwdAction != null) {
2027 fFollowArrowBwdAction.setEnabled(!hideArrows);
2028 }
2029 }
2030 }
2031 return fHideArrowsAction;
2032 }
2033
2034 /**
2035 * Get the follow arrow forward action.
2036 *
2037 * @return The Action object
2038 */
2039 public Action getFollowArrowFwdAction() {
2040 if (fFollowArrowFwdAction == null) {
2041 fFollowArrowFwdAction = new Action() {
2042 @Override
2043 public void runWithEvent(Event event) {
2044 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2045 fTimeGraphCtrl.followArrowFwd(extend);
2046 adjustVerticalScrollBar();
2047 }
2048 };
2049 fFollowArrowFwdAction.setText(Messages.TmfTimeGraphViewer_FollowArrowForwardActionNameText);
2050 fFollowArrowFwdAction.setToolTipText(Messages.TmfTimeGraphViewer_FollowArrowForwardActionToolTipText);
2051 fFollowArrowFwdAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FOLLOW_ARROW_FORWARD));
2052 if (fHideArrowsAction != null) {
2053 fFollowArrowFwdAction.setEnabled(!fHideArrowsAction.isChecked());
2054 }
2055 }
2056 return fFollowArrowFwdAction;
2057 }
2058
2059 /**
2060 * Get the follow arrow backward action.
2061 *
2062 * @return The Action object
2063 */
2064 public Action getFollowArrowBwdAction() {
2065 if (fFollowArrowBwdAction == null) {
2066 fFollowArrowBwdAction = new Action() {
2067 @Override
2068 public void runWithEvent(Event event) {
2069 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2070 fTimeGraphCtrl.followArrowBwd(extend);
2071 adjustVerticalScrollBar();
2072 }
2073 };
2074 fFollowArrowBwdAction.setText(Messages.TmfTimeGraphViewer_FollowArrowBackwardActionNameText);
2075 fFollowArrowBwdAction.setToolTipText(Messages.TmfTimeGraphViewer_FollowArrowBackwardActionToolTipText);
2076 fFollowArrowBwdAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FOLLOW_ARROW_BACKWARD));
2077 if (fHideArrowsAction != null) {
2078 fFollowArrowBwdAction.setEnabled(!fHideArrowsAction.isChecked());
2079 }
2080 }
2081 return fFollowArrowBwdAction;
2082 }
2083
2084 /**
2085 * Get the show filter dialog action.
2086 *
2087 * @return The Action object
2088 * @since 2.0
2089 */
2090 public ShowFilterDialogAction getShowFilterDialogAction() {
2091 if (fShowFilterDialogAction == null) {
2092 fShowFilterDialogAction = new ShowFilterDialogAction(this);
2093 }
2094 return fShowFilterDialogAction;
2095 }
2096
2097 /**
2098 * Get the toggle bookmark action.
2099 *
2100 * @return The Action object
2101 * @since 2.0
2102 */
2103 public Action getToggleBookmarkAction() {
2104 if (fToggleBookmarkAction == null) {
2105 fToggleBookmarkAction = new Action() {
2106 @Override
2107 public void runWithEvent(Event event) {
2108 IMarkerEvent selectedBookmark = getBookmarkAtSelection();
2109 if (selectedBookmark == null) {
2110 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2111 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2112 final AddBookmarkDialog dialog = new AddBookmarkDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), null);
2113 if (dialog.open() == Window.OK) {
2114 final String label = dialog.getValue();
2115 final RGBA rgba = dialog.getColorValue();
2116 IMarkerEvent bookmark = new MarkerEvent(null, time, duration, IMarkerEvent.BOOKMARKS, rgba, label, true);
2117 fBookmarks.add(bookmark);
2118 updateMarkerList();
2119 updateMarkerActions();
2120 getControl().redraw();
2121 fireBookmarkAdded(bookmark);
2122 }
2123 } else {
2124 fBookmarks.remove(selectedBookmark);
2125 updateMarkerList();
2126 updateMarkerActions();
2127 getControl().redraw();
2128 fireBookmarkRemoved(selectedBookmark);
2129 }
2130 }
2131 };
2132 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2133 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2134 fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
2135 }
2136 return fToggleBookmarkAction;
2137 }
2138
2139 /**
2140 * Get the next marker action.
2141 *
2142 * @return The Action object
2143 * @since 2.0
2144 */
2145 public Action getNextMarkerAction() {
2146 if (fNextMarkerAction == null) {
2147 fNextMarkerAction = new Action(Messages.TmfTimeGraphViewer_NextMarkerActionText, IAction.AS_DROP_DOWN_MENU) {
2148 @Override
2149 public void runWithEvent(Event event) {
2150 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2151 if (extend) {
2152 extendToNextMarker();
2153 } else {
2154 selectNextMarker();
2155 }
2156 }
2157 };
2158 fNextMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_NextMarkerActionText);
2159 fNextMarkerAction.setImageDescriptor(NEXT_BOOKMARK);
2160 fNextMarkerAction.setMenuCreator(new IMenuCreator () {
2161 Menu menu = null;
2162 @Override
2163 public void dispose() {
2164 if (menu != null) {
2165 menu.dispose();
2166 menu = null;
2167 }
2168 }
2169
2170 @Override
2171 public Menu getMenu(Control parent) {
2172 if (menu != null) {
2173 menu.dispose();
2174 }
2175 menu = new Menu(parent);
2176 for (String category : fMarkerCategories) {
2177 final Action action = new Action(category, IAction.AS_CHECK_BOX) {
2178 @Override
2179 public void runWithEvent(Event event) {
2180 if (isChecked()) {
2181 fSkippedMarkerCategories.remove(getText());
2182 } else {
2183 fSkippedMarkerCategories.add(getText());
2184 }
2185 updateMarkerActions();
2186 }
2187 };
2188 action.setEnabled(!fHiddenMarkerCategories.contains(category));
2189 action.setChecked(action.isEnabled() && !fSkippedMarkerCategories.contains(category));
2190 new ActionContributionItem(action).fill(menu, -1);
2191 }
2192 return menu;
2193 }
2194
2195 @Override
2196 public Menu getMenu(Menu parent) {
2197 return null;
2198 }
2199 });
2200 }
2201 return fNextMarkerAction;
2202 }
2203
2204 /**
2205 * Get the previous marker action.
2206 *
2207 * @return The Action object
2208 * @since 2.0
2209 */
2210 public Action getPreviousMarkerAction() {
2211 if (fPreviousMarkerAction == null) {
2212 fPreviousMarkerAction = new Action() {
2213 @Override
2214 public void runWithEvent(Event event) {
2215 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2216 if (extend) {
2217 extendToPrevMarker();
2218 } else {
2219 selectPrevMarker();
2220 }
2221 }
2222 };
2223 fPreviousMarkerAction.setText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
2224 fPreviousMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
2225 fPreviousMarkerAction.setImageDescriptor(PREVIOUS_BOOKMARK);
2226 }
2227 return fPreviousMarkerAction;
2228 }
2229
2230 /**
2231 * Get the show markers menu.
2232 *
2233 * @return The menu manager object
2234 * @since 2.0
2235 */
2236 public MenuManager getMarkersMenu() {
2237 if (fMarkersMenu == null) {
2238 fMarkersMenu = new MenuManager(Messages.TmfTimeGraphViewer_ShowMarkersMenuText);
2239 fMarkersMenu.setRemoveAllWhenShown(true);
2240 fMarkersMenu.addMenuListener(new IMenuListener() {
2241 @Override
2242 public void menuAboutToShow(IMenuManager manager) {
2243 for (String category : fMarkerCategories) {
2244 final Action action = new Action(category, IAction.AS_CHECK_BOX) {
2245 @Override
2246 public void runWithEvent(Event event) {
2247 setMarkerCategoryVisible(getText(), isChecked());
2248 }
2249 };
2250 action.setChecked(!fHiddenMarkerCategories.contains(category));
2251 manager.add(action);
2252 }
2253 }
2254 });
2255 }
2256 return fMarkersMenu;
2257 }
2258
2259 /**
2260 * Select the next marker that begins at or after the current selection
2261 * begin time. Markers that begin at the same time are ordered by end time.
2262 */
2263 private void selectNextMarker() {
2264 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2265 if (markers == null) {
2266 return;
2267 }
2268 for (IMarkerEvent marker : markers) {
2269 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2270 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2271 if ((marker.getTime() > time ||
2272 (marker.getTime() == time && marker.getDuration() > duration))
2273 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
2274 setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
2275 fTimeGraphCtrl.updateStatusLine();
2276 return;
2277 }
2278 }
2279 }
2280
2281 /**
2282 * Select the previous marker that begins at or before the current selection
2283 * begin time. Markers that begin at the same time are ordered by end time.
2284 */
2285 private void selectPrevMarker() {
2286 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2287 if (markers == null) {
2288 return;
2289 }
2290 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2291 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2292 for (int i = markers.size() - 1; i >= 0; i--) {
2293 IMarkerEvent marker = markers.get(i);
2294 if ((marker.getTime() < time ||
2295 (marker.getTime() == time && marker.getDuration() < duration))
2296 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
2297 setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), true);
2298 fTimeGraphCtrl.updateStatusLine();
2299 return;
2300 }
2301 }
2302 }
2303
2304 /**
2305 * Extend the selection to the closest next marker end time.
2306 */
2307 private void extendToNextMarker() {
2308 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2309 if (markers == null) {
2310 return;
2311 }
2312 IMarkerEvent nextMarker = null;
2313 for (IMarkerEvent marker : markers) {
2314 if (marker.getTime() + marker.getDuration() > fSelectionEnd
2315 && !fSkippedMarkerCategories.contains(marker.getCategory())
2316 && (nextMarker == null || marker.getTime() + marker.getDuration() < nextMarker.getTime() + nextMarker.getDuration())) {
2317 nextMarker = marker;
2318 }
2319 }
2320 if (nextMarker != null) {
2321 setSelectionRangeNotify(fSelectionBegin, nextMarker.getTime() + nextMarker.getDuration(), true);
2322 fTimeGraphCtrl.updateStatusLine();
2323 }
2324 }
2325
2326 /**
2327 * Extend the selection to the closest previous marker start time.
2328 */
2329 private void extendToPrevMarker() {
2330 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2331 if (markers == null) {
2332 return;
2333 }
2334 for (int i = markers.size() - 1; i >= 0; i--) {
2335 IMarkerEvent marker = markers.get(i);
2336 if (marker.getTime() < fSelectionEnd
2337 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
2338 setSelectionRangeNotify(fSelectionBegin, marker.getTime(), true);
2339 fTimeGraphCtrl.updateStatusLine();
2340 return;
2341 }
2342 }
2343 }
2344
2345 private IMarkerEvent getBookmarkAtSelection() {
2346 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2347 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2348 for (IMarkerEvent bookmark : fBookmarks) {
2349 if (bookmark.getTime() == time && bookmark.getDuration() == duration) {
2350 return bookmark;
2351 }
2352 }
2353 return null;
2354 }
2355
2356 private void updateMarkerActions() {
2357 boolean enabled = fTime0Bound != SWT.DEFAULT || fTime1Bound != SWT.DEFAULT;
2358 if (fToggleBookmarkAction != null) {
2359 if (getBookmarkAtSelection() != null) {
2360 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
2361 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
2362 fToggleBookmarkAction.setImageDescriptor(REMOVE_BOOKMARK);
2363 } else {
2364 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2365 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2366 fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
2367 }
2368 fToggleBookmarkAction.setEnabled(enabled);
2369 }
2370 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2371 if (markers == null) {
2372 markers = Collections.emptyList();
2373 }
2374 if (fPreviousMarkerAction != null) {
2375 fPreviousMarkerAction.setEnabled(enabled && !markers.isEmpty());
2376 }
2377 if (fNextMarkerAction != null) {
2378 fNextMarkerAction.setEnabled(enabled && !markers.isEmpty());
2379 }
2380 }
2381
2382 private void updateMarkerList() {
2383 List<IMarkerEvent> markers = new ArrayList<>();
2384 for (IMarkerEvent marker : fMarkers) {
2385 if (!fHiddenMarkerCategories.contains(marker.getCategory())) {
2386 markers.add(marker);
2387 }
2388 }
2389 if (!fHiddenMarkerCategories.contains(IMarkerEvent.BOOKMARKS)) {
2390 markers.addAll(fBookmarks);
2391 }
2392 Collections.sort(markers, new MarkerComparator());
2393 fTimeGraphCtrl.setMarkers(markers);
2394 fMarkerAxisCtrl.setMarkers(markers);
2395 }
2396
2397 private void adjustHorizontalScrollBar() {
2398 long time0 = getTime0();
2399 long time1 = getTime1();
2400 long timeMin = getMinTime();
2401 long timeMax = getMaxTime();
2402 long delta = timeMax - timeMin;
2403 int timePos = 0;
2404 int thumb = H_SCROLLBAR_MAX;
2405 if (delta != 0) {
2406 // Thumb size (page size)
2407 thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta)));
2408 // At the beginning of visible window
2409 timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta));
2410 }
2411 fHorizontalScrollBar.setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, Math.max(1, thumb / 2), Math.max(2, thumb));
2412 }
2413
2414 private void adjustVerticalScrollBar() {
2415 int topIndex = fTimeGraphCtrl.getTopIndex();
2416 int countPerPage = fTimeGraphCtrl.countPerPage();
2417 int expandedElementCount = fTimeGraphCtrl.getExpandedElementCount();
2418 if (topIndex + countPerPage > expandedElementCount) {
2419 fTimeGraphCtrl.setTopIndex(Math.max(0, expandedElementCount - countPerPage));
2420 }
2421
2422 int selection = fTimeGraphCtrl.getTopIndex();
2423 int min = 0;
2424 int max = Math.max(1, expandedElementCount - 1);
2425 int thumb = Math.min(max, Math.max(1, countPerPage - 1));
2426 int increment = 1;
2427 int pageIncrement = Math.max(1, countPerPage);
2428 fVerticalScrollBar.setValues(selection, min, max, thumb, increment, pageIncrement);
2429 }
2430
2431 /**
2432 * @param listener
2433 * a {@link MenuDetectListener}
2434 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener)
2435 */
2436 public void addTimeGraphEntryMenuListener(MenuDetectListener listener) {
2437 fTimeGraphCtrl.addTimeGraphEntryMenuListener(listener);
2438 }
2439
2440 /**
2441 * @param listener
2442 * a {@link MenuDetectListener}
2443 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener)
2444 */
2445 public void removeTimeGraphEntryMenuListener(MenuDetectListener listener) {
2446 fTimeGraphCtrl.removeTimeGraphEntryMenuListener(listener);
2447 }
2448
2449 /**
2450 * @param listener
2451 * a {@link MenuDetectListener}
2452 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener)
2453 */
2454 public void addTimeEventMenuListener(MenuDetectListener listener) {
2455 fTimeGraphCtrl.addTimeEventMenuListener(listener);
2456 }
2457
2458 /**
2459 * @param listener
2460 * a {@link MenuDetectListener}
2461 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener)
2462 */
2463 public void removeTimeEventMenuListener(MenuDetectListener listener) {
2464 fTimeGraphCtrl.removeTimeEventMenuListener(listener);
2465 }
2466
2467 /**
2468 * @param filter
2469 * The filter object to be attached to the view
2470 */
2471 public void addFilter(@NonNull ViewerFilter filter) {
2472 fTimeGraphCtrl.addFilter(filter);
2473 refresh();
2474 }
2475
2476 /**
2477 * @param filter
2478 * The filter object to be attached to the view
2479 */
2480 public void removeFilter(@NonNull ViewerFilter filter) {
2481 fTimeGraphCtrl.removeFilter(filter);
2482 refresh();
2483 }
2484
2485 /**
2486 * Returns this viewer's filters.
2487 *
2488 * @return an array of viewer filters
2489 * @since 2.0
2490 */
2491 public @NonNull ViewerFilter[] getFilters() {
2492 return fTimeGraphCtrl.getFilters();
2493 }
2494
2495 /**
2496 * Sets the filters, replacing any previous filters, and triggers
2497 * refiltering of the elements.
2498 *
2499 * @param filters
2500 * an array of viewer filters, or null
2501 * @since 2.0
2502 */
2503 public void setFilters(@NonNull ViewerFilter[] filters) {
2504 fTimeGraphCtrl.setFilters(filters);
2505 refresh();
2506 }
2507
2508 /**
2509 * Return the time alignment information
2510 *
2511 * @return the time alignment information
2512 *
2513 * @see ITmfTimeAligned
2514 *
2515 * @since 1.0
2516 */
2517 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
2518 return fTimeGraphCtrl.getTimeViewAlignmentInfo();
2519 }
2520
2521 /**
2522 * Return the available width for the time-axis.
2523 *
2524 * @see ITmfTimeAligned
2525 *
2526 * @param requestedOffset
2527 * the requested offset
2528 * @return the available width for the time-axis
2529 *
2530 * @since 1.0
2531 */
2532 public int getAvailableWidth(int requestedOffset) {
2533 int totalWidth = fTimeAlignedComposite.getSize().x;
2534 return Math.min(totalWidth, Math.max(0, totalWidth - requestedOffset));
2535 }
2536
2537 /**
2538 * Perform the alignment operation.
2539 *
2540 * @param offset
2541 * the alignment offset
2542 * @param width
2543 * the alignment width
2544 *
2545 * @see ITmfTimeAligned
2546 *
2547 * @since 1.0
2548 */
2549 public void performAlign(int offset, int width) {
2550 fTimeGraphCtrl.performAlign(offset);
2551 int alignmentWidth = width;
2552 int size = fTimeAlignedComposite.getSize().x;
2553 GridLayout layout = (GridLayout) fTimeAlignedComposite.getLayout();
2554 int marginSize = size - alignmentWidth - offset;
2555 layout.marginRight = Math.max(0, marginSize);
2556 fTimeAlignedComposite.layout();
2557 }
2558
2559 }
This page took 0.102991 seconds and 5 git commands to generate.