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