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