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