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