tmf : Add search dialog to timegraph views
[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
323 * @since 2.0
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
333 * @since 2.0
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
343 * @since 2.0
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) {
3bd20aa6 551 if ((e.character == '+' || e.character == '=') && ((e.stateMask & SWT.CTRL) == 0)) {
dc5ed8a6 552 zoomIn();
3bd20aa6 553 } else if (e.character == '-' && ((e.stateMask & SWT.CTRL) == 0)) {
dc5ed8a6 554 zoomOut();
4aa2593c
PT
555 } else if (e.keyCode == '.') {
556 boolean extend = (e.stateMask & SWT.SHIFT) != 0;
557 if (extend) {
558 extendToNextMarker();
559 } else {
560 selectNextMarker();
561 }
562 } else if (e.keyCode == ',') {
563 boolean extend = (e.stateMask & SWT.SHIFT) != 0;
564 if (extend) {
565 extendToPrevMarker();
566 } else {
567 selectPrevMarker();
568 }
dc5ed8a6 569 }
837a2f8c
PT
570 adjustVerticalScrollBar();
571 }
572 });
573
dc4fa715
PT
574 fMarkerAxisCtrl = createTimeGraphMarkerAxis(fTimeAlignedComposite, fColorScheme, this);
575 fMarkerAxisCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
f0a9cee1 576 fMarkerAxisCtrl.addMarkerAxisListener(this);
dc4fa715
PT
577 fMarkerAxisCtrl.addMouseWheelListener(new MouseWheelListener() {
578 @Override
579 public void mouseScrolled(MouseEvent e) {
93cfc823
PT
580 if (e.count == 0) {
581 return;
582 }
494c9b22
PT
583 if ((e.stateMask & SWT.CTRL) != 0) {
584 fTimeGraphCtrl.zoom(e.count > 0);
585 } else {
586 fTimeGraphCtrl.horizontalScroll(e.count > 0);
587 }
dc4fa715
PT
588 }
589 });
590
d2e4afa7
MAL
591 fVerticalScrollBar = new Slider(fDataViewer, SWT.VERTICAL | SWT.NO_FOCUS);
592 fVerticalScrollBar.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false, true, 1, 1));
593 fVerticalScrollBar.addSelectionListener(new SelectionAdapter() {
594 @Override
595 public void widgetSelected(SelectionEvent e) {
596 setTopIndex(fVerticalScrollBar.getSelection());
597 }
598 });
599
b698ec63
PT
600 fHorizontalScrollBar = new Slider(fDataViewer, SWT.HORIZONTAL | SWT.NO_FOCUS);
601 fHorizontalScrollBar.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
602 fHorizontalScrollBar.addListener(SWT.MouseWheel, new Listener() {
603 @Override
604 public void handleEvent(Event event) {
93cfc823
PT
605 // don't handle the immediately following SWT.Selection event
606 event.doit = false;
607 if (event.count == 0) {
608 return;
609 }
494c9b22
PT
610 if ((event.stateMask & SWT.CTRL) != 0) {
611 fTimeGraphCtrl.zoom(event.count > 0);
b698ec63 612 } else {
494c9b22 613 fTimeGraphCtrl.horizontalScroll(event.count > 0);
b698ec63 614 }
b698ec63
PT
615 }
616 });
617 fHorizontalScrollBar.addListener(SWT.Selection, new Listener() {
618 @Override
619 public void handleEvent(Event event) {
620 int start = fHorizontalScrollBar.getSelection();
621 long time0 = getTime0();
622 long time1 = getTime1();
623 long timeMin = getMinTime();
624 long timeMax = getMaxTime();
625 long delta = timeMax - timeMin;
626
627 long range = time1 - time0;
628 time0 = timeMin + Math.round(delta * ((double) start / H_SCROLLBAR_MAX));
629 time1 = time0 + range;
630
10ad9fa6 631 setStartFinishTimeNotify(time0, time1);
b698ec63
PT
632 }
633 });
634
f1fae91f 635 Composite filler = new Composite(fDataViewer, SWT.NONE);
837a2f8c 636 GridData gd = new GridData(SWT.DEFAULT, SWT.DEFAULT, false, false);
b698ec63 637 gd.heightHint = fHorizontalScrollBar.getSize().y;
837a2f8c
PT
638 filler.setLayoutData(gd);
639 filler.setLayout(new FillLayout());
640
f1fae91f 641 fTimeGraphCtrl.addControlListener(new ControlAdapter() {
837a2f8c
PT
642 @Override
643 public void controlResized(ControlEvent event) {
644 resizeControls();
645 }
646 });
647 resizeControls();
f1fae91f 648 fDataViewer.update();
b698ec63 649 adjustHorizontalScrollBar();
837a2f8c 650 adjustVerticalScrollBar();
25033fef
PT
651
652 fDataViewer.addDisposeListener((e) -> {
653 saveOptions();
654 fColorScheme.dispose();
655 });
656
f1fae91f 657 return fDataViewer;
837a2f8c
PT
658 }
659
660 /**
25033fef 661 * Dispose the time graph viewer.
837a2f8c
PT
662 */
663 public void dispose() {
f1fae91f 664 fDataViewer.dispose();
837a2f8c
PT
665 }
666
96d00a83 667 /**
a0a88f65
AM
668 * Create a new time graph control.
669 *
670 * @param parent
671 * The parent composite
672 * @param colors
673 * The color scheme
674 * @return The new TimeGraphControl
96d00a83 675 */
a0a88f65
AM
676 protected TimeGraphControl createTimeGraphControl(Composite parent,
677 TimeGraphColorScheme colors) {
96d00a83 678 return new TimeGraphControl(parent, colors);
837a2f8c
PT
679 }
680
dc4fa715
PT
681 /**
682 * Create a new time graph marker axis.
683 *
684 * @param parent
685 * The parent composite object
686 * @param colorScheme
687 * The color scheme to use
688 * @param timeProvider
689 * The time data provider
690 * @return The new TimeGraphMarkerAxis
691 * @since 2.0
692 */
693 protected TimeGraphMarkerAxis createTimeGraphMarkerAxis(Composite parent,
694 @NonNull TimeGraphColorScheme colorScheme, @NonNull ITimeDataProvider timeProvider) {
695 return new TimeGraphMarkerAxis(parent, colorScheme, timeProvider);
696 }
697
837a2f8c
PT
698 /**
699 * Resize the controls
700 */
701 public void resizeControls() {
f1fae91f 702 Rectangle r = fDataViewer.getClientArea();
837a2f8c
PT
703 if (r.isEmpty()) {
704 return;
705 }
706
707 int width = r.width;
f1fae91f
PT
708 if (fNameWidth > width - fMinNameWidth) {
709 fNameWidth = width - fMinNameWidth;
837a2f8c 710 }
f1fae91f
PT
711 if (fNameWidth < fMinNameWidth) {
712 fNameWidth = fMinNameWidth;
837a2f8c 713 }
b698ec63 714 adjustHorizontalScrollBar();
837a2f8c
PT
715 adjustVerticalScrollBar();
716 }
717
718 /**
50d36521
PT
719 * Recalculate the time bounds based on the time graph entries,
720 * if the user-specified bound is set to SWT.DEFAULT.
837a2f8c 721 *
50d36521
PT
722 * @param entries
723 * The root time graph entries in the model
837a2f8c 724 */
50d36521
PT
725 public void setTimeRange(ITimeGraphEntry entries[]) {
726 fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime);
727 fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime);
728 if (fBeginTime != SWT.DEFAULT && fEndTime != SWT.DEFAULT) {
729 return;
730 }
731 if (entries == null || entries.length == 0) {
732 return;
733 }
734 if (fTime0Bound == SWT.DEFAULT) {
735 fTime0Bound = Long.MAX_VALUE;
736 }
737 if (fTime1Bound == SWT.DEFAULT) {
738 fTime1Bound = Long.MIN_VALUE;
739 }
740 for (ITimeGraphEntry entry : entries) {
741 setTimeRange(entry);
742 }
743 }
744
745 private void setTimeRange(ITimeGraphEntry entry) {
746 if (fBeginTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getStartTime() != SWT.DEFAULT) {
747 fTime0Bound = Math.min(entry.getStartTime(), fTime0Bound);
748 }
749 if (fEndTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getEndTime() != SWT.DEFAULT) {
750 fTime1Bound = Math.max(entry.getEndTime(), fTime1Bound);
751 }
752 if (entry.hasChildren()) {
753 for (ITimeGraphEntry child : entry.getChildren()) {
754 setTimeRange(child);
837a2f8c
PT
755 }
756 }
50d36521 757 }
837a2f8c 758
50d36521
PT
759 /**
760 * Set the time bounds to the provided values.
761 *
762 * @param beginTime
763 * The bounds begin time, or SWT.DEFAULT to use the input bounds
764 * @param endTime
765 * The bounds end time, or SWT.DEFAULT to use the input bounds
766 */
767 public void setTimeBounds(long beginTime, long endTime) {
768 fBeginTime = beginTime;
769 fEndTime = endTime;
770 fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime);
771 fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime);
772 if (fTime0Bound > fTime1Bound) {
773 // only possible if both are not default
774 fBeginTime = endTime;
775 fEndTime = beginTime;
776 fTime0Bound = fBeginTime;
777 fTime1Bound = fEndTime;
837a2f8c 778 }
50d36521 779 adjustHorizontalScrollBar();
837a2f8c
PT
780 }
781
782 /**
50d36521 783 * Recalculate the current time window when bounds have changed.
837a2f8c
PT
784 */
785 public void setTimeBounds() {
f1fae91f
PT
786 if (!fTimeRangeFixed) {
787 fTime0 = fTime0Bound;
788 fTime1 = fTime1Bound;
837a2f8c 789 }
407bfdd5
PT
790 fTime0 = Math.max(fTime0Bound, Math.min(fTime0, fTime1Bound));
791 fTime1 = Math.max(fTime0Bound, Math.min(fTime1, fTime1Bound));
f1fae91f
PT
792 if (fTime1 - fTime0 < fMinTimeInterval) {
793 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
837a2f8c
PT
794 }
795 }
796
837a2f8c
PT
797 /**
798 * @param traces
799 */
800 private void refreshAllData(ITimeGraphEntry[] traces) {
801 setTimeBounds();
0fcf3b09
PT
802 if (fSelectionBegin < fBeginTime) {
803 fSelectionBegin = fBeginTime;
804 } else if (fSelectionBegin > fEndTime) {
805 fSelectionBegin = fEndTime;
806 }
807 if (fSelectionEnd < fBeginTime) {
808 fSelectionEnd = fBeginTime;
809 } else if (fSelectionEnd > fEndTime) {
810 fSelectionEnd = fEndTime;
837a2f8c 811 }
f1fae91f
PT
812 fTimeGraphCtrl.refreshData(traces);
813 fTimeScaleCtrl.redraw();
dc4fa715 814 fMarkerAxisCtrl.redraw();
f72cd563 815 updateMarkerActions();
837a2f8c
PT
816 adjustVerticalScrollBar();
817 }
818
819 /**
820 * Callback for when this view is focused
821 */
822 public void setFocus() {
f1fae91f
PT
823 if (null != fTimeGraphCtrl) {
824 fTimeGraphCtrl.setFocus();
837a2f8c
PT
825 }
826 }
827
828 /**
829 * Get the current focus status of this view.
830 *
831 * @return If the view is currently focused, or not
832 */
833 public boolean isInFocus() {
f1fae91f 834 return fTimeGraphCtrl.isInFocus();
837a2f8c
PT
835 }
836
837 /**
838 * Get the view's current selection
839 *
840 * @return The entry that is selected
841 */
842 public ITimeGraphEntry getSelection() {
f1fae91f 843 return fTimeGraphCtrl.getSelectedTrace();
837a2f8c
PT
844 }
845
846 /**
847 * Get the index of the current selection
848 *
849 * @return The index
850 */
851 public int getSelectionIndex() {
f1fae91f 852 return fTimeGraphCtrl.getSelectedIndex();
837a2f8c
PT
853 }
854
855 @Override
856 public long getTime0() {
f1fae91f 857 return fTime0;
837a2f8c
PT
858 }
859
860 @Override
861 public long getTime1() {
f1fae91f 862 return fTime1;
837a2f8c
PT
863 }
864
865 @Override
866 public long getMinTimeInterval() {
f1fae91f 867 return fMinTimeInterval;
837a2f8c
PT
868 }
869
870 @Override
871 public int getNameSpace() {
f1fae91f 872 return fNameWidth;
837a2f8c
PT
873 }
874
875 @Override
876 public void setNameSpace(int width) {
f1fae91f
PT
877 fNameWidth = width;
878 int w = fTimeGraphCtrl.getClientArea().width;
879 if (fNameWidth > w - MIN_NAME_WIDTH) {
880 fNameWidth = w - MIN_NAME_WIDTH;
837a2f8c 881 }
f1fae91f
PT
882 if (fNameWidth < MIN_NAME_WIDTH) {
883 fNameWidth = MIN_NAME_WIDTH;
837a2f8c 884 }
f1fae91f
PT
885 fTimeGraphCtrl.redraw();
886 fTimeScaleCtrl.redraw();
dc4fa715
PT
887 fMarkerAxisCtrl.redraw();
888 /* force update the controls to keep them aligned */
889 fTimeScaleCtrl.update();
890 fMarkerAxisCtrl.update();
891 fTimeGraphCtrl.update();
837a2f8c
PT
892 }
893
894 @Override
895 public int getTimeSpace() {
f1fae91f
PT
896 int w = fTimeGraphCtrl.getClientArea().width;
897 return w - fNameWidth;
837a2f8c
PT
898 }
899
837a2f8c
PT
900 @Override
901 public long getBeginTime() {
f1fae91f 902 return fBeginTime;
837a2f8c
PT
903 }
904
905 @Override
906 public long getEndTime() {
f1fae91f 907 return fEndTime;
837a2f8c
PT
908 }
909
910 @Override
911 public long getMaxTime() {
f1fae91f 912 return fTime1Bound;
837a2f8c
PT
913 }
914
915 @Override
916 public long getMinTime() {
f1fae91f 917 return fTime0Bound;
837a2f8c
PT
918 }
919
0fcf3b09
PT
920 @Override
921 public long getSelectionBegin() {
922 return fSelectionBegin;
923 }
924
0fcf3b09
PT
925 @Override
926 public long getSelectionEnd() {
927 return fSelectionEnd;
928 }
929
837a2f8c
PT
930 @Override
931 public void setStartFinishTimeNotify(long time0, long time1) {
88de10c6 932 setStartFinishTimeInt(time0, time1);
10ad9fa6 933 notifyRangeListeners();
837a2f8c
PT
934 }
935
837a2f8c
PT
936 @Override
937 public void notifyStartFinishTime() {
10ad9fa6 938 notifyRangeListeners();
837a2f8c
PT
939 }
940
837a2f8c
PT
941 @Override
942 public void setStartFinishTime(long time0, long time1) {
88de10c6
PT
943 /* if there is a pending time range, ignore this one */
944 if (fListenerNotifier != null && fListenerNotifier.hasTimeRangeUpdated()) {
945 return;
946 }
947 setStartFinishTimeInt(time0, time1);
45f63682 948 updateExtSynchValues();
88de10c6
PT
949 }
950
951 private void setStartFinishTimeInt(long time0, long time1) {
f1fae91f
PT
952 fTime0 = time0;
953 if (fTime0 < fTime0Bound) {
954 fTime0 = fTime0Bound;
837a2f8c 955 }
f1fae91f
PT
956 if (fTime0 > fTime1Bound) {
957 fTime0 = fTime1Bound;
837a2f8c 958 }
f1fae91f
PT
959 fTime1 = time1;
960 if (fTime1 < fTime0Bound) {
961 fTime1 = fTime0Bound;
837a2f8c 962 }
f1fae91f
PT
963 if (fTime1 > fTime1Bound) {
964 fTime1 = fTime1Bound;
837a2f8c 965 }
f1fae91f
PT
966 if (fTime1 - fTime0 < fMinTimeInterval) {
967 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
837a2f8c 968 }
f1fae91f 969 fTimeRangeFixed = true;
b698ec63 970 adjustHorizontalScrollBar();
f1fae91f
PT
971 fTimeGraphCtrl.redraw();
972 fTimeScaleCtrl.redraw();
dc4fa715
PT
973 fMarkerAxisCtrl.redraw();
974 /* force update the controls to keep them aligned */
975 fTimeScaleCtrl.update();
976 fMarkerAxisCtrl.update();
977 fTimeGraphCtrl.update();
837a2f8c
PT
978 }
979
837a2f8c
PT
980 @Override
981 public void resetStartFinishTime() {
88de10c6 982 setStartFinishTimeNotify(fTime0Bound, fTime1Bound);
f1fae91f 983 fTimeRangeFixed = false;
837a2f8c
PT
984 }
985
986 @Override
987 public void setSelectedTimeNotify(long time, boolean ensureVisible) {
988 setSelectedTimeInt(time, ensureVisible, true);
989 }
990
991 @Override
992 public void setSelectedTime(long time, boolean ensureVisible) {
88de10c6
PT
993 /* if there is a pending time selection, ignore this one */
994 if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) {
995 return;
996 }
837a2f8c
PT
997 setSelectedTimeInt(time, ensureVisible, false);
998 }
999
84c8aef7
PT
1000 private void setSelectedTimeInt(long time, boolean ensureVisible, boolean doNotify) {
1001 setSelectionRangeInt(time, time, ensureVisible, doNotify);
1002 }
1003
1004 /**
1005 * @since 2.0
1006 */
0fcf3b09 1007 @Override
84c8aef7
PT
1008 public void setSelectionRangeNotify(long beginTime, long endTime, boolean ensureVisible) {
1009 setSelectionRangeInt(beginTime, endTime, ensureVisible, true);
0fcf3b09
PT
1010 }
1011
84c8aef7
PT
1012 /**
1013 * @since 2.0
1014 */
0fcf3b09 1015 @Override
84c8aef7 1016 public void setSelectionRange(long beginTime, long endTime, boolean ensureVisible) {
88de10c6
PT
1017 /* if there is a pending time selection, ignore this one */
1018 if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) {
1019 return;
1020 }
84c8aef7 1021 setSelectionRangeInt(beginTime, endTime, ensureVisible, false);
0fcf3b09
PT
1022 }
1023
84c8aef7 1024 private void setSelectionRangeInt(long beginTime, long endTime, boolean ensureVisible, boolean doNotify) {
f1fae91f
PT
1025 long time0 = fTime0;
1026 long time1 = fTime1;
84c8aef7
PT
1027 long selectionBegin = fSelectionBegin;
1028 long selectionEnd = fSelectionEnd;
1029 fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime));
1030 fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime));
1031 boolean changed = (selectionBegin != fSelectionBegin || selectionEnd != fSelectionEnd);
1032
837a2f8c 1033 if (ensureVisible) {
84c8aef7 1034 ensureVisible(selectionBegin != fSelectionBegin ? fSelectionBegin : fSelectionEnd);
837a2f8c 1035 }
84c8aef7 1036
f1fae91f
PT
1037 fTimeGraphCtrl.redraw();
1038 fTimeScaleCtrl.redraw();
dc4fa715 1039 fMarkerAxisCtrl.redraw();
f72cd563 1040 updateMarkerActions();
837a2f8c 1041
37e1a265 1042 if ((time0 != fTime0) || (time1 != fTime1)) {
10ad9fa6 1043 notifyRangeListeners();
837a2f8c
PT
1044 }
1045
84c8aef7 1046 if (doNotify && changed) {
10ad9fa6 1047 notifyTimeListeners();
837a2f8c
PT
1048 }
1049 }
1050
33fa1fc7
PT
1051 private void ensureVisible(long time) {
1052 long timeMid = (fTime1 - fTime0) / 2;
1053 if (time < fTime0) {
1054 long dt = fTime0 - time + timeMid;
1055 fTime0 -= dt;
1056 fTime1 -= dt;
1057 } else if (time > fTime1) {
1058 long dt = time - fTime1 + timeMid;
1059 fTime0 += dt;
1060 fTime1 += dt;
1061 }
1062 if (fTime0 < fTime0Bound) {
1063 fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0));
1064 fTime0 = fTime0Bound;
1065 } else if (fTime1 > fTime1Bound) {
1066 fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound));
1067 fTime1 = fTime1Bound;
1068 }
1069 if (fTime1 - fTime0 < fMinTimeInterval) {
1070 fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval);
1071 }
1072 adjustHorizontalScrollBar();
1073 }
1074
837a2f8c
PT
1075 @Override
1076 public void widgetDefaultSelected(SelectionEvent e) {
f1fae91f
PT
1077 if (fSelectedEntry != getSelection()) {
1078 fSelectedEntry = getSelection();
10ad9fa6 1079 notifySelectionListeners();
837a2f8c
PT
1080 }
1081 }
1082
1083 @Override
1084 public void widgetSelected(SelectionEvent e) {
f1fae91f
PT
1085 if (fSelectedEntry != getSelection()) {
1086 fSelectedEntry = getSelection();
10ad9fa6 1087 notifySelectionListeners();
837a2f8c
PT
1088 }
1089 }
1090
1091 /**
1092 * Callback for when the next event is selected
33fa1fc7
PT
1093 *
1094 * @param extend
1095 * true to extend selection range, false for single selection
1096 * @since 1.0
837a2f8c 1097 */
33fa1fc7
PT
1098 public void selectNextEvent(boolean extend) {
1099 fTimeGraphCtrl.selectNextEvent(extend);
837a2f8c
PT
1100 adjustVerticalScrollBar();
1101 }
1102
1103 /**
1104 * Callback for when the previous event is selected
33fa1fc7
PT
1105 *
1106 * @param extend
1107 * true to extend selection range, false for single selection
1108 * @since 1.0
837a2f8c 1109 */
33fa1fc7
PT
1110 public void selectPrevEvent(boolean extend) {
1111 fTimeGraphCtrl.selectPrevEvent(extend);
837a2f8c
PT
1112 adjustVerticalScrollBar();
1113 }
1114
1115 /**
1116 * Callback for when the next item is selected
1117 */
1118 public void selectNextItem() {
f1fae91f 1119 fTimeGraphCtrl.selectNextTrace();
837a2f8c
PT
1120 adjustVerticalScrollBar();
1121 }
1122
1123 /**
1124 * Callback for when the previous item is selected
1125 */
1126 public void selectPrevItem() {
f1fae91f 1127 fTimeGraphCtrl.selectPrevTrace();
837a2f8c
PT
1128 adjustVerticalScrollBar();
1129 }
1130
1131 /**
1132 * Callback for the show legend action
1133 */
1134 public void showLegend() {
f1fae91f 1135 if (fDataViewer == null || fDataViewer.isDisposed()) {
837a2f8c
PT
1136 return;
1137 }
1138
f1fae91f 1139 TimeGraphLegend.open(fDataViewer.getShell(), fTimeGraphProvider);
837a2f8c
PT
1140 }
1141
1142 /**
1143 * Callback for the Zoom In action
1144 */
1145 public void zoomIn() {
f1fae91f 1146 fTimeGraphCtrl.zoomIn();
837a2f8c
PT
1147 }
1148
1149 /**
1150 * Callback for the Zoom Out action
1151 */
1152 public void zoomOut() {
f1fae91f 1153 fTimeGraphCtrl.zoomOut();
837a2f8c
PT
1154 }
1155
1156 private String getPreferenceString(String string) {
1157 return getViewTypeStr() + "." + string; //$NON-NLS-1$
1158 }
1159
1160 /**
1161 * Add a selection listener
1162 *
1163 * @param listener
1164 * The listener to add
1165 */
1166 public void addSelectionListener(ITimeGraphSelectionListener listener) {
1167 fSelectionListeners.add(listener);
1168 }
1169
1170 /**
1171 * Remove a selection listener
1172 *
1173 * @param listener
1174 * The listener to remove
1175 */
1176 public void removeSelectionListener(ITimeGraphSelectionListener listener) {
1177 fSelectionListeners.remove(listener);
1178 }
1179
10ad9fa6 1180 private void notifySelectionListeners() {
88de10c6
PT
1181 if (fListenerNotifier == null) {
1182 fListenerNotifier = new ListenerNotifier();
1183 fListenerNotifier.start();
10ad9fa6 1184 }
88de10c6 1185 fListenerNotifier.selectionChanged();
10ad9fa6
PT
1186 }
1187
1188 private void fireSelectionChanged(ITimeGraphEntry selection) {
837a2f8c
PT
1189 TimeGraphSelectionEvent event = new TimeGraphSelectionEvent(this, selection);
1190
1191 for (ITimeGraphSelectionListener listener : fSelectionListeners) {
1192 listener.selectionChanged(event);
1193 }
1194 }
1195
1196 /**
1197 * Add a time listener
1198 *
1199 * @param listener
1200 * The listener to add
1201 */
1202 public void addTimeListener(ITimeGraphTimeListener listener) {
1203 fTimeListeners.add(listener);
1204 }
1205
1206 /**
1207 * Remove a time listener
1208 *
1209 * @param listener
1210 * The listener to remove
1211 */
1212 public void removeTimeListener(ITimeGraphTimeListener listener) {
1213 fTimeListeners.remove(listener);
1214 }
1215
10ad9fa6 1216 private void notifyTimeListeners() {
88de10c6
PT
1217 if (fListenerNotifier == null) {
1218 fListenerNotifier = new ListenerNotifier();
1219 fListenerNotifier.start();
10ad9fa6 1220 }
88de10c6 1221 fListenerNotifier.timeSelected();
10ad9fa6
PT
1222 }
1223
1224 private void fireTimeSelected(long startTime, long endTime) {
0fcf3b09 1225 TimeGraphTimeEvent event = new TimeGraphTimeEvent(this, startTime, endTime);
837a2f8c
PT
1226
1227 for (ITimeGraphTimeListener listener : fTimeListeners) {
1228 listener.timeSelected(event);
1229 }
1230 }
1231
1232 /**
1233 * Add a range listener
1234 *
1235 * @param listener
1236 * The listener to add
1237 */
1238 public void addRangeListener(ITimeGraphRangeListener listener) {
1239 fRangeListeners.add(listener);
1240 }
1241
1242 /**
1243 * Remove a range listener
1244 *
1245 * @param listener
1246 * The listener to remove
1247 */
1248 public void removeRangeListener(ITimeGraphRangeListener listener) {
1249 fRangeListeners.remove(listener);
1250 }
1251
10ad9fa6 1252 private void notifyRangeListeners() {
88de10c6
PT
1253 if (fListenerNotifier == null) {
1254 fListenerNotifier = new ListenerNotifier();
1255 fListenerNotifier.start();
10ad9fa6 1256 }
88de10c6 1257 fListenerNotifier.timeRangeUpdated();
10ad9fa6
PT
1258 }
1259
1260 private void fireTimeRangeUpdated(long startTime, long endTime) {
837a2f8c 1261 // Check if the time has actually changed from last notification
f1fae91f 1262 if (startTime != fTime0ExtSynch || endTime != fTime1ExtSynch) {
837a2f8c
PT
1263 // Notify Time Scale Selection Listeners
1264 TimeGraphRangeUpdateEvent event = new TimeGraphRangeUpdateEvent(this, startTime, endTime);
1265
1266 for (ITimeGraphRangeListener listener : fRangeListeners) {
1267 listener.timeRangeUpdated(event);
1268 }
1269
45f63682
PT
1270 // update external synch values
1271 updateExtSynchValues();
837a2f8c
PT
1272 }
1273 }
1274
1d012443
PT
1275 /**
1276 * Add a bookmark listener
1277 *
1278 * @param listener
1279 * The listener to add
1280 * @since 2.0
1281 */
1282 public void addBookmarkListener(ITimeGraphBookmarkListener listener) {
1283 fBookmarkListeners.add(listener);
1284 }
1285
1286 /**
1287 * Remove a bookmark listener
1288 *
1289 * @param listener
1290 * The listener to remove
1291 * @since 2.0
1292 */
1293 public void removeBookmarkListener(ITimeGraphBookmarkListener listener) {
1294 fBookmarkListeners.remove(listener);
1295 }
1296
1297 private void fireBookmarkAdded(IMarkerEvent bookmark) {
1298 TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
1299
1300 for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
1301 listener.bookmarkAdded(event);
1302 }
1303 }
1304
1305 private void fireBookmarkRemoved(IMarkerEvent bookmark) {
1306 TimeGraphBookmarkEvent event = new TimeGraphBookmarkEvent(this, bookmark);
1307
1308 for (ITimeGraphBookmarkListener listener : fBookmarkListeners) {
1309 listener.bookmarkRemoved(event);
1310 }
1311 }
1312
1313 /**
1314 * Set the bookmarks list.
1315 *
1316 * @param bookmarks
1317 * The bookmarks list, or null
1318 * @since 2.0
1319 */
1320 public void setBookmarks(List<IMarkerEvent> bookmarks) {
1d012443
PT
1321 fBookmarks.clear();
1322 if (bookmarks != null) {
1323 fBookmarks.addAll(bookmarks);
1d012443 1324 }
f72cd563
PT
1325 updateMarkerList();
1326 updateMarkerActions();
1d012443
PT
1327 }
1328
1329 /**
1330 * Get the bookmarks list.
1331 *
1332 * @return The bookmarks list
1333 * @since 2.0
1334 */
1335 public List<IMarkerEvent> getBookmarks() {
1336 return Collections.unmodifiableList(fBookmarks);
1337 }
1338
91512088
PT
1339 /**
1340 * Set the list of marker categories.
1341 *
1342 * @param categories
1343 * The list of marker categories, or null
1344 * @since 2.0
1345 */
1346 public void setMarkerCategories(List<String> categories) {
1347 fMarkerCategories.clear();
91512088
PT
1348 if (categories != null) {
1349 fMarkerCategories.addAll(categories);
1350 }
a924e2ed
PT
1351 fMarkerCategories.add(IMarkerEvent.BOOKMARKS);
1352 fMarkerAxisCtrl.setMarkerCategories(fMarkerCategories);
91512088
PT
1353 }
1354
f0a9cee1
PT
1355 /**
1356 * @since 2.0
1357 */
1358 @Override
1359 public void setMarkerCategoryVisible(String category, boolean visible) {
1360 boolean changed = false;
1361 if (visible) {
1362 changed = fHiddenMarkerCategories.remove(category);
1363 } else {
1364 changed = fHiddenMarkerCategories.add(category);
1365 }
1366 if (changed) {
1367 updateMarkerList();
1368 updateMarkerActions();
1369 getControl().redraw();
1370 }
1371 }
1372
f72cd563
PT
1373 /**
1374 * Set the markers list.
1375 *
1376 * @param markers
1377 * The markers list, or null
1378 * @since 2.0
1379 */
1380 public void setMarkers(List<IMarkerEvent> markers) {
1381 fMarkers.clear();
1382 if (markers != null) {
1383 fMarkers.addAll(markers);
1384 }
1385 updateMarkerList();
1386 updateMarkerActions();
1387 }
1388
1389 /**
1390 * Get the markers list.
1391 *
1392 * @return The markers list, or null
1393 * @since 2.0
1394 */
1395 public List<IMarkerEvent> getMarkers() {
1396 return Collections.unmodifiableList(fMarkers);
1397 }
1398
837a2f8c
PT
1399 /**
1400 * Callback to set a selected event in the view
1401 *
1402 * @param event
1403 * The event that was selected
1404 * @param source
1405 * The source of this selection event
1406 */
1407 public void setSelectedEvent(ITimeEvent event, Object source) {
1408 if (event == null || source == this) {
1409 return;
1410 }
f1fae91f
PT
1411 fSelectedEntry = event.getEntry();
1412 fTimeGraphCtrl.selectItem(fSelectedEntry, false);
837a2f8c
PT
1413
1414 setSelectedTimeInt(event.getTime(), true, true);
1415 adjustVerticalScrollBar();
1416 }
1417
1418 /**
1419 * Set the seeked time of a trace
1420 *
1421 * @param trace
1422 * The trace that was seeked
1423 * @param time
1424 * The target time
1425 * @param source
1426 * The source of this seek event
1427 */
1428 public void setSelectedTraceTime(ITimeGraphEntry trace, long time, Object source) {
1429 if (trace == null || source == this) {
1430 return;
1431 }
f1fae91f
PT
1432 fSelectedEntry = trace;
1433 fTimeGraphCtrl.selectItem(trace, false);
837a2f8c
PT
1434
1435 setSelectedTimeInt(time, true, true);
1436 }
1437
1438 /**
1439 * Callback for a trace selection
1440 *
1441 * @param trace
1442 * The trace that was selected
1443 */
1444 public void setSelection(ITimeGraphEntry trace) {
88de10c6
PT
1445 /* if there is a pending selection, ignore this one */
1446 if (fListenerNotifier != null && fListenerNotifier.hasSelectionChanged()) {
1447 return;
1448 }
f1fae91f
PT
1449 fSelectedEntry = trace;
1450 fTimeGraphCtrl.selectItem(trace, false);
837a2f8c
PT
1451 adjustVerticalScrollBar();
1452 }
1453
1454 /**
1455 * Callback for a time window selection
1456 *
1457 * @param time0
1458 * Start time of the range
1459 * @param time1
1460 * End time of the range
1461 * @param source
1462 * Source of the event
1463 */
1464 public void setSelectVisTimeWindow(long time0, long time1, Object source) {
1465 if (source == this) {
1466 return;
1467 }
1468
88de10c6 1469 setStartFinishTimeInt(time0, time1);
837a2f8c
PT
1470
1471 // update notification time values since we are now in synch with the
1472 // external application
45f63682 1473 updateExtSynchValues();
837a2f8c
PT
1474 }
1475
1476 /**
45f63682 1477 * update the cache values used to identify the need to send a time window
837a2f8c
PT
1478 * update to external registered listeners
1479 */
45f63682 1480 private void updateExtSynchValues() {
837a2f8c 1481 // last time notification cache
f1fae91f
PT
1482 fTime0ExtSynch = fTime0;
1483 fTime1ExtSynch = fTime1;
837a2f8c
PT
1484 }
1485
026664b7
XR
1486 @Override
1487 public TimeFormat getTimeFormat() {
f1fae91f 1488 return fTimeFormat;
837a2f8c
PT
1489 }
1490
026664b7 1491 /**
79ec0b89
PT
1492 * @param tf
1493 * the {@link TimeFormat} used to display timestamps
026664b7
XR
1494 */
1495 public void setTimeFormat(TimeFormat tf) {
f1fae91f 1496 this.fTimeFormat = tf;
0fab12b0
PT
1497 if (tf == TimeFormat.CYCLES) {
1498 fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
1499 } else {
1500 fTimeDataProvider = this;
1501 }
1502 fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
1503 if (fToolTipHandler != null) {
1504 fToolTipHandler.setTimeProvider(fTimeDataProvider);
1505 }
1506 }
1507
1508 /**
1509 * Sets the clock frequency. Used when the time format is set to CYCLES.
1510 *
1511 * @param clockFrequency
1512 * the clock frequency in Hz
0fab12b0
PT
1513 */
1514 public void setClockFrequency(long clockFrequency) {
1515 fClockFrequency = clockFrequency;
1516 if (fTimeFormat == TimeFormat.CYCLES) {
1517 fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
1518 fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
1519 if (fToolTipHandler != null) {
1520 fToolTipHandler.setTimeProvider(fTimeDataProvider);
1521 }
1522 }
837a2f8c
PT
1523 }
1524
1525 /**
1526 * Retrieve the border width
1527 *
1528 * @return The width
1529 */
1530 public int getBorderWidth() {
f1fae91f 1531 return fBorderWidth;
837a2f8c
PT
1532 }
1533
1534 /**
1535 * Set the border width
1536 *
1537 * @param borderWidth
1538 * The width
1539 */
1540 public void setBorderWidth(int borderWidth) {
1541 if (borderWidth > -1) {
f1fae91f 1542 this.fBorderWidth = borderWidth;
79ec0b89 1543 GridLayout gl = (GridLayout) fDataViewer.getLayout();
837a2f8c
PT
1544 gl.marginHeight = borderWidth;
1545 }
1546 }
1547
1548 /**
1549 * Retrieve the height of the header
1550 *
1551 * @return The height
1552 */
1553 public int getHeaderHeight() {
f1fae91f 1554 return fTimeScaleHeight;
837a2f8c
PT
1555 }
1556
1557 /**
1558 * Set the height of the header
1559 *
1560 * @param headerHeight
1561 * The height to set
1562 */
1563 public void setHeaderHeight(int headerHeight) {
1564 if (headerHeight > -1) {
f1fae91f
PT
1565 this.fTimeScaleHeight = headerHeight;
1566 fTimeScaleCtrl.setHeight(headerHeight);
837a2f8c
PT
1567 }
1568 }
1569
1570 /**
1571 * Retrieve the height of an item row
1572 *
1573 * @return The height
1574 */
1575 public int getItemHeight() {
f1fae91f
PT
1576 if (fTimeGraphCtrl != null) {
1577 return fTimeGraphCtrl.getItemHeight();
837a2f8c
PT
1578 }
1579 return 0;
1580 }
1581
1582 /**
1583 * Set the height of an item row
1584 *
1585 * @param rowHeight
1586 * The height to set
1587 */
1588 public void setItemHeight(int rowHeight) {
f1fae91f
PT
1589 if (fTimeGraphCtrl != null) {
1590 fTimeGraphCtrl.setItemHeight(rowHeight);
837a2f8c
PT
1591 }
1592 }
1593
1594 /**
1595 * Set the minimum item width
1596 *
1597 * @param width
1598 * The min width
1599 */
1600 public void setMinimumItemWidth(int width) {
f1fae91f
PT
1601 if (fTimeGraphCtrl != null) {
1602 fTimeGraphCtrl.setMinimumItemWidth(width);
837a2f8c
PT
1603 }
1604 }
1605
1606 /**
1607 * Set the width for the name column
1608 *
79ec0b89
PT
1609 * @param width
1610 * The width
837a2f8c
PT
1611 */
1612 public void setNameWidthPref(int width) {
f1fae91f 1613 fNameWidthPref = width;
837a2f8c 1614 if (width == 0) {
f1fae91f
PT
1615 fMinNameWidth = 0;
1616 fNameWidth = 0;
837a2f8c
PT
1617 }
1618 }
1619
1620 /**
1621 * Retrieve the configure width for the name column
1622 *
1623 * @param width
1624 * Unused?
1625 * @return The width
1626 */
1627 public int getNameWidthPref(int width) {
f1fae91f 1628 return fNameWidthPref;
837a2f8c
PT
1629 }
1630
1631 /**
1632 * Returns the primary control associated with this viewer.
1633 *
1634 * @return the SWT control which displays this viewer's content
1635 */
1636 public Control getControl() {
f1fae91f 1637 return fDataViewer;
837a2f8c
PT
1638 }
1639
1640 /**
1641 * Returns the time graph control associated with this viewer.
1642 *
1643 * @return the time graph control
1644 */
3e9a3685 1645 public TimeGraphControl getTimeGraphControl() {
f1fae91f 1646 return fTimeGraphCtrl;
837a2f8c
PT
1647 }
1648
1649 /**
1650 * Returns the time graph scale associated with this viewer.
1651 *
1652 * @return the time graph scale
1653 */
3e9a3685 1654 public TimeGraphScale getTimeGraphScale() {
f1fae91f 1655 return fTimeScaleCtrl;
837a2f8c
PT
1656 }
1657
d2e4afa7
MAL
1658 /**
1659 * Returns the composite containing all the controls that are time aligned,
1660 * i.e. TimeGraphScale, TimeGraphControl.
1661 *
1662 * @return the time based composite
1663 * @since 1.0
1664 */
1665 public Composite getTimeAlignedComposite() {
1666 return fTimeAlignedComposite;
1667 }
1668
713a70ae
PT
1669 /**
1670 * Return the x coordinate corresponding to a time
1671 *
79ec0b89
PT
1672 * @param time
1673 * the time
713a70ae 1674 * @return the x coordinate corresponding to the time
713a70ae
PT
1675 */
1676 public int getXForTime(long time) {
f1fae91f 1677 return fTimeGraphCtrl.getXForTime(time);
713a70ae
PT
1678 }
1679
1680 /**
1681 * Return the time corresponding to an x coordinate
1682 *
79ec0b89
PT
1683 * @param x
1684 * the x coordinate
713a70ae 1685 * @return the time corresponding to the x coordinate
713a70ae
PT
1686 */
1687 public long getTimeAtX(int x) {
f1fae91f 1688 return fTimeGraphCtrl.getTimeAtX(x);
713a70ae
PT
1689 }
1690
837a2f8c
PT
1691 /**
1692 * Get the selection provider
1693 *
1694 * @return the selection provider
1695 */
1696 public ISelectionProvider getSelectionProvider() {
f1fae91f 1697 return fTimeGraphCtrl;
837a2f8c
PT
1698 }
1699
1700 /**
1701 * Wait for the cursor
1702 *
1703 * @param waitInd
1704 * Wait indefinitely?
1705 */
1706 public void waitCursor(boolean waitInd) {
f1fae91f 1707 fTimeGraphCtrl.waitCursor(waitInd);
837a2f8c
PT
1708 }
1709
1710 /**
1711 * Get the horizontal scroll bar object
1712 *
1713 * @return The scroll bar
1714 */
b698ec63
PT
1715 public Slider getHorizontalBar() {
1716 return fHorizontalScrollBar;
837a2f8c
PT
1717 }
1718
1719 /**
1720 * Get the vertical scroll bar object
1721 *
1722 * @return The scroll bar
1723 */
1724 public Slider getVerticalBar() {
f1fae91f 1725 return fVerticalScrollBar;
837a2f8c
PT
1726 }
1727
1728 /**
1729 * Set the given index as the top one
1730 *
1731 * @param index
1732 * The index that will go to the top
1733 */
1734 public void setTopIndex(int index) {
f1fae91f 1735 fTimeGraphCtrl.setTopIndex(index);
837a2f8c
PT
1736 adjustVerticalScrollBar();
1737 }
1738
1739 /**
1740 * Retrieve the current top index
1741 *
1742 * @return The top index
1743 */
1744 public int getTopIndex() {
f1fae91f 1745 return fTimeGraphCtrl.getTopIndex();
837a2f8c
PT
1746 }
1747
f4617471 1748 /**
df0e3d5f
PT
1749 * Sets the auto-expand level to be used for new entries discovered when
1750 * calling {@link #setInput(Object)} or {@link #refresh()}. The value 0
1751 * means that there is no auto-expand; 1 means that top-level entries are
1752 * expanded, but not their children; 2 means that top-level entries are
1753 * expanded, and their children, but not grand-children; and so on.
f4617471
PT
1754 * <p>
1755 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1756 * </p>
df0e3d5f 1757 *
f4617471
PT
1758 * @param level
1759 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1760 * levels of the tree
f4617471
PT
1761 */
1762 public void setAutoExpandLevel(int level) {
1763 fTimeGraphCtrl.setAutoExpandLevel(level);
1764 }
1765
1766 /**
1767 * Returns the auto-expand level.
1768 *
1769 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of
1770 * the tree are expanded automatically
1771 * @see #setAutoExpandLevel
f4617471
PT
1772 */
1773 public int getAutoExpandLevel() {
1774 return fTimeGraphCtrl.getAutoExpandLevel();
1775 }
1776
df0e3d5f
PT
1777 /**
1778 * Get the expanded state of an entry.
1779 *
1780 * @param entry
1781 * The entry
1782 * @return true if the entry is expanded, false if collapsed
0336f981 1783 * @since 1.1
df0e3d5f
PT
1784 */
1785 public boolean getExpandedState(ITimeGraphEntry entry) {
1786 return fTimeGraphCtrl.getExpandedState(entry);
1787 }
1788
837a2f8c
PT
1789 /**
1790 * Set the expanded state of an entry
1791 *
1792 * @param entry
1793 * The entry to expand/collapse
1794 * @param expanded
1795 * True for expanded, false for collapsed
1796 */
1797 public void setExpandedState(ITimeGraphEntry entry, boolean expanded) {
f1fae91f 1798 fTimeGraphCtrl.setExpandedState(entry, expanded);
837a2f8c
PT
1799 adjustVerticalScrollBar();
1800 }
1801
1802 /**
1803 * Collapses all nodes of the viewer's tree, starting with the root.
837a2f8c
PT
1804 */
1805 public void collapseAll() {
f1fae91f 1806 fTimeGraphCtrl.collapseAll();
837a2f8c
PT
1807 adjustVerticalScrollBar();
1808 }
1809
1810 /**
df0e3d5f 1811 * Expands all entries of the viewer's tree, starting with the root.
837a2f8c
PT
1812 */
1813 public void expandAll() {
f1fae91f 1814 fTimeGraphCtrl.expandAll();
837a2f8c
PT
1815 adjustVerticalScrollBar();
1816 }
1817
36299425
JCK
1818 /**
1819 * Select an entry and reveal it
1820 *
1821 * @param entry
1822 * The entry to select
1823 * @since 2.0
1824 */
1825 public void selectAndReveal(@NonNull ITimeGraphEntry entry) {
1826 final ITimeGraphEntry parent = entry.getParent();
1827 if (parent != null) {
1828 fTimeGraphCtrl.setExpandedState(parent, true);
1829 }
1830 setSelection(entry);
1831 adjustVerticalScrollBar();
1832 }
1833
837a2f8c 1834 /**
df0e3d5f
PT
1835 * Get the number of expanded (visible) time graph entries. This includes
1836 * leafs and does not include filtered-out entries.
837a2f8c 1837 *
df0e3d5f 1838 * @return The number of expanded (visible) time graph entries
837a2f8c
PT
1839 */
1840 public int getExpandedElementCount() {
f1fae91f 1841 return fTimeGraphCtrl.getExpandedElementCount();
837a2f8c
PT
1842 }
1843
1844 /**
df0e3d5f
PT
1845 * Get the expanded (visible) time graph entries. This includes leafs and
1846 * does not include filtered-out entries.
837a2f8c 1847 *
df0e3d5f 1848 * @return The array of expanded (visible) time graph entries
837a2f8c
PT
1849 */
1850 public ITimeGraphEntry[] getExpandedElements() {
f1fae91f 1851 return fTimeGraphCtrl.getExpandedElements();
837a2f8c
PT
1852 }
1853
1854 /**
1855 * Add a tree listener
1856 *
1857 * @param listener
1858 * The listener to add
1859 */
1860 public void addTreeListener(ITimeGraphTreeListener listener) {
f1fae91f 1861 fTimeGraphCtrl.addTreeListener(listener);
837a2f8c
PT
1862 }
1863
1864 /**
1865 * Remove a tree listener
1866 *
1867 * @param listener
1868 * The listener to remove
1869 */
1870 public void removeTreeListener(ITimeGraphTreeListener listener) {
f1fae91f 1871 fTimeGraphCtrl.removeTreeListener(listener);
837a2f8c
PT
1872 }
1873
1874 /**
1875 * Get the reset scale action.
1876 *
1877 * @return The Action object
1878 */
1879 public Action getResetScaleAction() {
f1fae91f 1880 if (fResetScaleAction == null) {
837a2f8c 1881 // resetScale
f1fae91f 1882 fResetScaleAction = new Action() {
837a2f8c
PT
1883 @Override
1884 public void run() {
1885 resetStartFinishTime();
1886 }
1887 };
f1fae91f
PT
1888 fResetScaleAction.setText(Messages.TmfTimeGraphViewer_ResetScaleActionNameText);
1889 fResetScaleAction.setToolTipText(Messages.TmfTimeGraphViewer_ResetScaleActionToolTipText);
1890 fResetScaleAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_HOME_MENU));
837a2f8c 1891 }
f1fae91f 1892 return fResetScaleAction;
837a2f8c
PT
1893 }
1894
1895 /**
1896 * Get the show legend action.
1897 *
1898 * @return The Action object
1899 */
1900 public Action getShowLegendAction() {
f1fae91f 1901 if (fShowLegendAction == null) {
837a2f8c 1902 // showLegend
f1fae91f 1903 fShowLegendAction = new Action() {
837a2f8c
PT
1904 @Override
1905 public void run() {
1906 showLegend();
1907 }
1908 };
f1fae91f
PT
1909 fShowLegendAction.setText(Messages.TmfTimeGraphViewer_LegendActionNameText);
1910 fShowLegendAction.setToolTipText(Messages.TmfTimeGraphViewer_LegendActionToolTipText);
1911 fShowLegendAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_SHOW_LEGEND));
837a2f8c
PT
1912 }
1913
f1fae91f 1914 return fShowLegendAction;
837a2f8c
PT
1915 }
1916
1917 /**
1918 * Get the the next event action.
1919 *
1920 * @return The action object
1921 */
1922 public Action getNextEventAction() {
f1fae91f
PT
1923 if (fNextEventAction == null) {
1924 fNextEventAction = new Action() {
837a2f8c 1925 @Override
33fa1fc7
PT
1926 public void runWithEvent(Event event) {
1927 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
1928 selectNextEvent(extend);
837a2f8c
PT
1929 }
1930 };
1931
f1fae91f
PT
1932 fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
1933 fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
1934 fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
837a2f8c
PT
1935 }
1936
f1fae91f 1937 return fNextEventAction;
837a2f8c
PT
1938 }
1939
1940 /**
1941 * Get the previous event action.
1942 *
1943 * @return The Action object
1944 */
1945 public Action getPreviousEventAction() {
f1fae91f
PT
1946 if (fPrevEventAction == null) {
1947 fPrevEventAction = new Action() {
837a2f8c 1948 @Override
33fa1fc7
PT
1949 public void runWithEvent(Event event) {
1950 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
1951 selectPrevEvent(extend);
837a2f8c
PT
1952 }
1953 };
1954
f1fae91f
PT
1955 fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
1956 fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
1957 fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
837a2f8c
PT
1958 }
1959
f1fae91f 1960 return fPrevEventAction;
837a2f8c
PT
1961 }
1962
1963 /**
1964 * Get the next item action.
1965 *
1966 * @return The Action object
1967 */
1968 public Action getNextItemAction() {
f1fae91f 1969 if (fNextItemAction == null) {
837a2f8c 1970
f1fae91f 1971 fNextItemAction = new Action() {
837a2f8c
PT
1972 @Override
1973 public void run() {
1974 selectNextItem();
1975 }
1976 };
f1fae91f
PT
1977 fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
1978 fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
1979 fNextItemAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_ITEM));
837a2f8c 1980 }
f1fae91f 1981 return fNextItemAction;
837a2f8c
PT
1982 }
1983
1984 /**
1985 * Get the previous item action.
1986 *
1987 * @return The Action object
1988 */
1989 public Action getPreviousItemAction() {
f1fae91f 1990 if (fPreviousItemAction == null) {
837a2f8c 1991
f1fae91f 1992 fPreviousItemAction = new Action() {
837a2f8c
PT
1993 @Override
1994 public void run() {
1995 selectPrevItem();
1996 }
1997 };
f1fae91f
PT
1998 fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
1999 fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
2000 fPreviousItemAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_ITEM));
837a2f8c 2001 }
f1fae91f 2002 return fPreviousItemAction;
837a2f8c
PT
2003 }
2004
2005 /**
2006 * Get the zoom in action
2007 *
2008 * @return The Action object
2009 */
2010 public Action getZoomInAction() {
f1fae91f
PT
2011 if (fZoomInAction == null) {
2012 fZoomInAction = new Action() {
837a2f8c
PT
2013 @Override
2014 public void run() {
2015 zoomIn();
2016 }
2017 };
f1fae91f
PT
2018 fZoomInAction.setText(Messages.TmfTimeGraphViewer_ZoomInActionNameText);
2019 fZoomInAction.setToolTipText(Messages.TmfTimeGraphViewer_ZoomInActionToolTipText);
2020 fZoomInAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ZOOM_IN_MENU));
837a2f8c 2021 }
f1fae91f 2022 return fZoomInAction;
837a2f8c
PT
2023 }
2024
2025 /**
2026 * Get the zoom out action
2027 *
2028 * @return The Action object
2029 */
2030 public Action getZoomOutAction() {
f1fae91f
PT
2031 if (fZoomOutAction == null) {
2032 fZoomOutAction = new Action() {
837a2f8c
PT
2033 @Override
2034 public void run() {
2035 zoomOut();
2036 }
2037 };
f1fae91f
PT
2038 fZoomOutAction.setText(Messages.TmfTimeGraphViewer_ZoomOutActionNameText);
2039 fZoomOutAction.setToolTipText(Messages.TmfTimeGraphViewer_ZoomOutActionToolTipText);
2040 fZoomOutAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_ZOOM_OUT_MENU));
837a2f8c 2041 }
f1fae91f 2042 return fZoomOutAction;
837a2f8c
PT
2043 }
2044
79ec0b89
PT
2045 /**
2046 * Get the hide arrows action
2047 *
2048 * @param dialogSettings
2049 * The dialog settings section where the state should be stored,
2050 * or null
2051 *
2052 * @return The Action object
79ec0b89
PT
2053 */
2054 public Action getHideArrowsAction(final IDialogSettings dialogSettings) {
2055 if (fHideArrowsAction == null) {
2056 fHideArrowsAction = new Action(Messages.TmfTimeGraphViewer_HideArrowsActionNameText, IAction.AS_CHECK_BOX) {
2057 @Override
2058 public void run() {
2059 boolean hideArrows = fHideArrowsAction.isChecked();
2060 fTimeGraphCtrl.hideArrows(hideArrows);
2061 refresh();
2062 if (dialogSettings != null) {
2063 dialogSettings.put(HIDE_ARROWS_KEY, hideArrows);
2064 }
086f21ae
PT
2065 if (fFollowArrowFwdAction != null) {
2066 fFollowArrowFwdAction.setEnabled(!hideArrows);
2067 }
2068 if (fFollowArrowBwdAction != null) {
2069 fFollowArrowBwdAction.setEnabled(!hideArrows);
2070 }
79ec0b89
PT
2071 }
2072 };
2073 fHideArrowsAction.setToolTipText(Messages.TmfTimeGraphViewer_HideArrowsActionToolTipText);
2074 fHideArrowsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_HIDE_ARROWS));
2075 if (dialogSettings != null) {
2076 boolean hideArrows = dialogSettings.getBoolean(HIDE_ARROWS_KEY);
2077 fTimeGraphCtrl.hideArrows(hideArrows);
2078 fHideArrowsAction.setChecked(hideArrows);
086f21ae
PT
2079 if (fFollowArrowFwdAction != null) {
2080 fFollowArrowFwdAction.setEnabled(!hideArrows);
2081 }
2082 if (fFollowArrowBwdAction != null) {
2083 fFollowArrowBwdAction.setEnabled(!hideArrows);
2084 }
79ec0b89
PT
2085 }
2086 }
2087 return fHideArrowsAction;
2088 }
837a2f8c 2089
086f21ae
PT
2090 /**
2091 * Get the follow arrow forward action.
2092 *
2093 * @return The Action object
086f21ae
PT
2094 */
2095 public Action getFollowArrowFwdAction() {
2096 if (fFollowArrowFwdAction == null) {
2097 fFollowArrowFwdAction = new Action() {
2098 @Override
33fa1fc7
PT
2099 public void runWithEvent(Event event) {
2100 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2101 fTimeGraphCtrl.followArrowFwd(extend);
086f21ae
PT
2102 adjustVerticalScrollBar();
2103 }
2104 };
2105 fFollowArrowFwdAction.setText(Messages.TmfTimeGraphViewer_FollowArrowForwardActionNameText);
2106 fFollowArrowFwdAction.setToolTipText(Messages.TmfTimeGraphViewer_FollowArrowForwardActionToolTipText);
2107 fFollowArrowFwdAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FOLLOW_ARROW_FORWARD));
2108 if (fHideArrowsAction != null) {
2109 fFollowArrowFwdAction.setEnabled(!fHideArrowsAction.isChecked());
2110 }
2111 }
2112 return fFollowArrowFwdAction;
2113 }
2114
2115 /**
2116 * Get the follow arrow backward action.
2117 *
2118 * @return The Action object
086f21ae
PT
2119 */
2120 public Action getFollowArrowBwdAction() {
2121 if (fFollowArrowBwdAction == null) {
2122 fFollowArrowBwdAction = new Action() {
2123 @Override
33fa1fc7
PT
2124 public void runWithEvent(Event event) {
2125 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2126 fTimeGraphCtrl.followArrowBwd(extend);
086f21ae
PT
2127 adjustVerticalScrollBar();
2128 }
2129 };
2130 fFollowArrowBwdAction.setText(Messages.TmfTimeGraphViewer_FollowArrowBackwardActionNameText);
2131 fFollowArrowBwdAction.setToolTipText(Messages.TmfTimeGraphViewer_FollowArrowBackwardActionToolTipText);
2132 fFollowArrowBwdAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FOLLOW_ARROW_BACKWARD));
2133 if (fHideArrowsAction != null) {
2134 fFollowArrowBwdAction.setEnabled(!fHideArrowsAction.isChecked());
2135 }
2136 }
2137 return fFollowArrowBwdAction;
2138 }
2139
cfcfd964
PT
2140 /**
2141 * Get the show filter dialog action.
2142 *
2143 * @return The Action object
2144 * @since 2.0
2145 */
2146 public ShowFilterDialogAction getShowFilterDialogAction() {
2147 if (fShowFilterDialogAction == null) {
2148 fShowFilterDialogAction = new ShowFilterDialogAction(this);
2149 }
2150 return fShowFilterDialogAction;
2151 }
2152
1d012443
PT
2153 /**
2154 * Get the toggle bookmark action.
2155 *
2156 * @return The Action object
2157 * @since 2.0
2158 */
2159 public Action getToggleBookmarkAction() {
2160 if (fToggleBookmarkAction == null) {
2161 fToggleBookmarkAction = new Action() {
2162 @Override
2163 public void runWithEvent(Event event) {
2164 IMarkerEvent selectedBookmark = getBookmarkAtSelection();
2165 if (selectedBookmark == null) {
2166 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2167 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
7697e148 2168 final AddBookmarkDialog dialog = new AddBookmarkDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), null);
1d012443
PT
2169 if (dialog.open() == Window.OK) {
2170 final String label = dialog.getValue();
2171 final RGBA rgba = dialog.getColorValue();
8910dea2 2172 IMarkerEvent bookmark = new MarkerEvent(null, time, duration, IMarkerEvent.BOOKMARKS, rgba, label, true);
1d012443 2173 fBookmarks.add(bookmark);
f72cd563 2174 updateMarkerList();
91512088 2175 updateMarkerActions();
1d012443
PT
2176 getControl().redraw();
2177 fireBookmarkAdded(bookmark);
2178 }
2179 } else {
1d012443 2180 fBookmarks.remove(selectedBookmark);
f72cd563 2181 updateMarkerList();
91512088 2182 updateMarkerActions();
1d012443
PT
2183 getControl().redraw();
2184 fireBookmarkRemoved(selectedBookmark);
2185 }
1d012443
PT
2186 }
2187 };
2188 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2189 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2190 fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
2191 }
2192 return fToggleBookmarkAction;
2193 }
2194
2195 /**
f72cd563 2196 * Get the next marker action.
1d012443
PT
2197 *
2198 * @return The Action object
2199 * @since 2.0
2200 */
f72cd563
PT
2201 public Action getNextMarkerAction() {
2202 if (fNextMarkerAction == null) {
6d5b0ba1 2203 fNextMarkerAction = new Action(Messages.TmfTimeGraphViewer_NextMarkerActionText, IAction.AS_DROP_DOWN_MENU) {
1d012443
PT
2204 @Override
2205 public void runWithEvent(Event event) {
4aa2593c
PT
2206 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2207 if (extend) {
2208 extendToNextMarker();
2209 } else {
2210 selectNextMarker();
1d012443
PT
2211 }
2212 }
2213 };
f72cd563
PT
2214 fNextMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_NextMarkerActionText);
2215 fNextMarkerAction.setImageDescriptor(NEXT_BOOKMARK);
6d5b0ba1
PT
2216 fNextMarkerAction.setMenuCreator(new IMenuCreator () {
2217 Menu menu = null;
2218 @Override
2219 public void dispose() {
2220 if (menu != null) {
2221 menu.dispose();
2222 menu = null;
2223 }
2224 }
2225
2226 @Override
2227 public Menu getMenu(Control parent) {
2228 if (menu != null) {
2229 menu.dispose();
2230 }
2231 menu = new Menu(parent);
2232 for (String category : fMarkerCategories) {
2233 final Action action = new Action(category, IAction.AS_CHECK_BOX) {
2234 @Override
2235 public void runWithEvent(Event event) {
2236 if (isChecked()) {
2237 fSkippedMarkerCategories.remove(getText());
2238 } else {
2239 fSkippedMarkerCategories.add(getText());
2240 }
2241 updateMarkerActions();
2242 }
2243 };
2244 action.setEnabled(!fHiddenMarkerCategories.contains(category));
2245 action.setChecked(action.isEnabled() && !fSkippedMarkerCategories.contains(category));
2246 new ActionContributionItem(action).fill(menu, -1);
2247 }
2248 return menu;
2249 }
2250
2251 @Override
2252 public Menu getMenu(Menu parent) {
2253 return null;
2254 }
2255 });
1d012443 2256 }
f72cd563 2257 return fNextMarkerAction;
1d012443
PT
2258 }
2259
2260 /**
f72cd563 2261 * Get the previous marker action.
1d012443
PT
2262 *
2263 * @return The Action object
2264 * @since 2.0
2265 */
f72cd563
PT
2266 public Action getPreviousMarkerAction() {
2267 if (fPreviousMarkerAction == null) {
2268 fPreviousMarkerAction = new Action() {
1d012443
PT
2269 @Override
2270 public void runWithEvent(Event event) {
4aa2593c
PT
2271 boolean extend = (event.stateMask & SWT.SHIFT) != 0;
2272 if (extend) {
2273 extendToPrevMarker();
2274 } else {
2275 selectPrevMarker();
1d012443
PT
2276 }
2277 }
2278 };
f72cd563
PT
2279 fPreviousMarkerAction.setText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
2280 fPreviousMarkerAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousMarkerActionText);
2281 fPreviousMarkerAction.setImageDescriptor(PREVIOUS_BOOKMARK);
1d012443 2282 }
f72cd563 2283 return fPreviousMarkerAction;
1d012443
PT
2284 }
2285
91512088
PT
2286 /**
2287 * Get the show markers menu.
2288 *
2289 * @return The menu manager object
2290 * @since 2.0
2291 */
2292 public MenuManager getMarkersMenu() {
2293 if (fMarkersMenu == null) {
2294 fMarkersMenu = new MenuManager(Messages.TmfTimeGraphViewer_ShowMarkersMenuText);
2295 fMarkersMenu.setRemoveAllWhenShown(true);
2296 fMarkersMenu.addMenuListener(new IMenuListener() {
2297 @Override
2298 public void menuAboutToShow(IMenuManager manager) {
2299 for (String category : fMarkerCategories) {
2300 final Action action = new Action(category, IAction.AS_CHECK_BOX) {
2301 @Override
2302 public void runWithEvent(Event event) {
f0a9cee1 2303 setMarkerCategoryVisible(getText(), isChecked());
91512088
PT
2304 }
2305 };
2306 action.setChecked(!fHiddenMarkerCategories.contains(category));
2307 manager.add(action);
2308 }
2309 }
2310 });
2311 }
2312 return fMarkersMenu;
2313 }
2314
4aa2593c
PT
2315 /**
2316 * Select the next marker that begins at or after the current selection
2317 * begin time. Markers that begin at the same time are ordered by end time.
2318 */
2319 private void selectNextMarker() {
2320 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2321 if (markers == null) {
2322 return;
2323 }
2324 for (IMarkerEvent marker : markers) {
2325 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2326 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2327 if ((marker.getTime() > time ||
2328 (marker.getTime() == time && marker.getDuration() > duration))
2329 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
d5997aaf
PT
2330 setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), false);
2331 ensureVisible(marker.getTime());
2332 notifyRangeListeners();
4aa2593c
PT
2333 fTimeGraphCtrl.updateStatusLine();
2334 return;
2335 }
2336 }
2337 }
2338
2339 /**
2340 * Select the previous marker that begins at or before the current selection
2341 * begin time. Markers that begin at the same time are ordered by end time.
2342 */
2343 private void selectPrevMarker() {
2344 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2345 if (markers == null) {
2346 return;
2347 }
2348 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2349 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2350 for (int i = markers.size() - 1; i >= 0; i--) {
2351 IMarkerEvent marker = markers.get(i);
2352 if ((marker.getTime() < time ||
2353 (marker.getTime() == time && marker.getDuration() < duration))
2354 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
d5997aaf
PT
2355 setSelectionRangeNotify(marker.getTime(), marker.getTime() + marker.getDuration(), false);
2356 ensureVisible(marker.getTime());
2357 notifyRangeListeners();
4aa2593c
PT
2358 fTimeGraphCtrl.updateStatusLine();
2359 return;
2360 }
2361 }
2362 }
2363
2364 /**
2365 * Extend the selection to the closest next marker end time.
2366 */
2367 private void extendToNextMarker() {
2368 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2369 if (markers == null) {
2370 return;
2371 }
2372 IMarkerEvent nextMarker = null;
2373 for (IMarkerEvent marker : markers) {
2374 if (marker.getTime() + marker.getDuration() > fSelectionEnd
2375 && !fSkippedMarkerCategories.contains(marker.getCategory())
2376 && (nextMarker == null || marker.getTime() + marker.getDuration() < nextMarker.getTime() + nextMarker.getDuration())) {
2377 nextMarker = marker;
2378 }
2379 }
2380 if (nextMarker != null) {
84c8aef7 2381 setSelectionRangeNotify(fSelectionBegin, nextMarker.getTime() + nextMarker.getDuration(), true);
4aa2593c
PT
2382 fTimeGraphCtrl.updateStatusLine();
2383 }
2384 }
2385
2386 /**
2387 * Extend the selection to the closest previous marker start time.
2388 */
2389 private void extendToPrevMarker() {
2390 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2391 if (markers == null) {
2392 return;
2393 }
2394 for (int i = markers.size() - 1; i >= 0; i--) {
2395 IMarkerEvent marker = markers.get(i);
2396 if (marker.getTime() < fSelectionEnd
2397 && !fSkippedMarkerCategories.contains(marker.getCategory())) {
84c8aef7 2398 setSelectionRangeNotify(fSelectionBegin, marker.getTime(), true);
4aa2593c
PT
2399 fTimeGraphCtrl.updateStatusLine();
2400 return;
2401 }
2402 }
2403 }
2404
1d012443
PT
2405 private IMarkerEvent getBookmarkAtSelection() {
2406 final long time = Math.min(fSelectionBegin, fSelectionEnd);
2407 final long duration = Math.max(fSelectionBegin, fSelectionEnd) - time;
2408 for (IMarkerEvent bookmark : fBookmarks) {
2409 if (bookmark.getTime() == time && bookmark.getDuration() == duration) {
2410 return bookmark;
2411 }
2412 }
2413 return null;
2414 }
2415
f72cd563 2416 private void updateMarkerActions() {
6d5b0ba1 2417 boolean enabled = fTime0Bound != SWT.DEFAULT || fTime1Bound != SWT.DEFAULT;
1d012443
PT
2418 if (fToggleBookmarkAction != null) {
2419 if (getBookmarkAtSelection() != null) {
2420 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
2421 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionRemoveText);
2422 fToggleBookmarkAction.setImageDescriptor(REMOVE_BOOKMARK);
2423 } else {
2424 fToggleBookmarkAction.setText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2425 fToggleBookmarkAction.setToolTipText(Messages.TmfTimeGraphViewer_BookmarkActionAddText);
2426 fToggleBookmarkAction.setImageDescriptor(ADD_BOOKMARK);
2427 }
6d5b0ba1 2428 fToggleBookmarkAction.setEnabled(enabled);
1d012443 2429 }
f72cd563
PT
2430 List<IMarkerEvent> markers = getTimeGraphControl().getMarkers();
2431 if (markers == null) {
2432 markers = Collections.emptyList();
2433 }
2434 if (fPreviousMarkerAction != null) {
6d5b0ba1 2435 fPreviousMarkerAction.setEnabled(enabled && !markers.isEmpty());
1d012443 2436 }
f72cd563 2437 if (fNextMarkerAction != null) {
6d5b0ba1 2438 fNextMarkerAction.setEnabled(enabled && !markers.isEmpty());
1d012443
PT
2439 }
2440 }
2441
f72cd563 2442 private void updateMarkerList() {
91512088
PT
2443 List<IMarkerEvent> markers = new ArrayList<>();
2444 for (IMarkerEvent marker : fMarkers) {
2445 if (!fHiddenMarkerCategories.contains(marker.getCategory())) {
2446 markers.add(marker);
2447 }
2448 }
2449 if (!fHiddenMarkerCategories.contains(IMarkerEvent.BOOKMARKS)) {
2450 markers.addAll(fBookmarks);
2451 }
f72cd563 2452 Collections.sort(markers, new MarkerComparator());
dc4fa715
PT
2453 fTimeGraphCtrl.setMarkers(markers);
2454 fMarkerAxisCtrl.setMarkers(markers);
f72cd563
PT
2455 }
2456
b698ec63
PT
2457 private void adjustHorizontalScrollBar() {
2458 long time0 = getTime0();
2459 long time1 = getTime1();
2460 long timeMin = getMinTime();
2461 long timeMax = getMaxTime();
2462 long delta = timeMax - timeMin;
2463 int timePos = 0;
2464 int thumb = H_SCROLLBAR_MAX;
2465 if (delta != 0) {
2466 // Thumb size (page size)
2467 thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta)));
2468 // At the beginning of visible window
2469 timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta));
2470 }
2471 fHorizontalScrollBar.setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, Math.max(1, thumb / 2), Math.max(2, thumb));
2472 }
2473
837a2f8c 2474 private void adjustVerticalScrollBar() {
f1fae91f
PT
2475 int topIndex = fTimeGraphCtrl.getTopIndex();
2476 int countPerPage = fTimeGraphCtrl.countPerPage();
2477 int expandedElementCount = fTimeGraphCtrl.getExpandedElementCount();
837a2f8c 2478 if (topIndex + countPerPage > expandedElementCount) {
f1fae91f 2479 fTimeGraphCtrl.setTopIndex(Math.max(0, expandedElementCount - countPerPage));
837a2f8c
PT
2480 }
2481
f1fae91f 2482 int selection = fTimeGraphCtrl.getTopIndex();
837a2f8c
PT
2483 int min = 0;
2484 int max = Math.max(1, expandedElementCount - 1);
2485 int thumb = Math.min(max, Math.max(1, countPerPage - 1));
2486 int increment = 1;
2487 int pageIncrement = Math.max(1, countPerPage);
f1fae91f 2488 fVerticalScrollBar.setValues(selection, min, max, thumb, increment, pageIncrement);
837a2f8c
PT
2489 }
2490
27df1564 2491 /**
79ec0b89
PT
2492 * @param listener
2493 * a {@link MenuDetectListener}
2bdf0193 2494 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener)
27df1564
XR
2495 */
2496 public void addTimeGraphEntryMenuListener(MenuDetectListener listener) {
f1fae91f 2497 fTimeGraphCtrl.addTimeGraphEntryMenuListener(listener);
27df1564
XR
2498 }
2499
2500 /**
79ec0b89
PT
2501 * @param listener
2502 * a {@link MenuDetectListener}
2bdf0193 2503 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener)
27df1564
XR
2504 */
2505 public void removeTimeGraphEntryMenuListener(MenuDetectListener listener) {
f1fae91f 2506 fTimeGraphCtrl.removeTimeGraphEntryMenuListener(listener);
27df1564
XR
2507 }
2508
2509 /**
79ec0b89
PT
2510 * @param listener
2511 * a {@link MenuDetectListener}
2bdf0193 2512 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener)
27df1564
XR
2513 */
2514 public void addTimeEventMenuListener(MenuDetectListener listener) {
f1fae91f 2515 fTimeGraphCtrl.addTimeEventMenuListener(listener);
27df1564
XR
2516 }
2517
2518 /**
79ec0b89
PT
2519 * @param listener
2520 * a {@link MenuDetectListener}
2bdf0193 2521 * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener)
27df1564
XR
2522 */
2523 public void removeTimeEventMenuListener(MenuDetectListener listener) {
f1fae91f 2524 fTimeGraphCtrl.removeTimeEventMenuListener(listener);
27df1564
XR
2525 }
2526
6ac5a950 2527 /**
79ec0b89
PT
2528 * @param filter
2529 * The filter object to be attached to the view
6ac5a950 2530 */
367e2932 2531 public void addFilter(@NonNull ViewerFilter filter) {
f1fae91f 2532 fTimeGraphCtrl.addFilter(filter);
6ac5a950
AM
2533 refresh();
2534 }
837a2f8c 2535
6ac5a950 2536 /**
79ec0b89
PT
2537 * @param filter
2538 * The filter object to be attached to the view
6ac5a950 2539 */
367e2932 2540 public void removeFilter(@NonNull ViewerFilter filter) {
f1fae91f 2541 fTimeGraphCtrl.removeFilter(filter);
6ac5a950
AM
2542 refresh();
2543 }
837a2f8c 2544
4923d7b9
PT
2545 /**
2546 * Returns this viewer's filters.
2547 *
2548 * @return an array of viewer filters
2549 * @since 2.0
2550 */
367e2932 2551 public @NonNull ViewerFilter[] getFilters() {
4923d7b9
PT
2552 return fTimeGraphCtrl.getFilters();
2553 }
2554
2555 /**
2556 * Sets the filters, replacing any previous filters, and triggers
2557 * refiltering of the elements.
2558 *
2559 * @param filters
2560 * an array of viewer filters, or null
2561 * @since 2.0
2562 */
367e2932 2563 public void setFilters(@NonNull ViewerFilter[] filters) {
4923d7b9
PT
2564 fTimeGraphCtrl.setFilters(filters);
2565 refresh();
2566 }
2567
d2e4afa7
MAL
2568 /**
2569 * Return the time alignment information
2570 *
2571 * @return the time alignment information
2572 *
2573 * @see ITmfTimeAligned
2574 *
2575 * @since 1.0
2576 */
2577 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
2578 return fTimeGraphCtrl.getTimeViewAlignmentInfo();
2579 }
2580
2581 /**
2582 * Return the available width for the time-axis.
2583 *
2584 * @see ITmfTimeAligned
2585 *
2586 * @param requestedOffset
2587 * the requested offset
2588 * @return the available width for the time-axis
2589 *
2590 * @since 1.0
2591 */
2592 public int getAvailableWidth(int requestedOffset) {
921ae867
MAL
2593 int totalWidth = fTimeAlignedComposite.getSize().x;
2594 return Math.min(totalWidth, Math.max(0, totalWidth - requestedOffset));
d2e4afa7
MAL
2595 }
2596
2597 /**
2598 * Perform the alignment operation.
2599 *
2600 * @param offset
2601 * the alignment offset
2602 * @param width
2603 * the alignment width
2604 *
2605 * @see ITmfTimeAligned
2606 *
2607 * @since 1.0
2608 */
2609 public void performAlign(int offset, int width) {
2610 fTimeGraphCtrl.performAlign(offset);
2611 int alignmentWidth = width;
2612 int size = fTimeAlignedComposite.getSize().x;
2613 GridLayout layout = (GridLayout) fTimeAlignedComposite.getLayout();
2614 int marginSize = size - alignmentWidth - offset;
2615 layout.marginRight = Math.max(0, marginSize);
2616 fTimeAlignedComposite.layout();
2617 }
2618
837a2f8c 2619}
This page took 0.410615 seconds and 5 git commands to generate.