Use the NonNull utility methods where we can
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractTimeGraphView.java
CommitLineData
4999a196 1/*******************************************************************************
1cf25311 2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
4999a196
GB
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 * Geneviève Bastien - Move code to provide base classes for time graph view
c1cd9635 13 * Marc-Andre Laperle - Add time zone preference
bec1f1ac 14 * Geneviève Bastien - Add event links between entries
4999a196
GB
15 *******************************************************************************/
16
2bdf0193 17package org.eclipse.tracecompass.tmf.ui.views.timegraph;
4999a196 18
5db5a3a4
AM
19import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
20
4999a196 21import java.util.ArrayList;
41cc4f90 22import java.util.Arrays;
4999a196
GB
23import java.util.Collections;
24import java.util.Comparator;
25import java.util.HashMap;
26import java.util.List;
27import java.util.Map;
1cf25311 28import java.util.concurrent.CopyOnWriteArrayList;
4999a196
GB
29
30import org.eclipse.core.runtime.IProgressMonitor;
31import org.eclipse.core.runtime.NullProgressMonitor;
dfa0ef96 32import org.eclipse.jdt.annotation.NonNull;
d2120fb6 33import org.eclipse.jdt.annotation.Nullable;
4999a196 34import org.eclipse.jface.action.Action;
747adf5c 35import org.eclipse.jface.action.IAction;
0fcf3b09 36import org.eclipse.jface.action.IStatusLineManager;
4999a196
GB
37import org.eclipse.jface.action.IToolBarManager;
38import org.eclipse.jface.action.Separator;
5d021ccf 39import org.eclipse.jface.viewers.AbstractTreeViewer;
40b7b614 40import org.eclipse.jface.viewers.ILabelProvider;
4999a196 41import org.eclipse.jface.viewers.ILabelProviderListener;
747adf5c 42import org.eclipse.jface.viewers.ISelectionProvider;
4999a196
GB
43import org.eclipse.jface.viewers.ITableLabelProvider;
44import org.eclipse.jface.viewers.ITreeContentProvider;
747adf5c 45import org.eclipse.jface.viewers.TreeViewer;
4999a196 46import org.eclipse.jface.viewers.Viewer;
4999a196
GB
47import org.eclipse.swt.SWT;
48import org.eclipse.swt.graphics.Image;
49import org.eclipse.swt.widgets.Composite;
50import org.eclipse.swt.widgets.Display;
51import org.eclipse.swt.widgets.TreeColumn;
2bdf0193
AM
52import org.eclipse.tracecompass.tmf.core.signal.TmfRangeSynchSignal;
53import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
54import org.eclipse.tracecompass.tmf.core.signal.TmfTimeSynchSignal;
55import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
56import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
57import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
58import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
59import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
60import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
61import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
62import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
63import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
64import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
65import org.eclipse.tracecompass.tmf.ui.views.TmfView;
66import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
67import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
68import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
69import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
70import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
71import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
72import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
73import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
74import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
75import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
76import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
77import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
78import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
79import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
80import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
4999a196
GB
81import org.eclipse.ui.IActionBars;
82
83/**
84 * An abstract view all time graph views can inherit
85 *
747adf5c
PT
86 * This view contains either a time graph viewer, or a time graph combo which is
87 * divided between a tree viewer on the left and a time graph viewer on the right.
4999a196 88 *
4b121c48 89 * @since 2.1
4999a196
GB
90 */
91public abstract class AbstractTimeGraphView extends TmfView {
92
5d021ccf
GB
93 /** Constant indicating that all levels of the time graph should be expanded */
94 protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
95
4999a196
GB
96 /**
97 * Redraw state enum
98 */
99 private enum State {
100 IDLE, BUSY, PENDING
101 }
102
103 // ------------------------------------------------------------------------
104 // Fields
105 // ------------------------------------------------------------------------
106
747adf5c
PT
107 /** The timegraph wrapper */
108 private ITimeGraphWrapper fTimeGraphWrapper;
4999a196
GB
109
110 /** The selected trace */
111 private ITmfTrace fTrace;
112
113 /** The timegraph entry list */
114 private List<TimeGraphEntry> fEntryList;
115
116 /** The trace to entry list hash map */
507b1336 117 private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
4999a196 118
1cf25311 119 /** The trace to build thread hash map */
507b1336 120 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
4999a196
GB
121
122 /** The start time */
123 private long fStartTime;
124
125 /** The end time */
126 private long fEndTime;
127
128 /** The display width */
129 private final int fDisplayWidth;
130
131 /** The zoom thread */
132 private ZoomThread fZoomThread;
133
134 /** The next resource action */
135 private Action fNextResourceAction;
136
137 /** The previous resource action */
138 private Action fPreviousResourceAction;
139
4999a196
GB
140 /** A comparator class */
141 private Comparator<ITimeGraphEntry> fEntryComparator = null;
142
1cf25311 143 /** The redraw state used to prevent unnecessary queuing of display runnables */
4999a196
GB
144 private State fRedrawState = State.IDLE;
145
146 /** The redraw synchronization object */
147 private final Object fSyncObj = new Object();
148
149 /** The presentation provider for this view */
150 private final TimeGraphPresentationProvider fPresentation;
151
747adf5c
PT
152 /** The tree column label array, or null if combo is not used */
153 private String[] fColumns;
154
155 /** The tree label provider, or null if combo is not used */
156 private TreeLabelProvider fLabelProvider = null;
157
158 /** The relative weight of the sash, ignored if combo is not used */
159 private int[] fWeight = { 1, 1 };
160
161 /** The filter column label array, or null if filter is not used */
162 private String[] fFilterColumns;
4999a196 163
1cf25311
PT
164 /** The pack done flag */
165 private boolean fPackDone = false;
166
a03b7ee4
PT
167 /** The filter label provider, or null if filter is not used */
168 private TreeLabelProvider fFilterLabelProvider;
169
5d021ccf
GB
170 private int fAutoExpandLevel = ALL_LEVELS;
171
4999a196 172 // ------------------------------------------------------------------------
747adf5c 173 // Classes
4999a196
GB
174 // ------------------------------------------------------------------------
175
747adf5c 176 private interface ITimeGraphWrapper {
4999a196 177
747adf5c 178 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation);
4999a196 179
747adf5c 180 TimeGraphViewer getTimeGraphViewer();
4999a196 181
747adf5c 182 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener);
4999a196 183
747adf5c 184 ISelectionProvider getSelectionProvider();
4999a196 185
747adf5c 186 void setFocus();
4999a196 187
747adf5c 188 boolean isDisposed();
4999a196 189
747adf5c 190 void refresh();
4999a196 191
1cf25311
PT
192 void setInput(Object input);
193
194 Object getInput();
4999a196 195
747adf5c 196 void redraw();
4999a196 197
747adf5c 198 void update();
4999a196 199
5d021ccf
GB
200 void setAutoExpandLevel(int level);
201
4999a196
GB
202 }
203
747adf5c
PT
204 private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
205 private TimeGraphViewer viewer;
4999a196 206
747adf5c
PT
207 private TimeGraphViewerWrapper(Composite parent, int style) {
208 viewer = new TimeGraphViewer(parent, style);
4999a196 209 }
4999a196 210
747adf5c
PT
211 @Override
212 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
213 viewer.setTimeGraphProvider(timeGraphProvider);
214 }
4999a196 215
747adf5c
PT
216 @Override
217 public TimeGraphViewer getTimeGraphViewer() {
218 return viewer;
219 }
4999a196 220
747adf5c
PT
221 @Override
222 public void addSelectionListener(ITimeGraphSelectionListener listener) {
223 viewer.addSelectionListener(listener);
224 }
4999a196 225
747adf5c
PT
226 @Override
227 public ISelectionProvider getSelectionProvider() {
228 return viewer.getSelectionProvider();
229 }
230
231 @Override
232 public void setFocus() {
233 viewer.setFocus();
234 }
235
236 @Override
237 public boolean isDisposed() {
238 return viewer.getControl().isDisposed();
239 }
240
241 @Override
1cf25311 242 public void setInput(Object input) {
747adf5c
PT
243 viewer.setInput(input);
244 }
245
1cf25311
PT
246 @Override
247 public Object getInput() {
248 return viewer.getInput();
249 }
250
747adf5c
PT
251 @Override
252 public void refresh() {
253 viewer.refresh();
254 }
255
256 @Override
257 public void redraw() {
258 viewer.getControl().redraw();
259 }
260
261 @Override
262 public void update() {
263 viewer.getControl().update();
264 }
5d021ccf
GB
265
266 @Override
267 public void setAutoExpandLevel(int level) {
268 viewer.setAutoExpandLevel(level);
269 }
4999a196
GB
270 }
271
747adf5c
PT
272 private class TimeGraphComboWrapper implements ITimeGraphWrapper {
273 private TimeGraphCombo combo;
274
275 private TimeGraphComboWrapper(Composite parent, int style) {
276 combo = new TimeGraphCombo(parent, style, fWeight);
277 }
278
279 @Override
280 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
281 combo.setTimeGraphProvider(timeGraphProvider);
282 }
283
284 @Override
285 public TimeGraphViewer getTimeGraphViewer() {
286 return combo.getTimeGraphViewer();
287 }
288
289 @Override
290 public void addSelectionListener(ITimeGraphSelectionListener listener) {
291 combo.addSelectionListener(listener);
292 }
293
294 @Override
295 public ISelectionProvider getSelectionProvider() {
296 return combo.getTreeViewer();
297 }
298
299 @Override
300 public void setFocus() {
301 combo.setFocus();
302 }
303
304 @Override
305 public boolean isDisposed() {
306 return combo.isDisposed();
307 }
308
309 @Override
1cf25311 310 public void setInput(Object input) {
747adf5c
PT
311 combo.setInput(input);
312 }
313
1cf25311
PT
314 @Override
315 public Object getInput() {
316 return combo.getInput();
317 }
318
747adf5c
PT
319 @Override
320 public void refresh() {
321 combo.refresh();
322 }
323
324 @Override
325 public void redraw() {
326 combo.redraw();
327 }
328
329 @Override
330 public void update() {
331 combo.update();
332 }
333
5d021ccf
GB
334 @Override
335 public void setAutoExpandLevel(int level) {
336 combo.setAutoExpandLevel(level);
337 }
338
747adf5c
PT
339 TimeGraphCombo getTimeGraphCombo() {
340 return combo;
341 }
342
343 TreeViewer getTreeViewer() {
344 return combo.getTreeViewer();
345 }
346
347 IAction getShowFilterAction() {
348 return combo.getShowFilterAction();
349 }
350 }
4999a196
GB
351
352 private class TreeContentProvider implements ITreeContentProvider {
353
354 @Override
355 public void dispose() {
356 }
357
358 @Override
359 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
360 }
361
362 @Override
1cf25311
PT
363 public ITimeGraphEntry[] getElements(Object inputElement) {
364 if (inputElement != null) {
365 try {
366 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
367 } catch (ClassCastException e) {
368 }
369 }
370 return new ITimeGraphEntry[0];
4999a196
GB
371 }
372
373 @Override
374 public Object[] getChildren(Object parentElement) {
375 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
376 List<? extends ITimeGraphEntry> children = entry.getChildren();
377 return children.toArray(new ITimeGraphEntry[children.size()]);
378 }
379
380 @Override
381 public Object getParent(Object element) {
382 ITimeGraphEntry entry = (ITimeGraphEntry) element;
383 return entry.getParent();
384 }
385
386 @Override
387 public boolean hasChildren(Object element) {
388 ITimeGraphEntry entry = (ITimeGraphEntry) element;
389 return entry.hasChildren();
390 }
391
392 }
393
1cf25311
PT
394 private class TimeGraphContentProvider implements ITimeGraphContentProvider {
395
396 @Override
397 public ITimeGraphEntry[] getElements(Object inputElement) {
398 if (inputElement != null) {
399 try {
400 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
401 } catch (ClassCastException e) {
402 }
403 }
404 return new ITimeGraphEntry[0];
405 }
406
407 }
408
4999a196 409 /**
747adf5c
PT
410 * Base class to provide the labels for the tree viewer. Views extending
411 * this class typically need to override the getColumnText method if they
412 * have more than one column to display
4999a196 413 */
40b7b614 414 protected static class TreeLabelProvider implements ITableLabelProvider, ILabelProvider {
4999a196
GB
415
416 @Override
417 public void addListener(ILabelProviderListener listener) {
418 }
419
420 @Override
421 public void dispose() {
422 }
423
424 @Override
425 public boolean isLabelProperty(Object element, String property) {
426 return false;
427 }
428
429 @Override
430 public void removeListener(ILabelProviderListener listener) {
431 }
432
433 @Override
434 public Image getColumnImage(Object element, int columnIndex) {
435 return null;
436 }
437
438 @Override
439 public String getColumnText(Object element, int columnIndex) {
440 TimeGraphEntry entry = (TimeGraphEntry) element;
441 if (columnIndex == 0) {
442 return entry.getName();
443 }
76fccfb0 444 return new String();
4999a196
GB
445 }
446
40b7b614 447 /**
a465519a 448 * @since 3.2
40b7b614
GP
449 */
450 @Override
451 public Image getImage(Object element) {
452 return null;
453 }
454
455 /**
a465519a 456 * @since 3.2
40b7b614
GP
457 */
458 @Override
459 public String getText(Object element) {
460 TimeGraphEntry entry = (TimeGraphEntry) element;
461 return entry.getName();
462 }
463
4999a196
GB
464 }
465
466 private class BuildThread extends Thread {
dfa0ef96
GB
467 private final @NonNull ITmfTrace fBuildTrace;
468 private final @NonNull ITmfTrace fParentTrace;
469 private final @NonNull IProgressMonitor fMonitor;
4999a196 470
dfa0ef96 471 public BuildThread(final @NonNull ITmfTrace trace, final @NonNull ITmfTrace parentTrace, final String name) {
4999a196
GB
472 super(name + " build"); //$NON-NLS-1$
473 fBuildTrace = trace;
1cf25311 474 fParentTrace = parentTrace;
4999a196
GB
475 fMonitor = new NullProgressMonitor();
476 }
477
478 @Override
479 public void run() {
1cf25311 480 buildEventList(fBuildTrace, fParentTrace, fMonitor);
4999a196 481 synchronized (fBuildThreadMap) {
1cf25311 482 fBuildThreadMap.remove(fBuildTrace);
4999a196
GB
483 }
484 }
485
486 public void cancel() {
487 fMonitor.setCanceled(true);
488 }
489 }
490
491 private class ZoomThread extends Thread {
dfa0ef96 492 private final @NonNull List<TimeGraphEntry> fZoomEntryList;
4999a196
GB
493 private final long fZoomStartTime;
494 private final long fZoomEndTime;
495 private final long fResolution;
dfa0ef96 496 private final @NonNull IProgressMonitor fMonitor;
4999a196 497
dfa0ef96 498 public ZoomThread(@NonNull List<TimeGraphEntry> entryList, long startTime, long endTime, String name) {
4999a196
GB
499 super(name + " zoom"); //$NON-NLS-1$
500 fZoomEntryList = entryList;
501 fZoomStartTime = startTime;
502 fZoomEndTime = endTime;
503 fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
504 fMonitor = new NullProgressMonitor();
505 }
506
507 @Override
508 public void run() {
4999a196
GB
509 for (TimeGraphEntry entry : fZoomEntryList) {
510 if (fMonitor.isCanceled()) {
79ec0b89 511 return;
4999a196 512 }
dfa0ef96
GB
513 if (entry == null) {
514 break;
515 }
4999a196
GB
516 zoom(entry, fMonitor);
517 }
bec1f1ac
GB
518 /* Refresh the arrows when zooming */
519 List<ILinkEvent> events = getLinkList(fZoomStartTime, fZoomEndTime, fResolution, fMonitor);
79ec0b89 520 if (events != null) {
747adf5c 521 fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
79ec0b89
PT
522 redraw();
523 }
4999a196
GB
524 }
525
dfa0ef96 526 private void zoom(@NonNull TimeGraphEntry entry, @NonNull IProgressMonitor monitor) {
4999a196
GB
527 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
528 entry.setZoomedEventList(null);
529 } else {
530 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor);
531 if (zoomedEventList != null) {
532 entry.setZoomedEventList(zoomedEventList);
533 }
534 }
535 redraw();
a3188982 536 for (ITimeGraphEntry child : entry.getChildren()) {
4999a196
GB
537 if (fMonitor.isCanceled()) {
538 return;
539 }
a3188982
PT
540 if (child instanceof TimeGraphEntry) {
541 zoom((TimeGraphEntry) child, monitor);
542 }
4999a196
GB
543 }
544 }
545
546 public void cancel() {
547 fMonitor.setCanceled(true);
548 }
549 }
550
551 // ------------------------------------------------------------------------
552 // Constructors
553 // ------------------------------------------------------------------------
554
555 /**
747adf5c
PT
556 * Constructs a time graph view that contains either a time graph viewer or
557 * a time graph combo.
558 *
559 * By default, the view uses a time graph viewer. To use a time graph combo,
560 * the subclass constructor must call {@link #setTreeColumns(String[])} and
561 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
4999a196
GB
562 *
563 * @param id
564 * The id of the view
4999a196
GB
565 * @param pres
566 * The presentation provider
567 */
747adf5c 568 public AbstractTimeGraphView(String id, TimeGraphPresentationProvider pres) {
4999a196 569 super(id);
4999a196
GB
570 fPresentation = pres;
571 fDisplayWidth = Display.getDefault().getBounds().width;
572 }
573
574 // ------------------------------------------------------------------------
747adf5c 575 // Getters and setters
4999a196
GB
576 // ------------------------------------------------------------------------
577
747adf5c
PT
578 /**
579 * Getter for the time graph combo
580 *
581 * @return The time graph combo, or null if combo is not used
582 */
583 protected TimeGraphCombo getTimeGraphCombo() {
584 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
585 return ((TimeGraphComboWrapper) fTimeGraphWrapper).getTimeGraphCombo();
586 }
587 return null;
588 }
4999a196 589
747adf5c
PT
590 /**
591 * Getter for the time graph viewer
592 *
593 * @return The time graph viewer
594 */
595 protected TimeGraphViewer getTimeGraphViewer() {
596 return fTimeGraphWrapper.getTimeGraphViewer();
597 }
598
50c2da9e
GB
599 /**
600 * Getter for the presentation provider
601 *
602 * @return The time graph presentation provider
603 * @since 3.0
604 */
605 protected ITimeGraphPresentationProvider2 getPresentationProvider() {
606 return fPresentation;
607 }
608
747adf5c
PT
609 /**
610 * Sets the tree column labels.
611 * This should be called from the constructor.
612 *
613 * @param columns
614 * The array of tree column labels
615 */
616 protected void setTreeColumns(final String[] columns) {
617 fColumns = columns;
618 }
619
620 /**
621 * Sets the tree label provider.
622 * This should be called from the constructor.
623 *
624 * @param tlp
625 * The tree label provider
626 */
627 protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
628 fLabelProvider = tlp;
629 }
630
631 /**
632 * Sets the relative weight of each part of the time graph combo.
633 * This should be called from the constructor.
634 *
635 * @param weights
636 * The array (length 2) of relative weights of each part of the combo
637 */
638 protected void setWeight(final int[] weights) {
639 fWeight = weights;
640 }
4999a196 641
747adf5c
PT
642 /**
643 * Sets the filter column labels.
644 * This should be called from the constructor.
645 *
646 * @param filterColumns
647 * The array of filter column labels
648 */
649 protected void setFilterColumns(final String[] filterColumns) {
650 fFilterColumns = filterColumns;
651 }
4999a196 652
a03b7ee4
PT
653 /**
654 * Sets the filter label provider.
655 * This should be called from the constructor.
656 *
657 * @param labelProvider
658 * The filter label provider
659 *
660 * @since 3.0
661 */
662 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
663 fFilterLabelProvider = labelProvider;
664 }
665
747adf5c
PT
666 /**
667 * Gets the display width
668 *
669 * @return the display width
670 */
671 protected int getDisplayWidth() {
672 return fDisplayWidth;
673 }
4999a196 674
747adf5c
PT
675 /**
676 * Gets the comparator for the entries
677 *
678 * @return The entry comparator
679 */
680 protected Comparator<ITimeGraphEntry> getEntryComparator() {
681 return fEntryComparator;
682 }
4999a196 683
747adf5c
PT
684 /**
685 * Sets the comparator class for the entries
686 *
687 * @param comparator
688 * A comparator object
689 */
690 protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) {
691 fEntryComparator = comparator;
692 }
4999a196 693
747adf5c
PT
694 /**
695 * Gets the trace displayed in the view
696 *
697 * @return The trace
698 */
699 protected ITmfTrace getTrace() {
700 return fTrace;
701 }
4999a196 702
747adf5c
PT
703 /**
704 * Gets the start time
705 *
706 * @return The start time
707 */
708 protected long getStartTime() {
709 return fStartTime;
710 }
4999a196 711
747adf5c
PT
712 /**
713 * Sets the start time
714 *
715 * @param time
716 * The start time
717 */
718 protected void setStartTime(long time) {
719 fStartTime = time;
720 }
721
722 /**
723 * Gets the end time
724 *
725 * @return The end time
726 */
727 protected long getEndTime() {
728 return fEndTime;
729 }
730
731 /**
732 * Sets the end time
733 *
734 * @param time
735 * The end time
736 */
737 protected void setEndTime(long time) {
738 fEndTime = time;
739 }
740
5d021ccf
GB
741 /**
742 * Sets the auto-expand level to be used for the input of the view. The
743 * value 0 means that there is no auto-expand; 1 means that top-level
744 * elements are expanded, but not their children; 2 means that top-level
745 * elements are expanded, and their children, but not grand-children; and so
746 * on.
747 * <p>
748 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
749 * </p>
750 *
751 * @param level
752 * non-negative level, or <code>ALL_LEVELS</code> to expand all
753 * levels of the tree
754 */
755 protected void setAutoExpandLevel(int level) {
756 fAutoExpandLevel = level;
757 ITimeGraphWrapper tgWrapper = fTimeGraphWrapper;
758 if (tgWrapper != null) {
759 tgWrapper.setAutoExpandLevel(level);
760 }
761 }
762
747adf5c 763 /**
1cf25311
PT
764 * Gets the entry list for a trace
765 *
766 * @param trace
767 * the trace
747adf5c
PT
768 *
769 * @return the entry list map
1cf25311 770 * @since 3.0
747adf5c 771 */
1cf25311
PT
772 protected List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
773 synchronized (fEntryListMap) {
774 return fEntryListMap.get(trace);
775 }
747adf5c
PT
776 }
777
778 /**
1cf25311 779 * Adds a trace entry list to the entry list map
747adf5c
PT
780 *
781 * @param trace
782 * the trace to add
783 * @param list
1cf25311 784 * the list of time graph entries
747adf5c
PT
785 */
786 protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
1cf25311
PT
787 synchronized (fEntryListMap) {
788 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
789 }
790 }
791
792 /**
793 * Adds a list of entries to a trace's entry list
794 *
795 * @param trace
796 * the trace
797 * @param list
798 * the list of time graph entries to add
799 * @since 3.0
800 */
801 protected void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
802 synchronized (fEntryListMap) {
803 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
804 if (entryList == null) {
805 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
806 } else {
807 entryList.addAll(list);
808 }
809 }
810 }
811
812 /**
813 * Removes a list of entries from a trace's entry list
814 *
815 * @param trace
816 * the trace
817 * @param list
818 * the list of time graph entries to remove
819 * @since 3.0
820 */
821 protected void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
822 synchronized (fEntryListMap) {
823 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
824 if (entryList != null) {
825 entryList.removeAll(list);
826 }
747adf5c
PT
827 }
828 }
4999a196 829
747adf5c
PT
830 /**
831 * Text for the "next" button
832 *
833 * @return The "next" button text
834 */
835 protected String getNextText() {
836 return Messages.AbstractTimeGraphtView_NextText;
837 }
4999a196 838
747adf5c
PT
839 /**
840 * Tooltip for the "next" button
841 *
842 * @return Tooltip for the "next" button
843 */
844 protected String getNextTooltip() {
845 return Messages.AbstractTimeGraphView_NextTooltip;
846 }
4999a196 847
747adf5c
PT
848 /**
849 * Text for the "Previous" button
850 *
851 * @return The "Previous" button text
852 */
853 protected String getPrevText() {
854 return Messages.AbstractTimeGraphView_PreviousText;
855 }
4999a196 856
747adf5c
PT
857 /**
858 * Tooltip for the "previous" button
859 *
860 * @return Tooltip for the "previous" button
861 */
862 protected String getPrevTooltip() {
863 return Messages.AbstractTimeGraphView_PreviousTooltip;
864 }
4999a196 865
747adf5c
PT
866 // ------------------------------------------------------------------------
867 // ViewPart
868 // ------------------------------------------------------------------------
4999a196 869
747adf5c
PT
870 @Override
871 public void createPartControl(Composite parent) {
872 if (fColumns == null || fLabelProvider == null) {
873 fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
1cf25311
PT
874 TimeGraphViewer viewer = fTimeGraphWrapper.getTimeGraphViewer();
875 viewer.setTimeGraphContentProvider(new TimeGraphContentProvider());
747adf5c
PT
876 } else {
877 TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
878 fTimeGraphWrapper = wrapper;
879 TimeGraphCombo combo = wrapper.getTimeGraphCombo();
880 combo.setTreeContentProvider(new TreeContentProvider());
881 combo.setTreeLabelProvider(fLabelProvider);
882 combo.setTreeColumns(fColumns);
883 combo.setFilterContentProvider(new TreeContentProvider());
a03b7ee4 884 combo.setFilterLabelProvider(fFilterLabelProvider);
747adf5c 885 combo.setFilterColumns(fFilterColumns);
1cf25311 886 combo.setTimeGraphContentProvider(new TimeGraphContentProvider());
747adf5c 887 }
4999a196 888
747adf5c 889 fTimeGraphWrapper.setTimeGraphProvider(fPresentation);
5d021ccf 890 fTimeGraphWrapper.setAutoExpandLevel(fAutoExpandLevel);
4999a196 891
747adf5c 892 fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
4999a196
GB
893 @Override
894 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
895 final long startTime = event.getStartTime();
896 final long endTime = event.getEndTime();
f566d40a 897 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
0fcf3b09 898 broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView.this, range));
4999a196
GB
899 startZoomThread(startTime, endTime);
900 }
901 });
902
747adf5c 903 fTimeGraphWrapper.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
4999a196
GB
904 @Override
905 public void timeSelected(TimeGraphTimeEvent event) {
f566d40a
PT
906 TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime());
907 TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime());
0fcf3b09 908 broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView.this, startTime, endTime));
4999a196
GB
909 }
910 });
911
747adf5c 912 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
4999a196 913
0fcf3b09 914 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
747adf5c 915 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
0fcf3b09 916
4999a196
GB
917 // View Action Handling
918 makeActions();
919 contributeToActionBars();
920
921 ITmfTrace trace = getActiveTrace();
922 if (trace != null) {
923 traceSelected(new TmfTraceSelectedSignal(this, trace));
924 }
925
926 // make selection available to other views
747adf5c 927 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
4999a196
GB
928 }
929
930 @Override
931 public void setFocus() {
747adf5c 932 fTimeGraphWrapper.setFocus();
4999a196
GB
933 }
934
935 // ------------------------------------------------------------------------
936 // Signal handlers
937 // ------------------------------------------------------------------------
938
939 /**
940 * Handler for the trace opened signal.
941 *
942 * @param signal
943 * The incoming signal
944 * @since 2.0
945 */
946 @TmfSignalHandler
947 public void traceOpened(TmfTraceOpenedSignal signal) {
948 fTrace = signal.getTrace();
949 loadTrace();
950 }
951
952 /**
953 * Handler for the trace selected signal
954 *
955 * @param signal
956 * The incoming signal
957 */
958 @TmfSignalHandler
959 public void traceSelected(final TmfTraceSelectedSignal signal) {
960 if (signal.getTrace() == fTrace) {
961 return;
962 }
963 fTrace = signal.getTrace();
964
965 loadTrace();
966 }
967
968 /**
969 * Trace is closed: clear the data structures and the view
970 *
971 * @param signal
972 * the signal received
973 */
974 @TmfSignalHandler
975 public void traceClosed(final TmfTraceClosedSignal signal) {
976 synchronized (fBuildThreadMap) {
41cc4f90 977 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
1cf25311
PT
978 BuildThread buildThread = fBuildThreadMap.remove(trace);
979 if (buildThread != null) {
980 buildThread.cancel();
981 }
4999a196
GB
982 }
983 }
984 synchronized (fEntryListMap) {
985 fEntryListMap.remove(signal.getTrace());
986 }
987 if (signal.getTrace() == fTrace) {
988 fTrace = null;
989 fStartTime = 0;
990 fEndTime = 0;
991 if (fZoomThread != null) {
992 fZoomThread.cancel();
993 }
994 refresh();
995 }
996 }
997
998 /**
0fcf3b09 999 * Handler for the time synch signal
4999a196
GB
1000 *
1001 * @param signal
1002 * The signal that's received
1003 */
1004 @TmfSignalHandler
1005 public void synchToTime(final TmfTimeSynchSignal signal) {
1006 if (signal.getSource() == this || fTrace == null) {
1007 return;
1008 }
0fcf3b09
PT
1009 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1010 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
4999a196
GB
1011
1012 Display.getDefault().asyncExec(new Runnable() {
1013 @Override
1014 public void run() {
747adf5c 1015 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1016 return;
1017 }
0fcf3b09 1018 if (beginTime == endTime) {
747adf5c 1019 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
0fcf3b09 1020 } else {
747adf5c 1021 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
0fcf3b09 1022 }
747adf5c 1023 startZoomThread(fTimeGraphWrapper.getTimeGraphViewer().getTime0(), fTimeGraphWrapper.getTimeGraphViewer().getTime1());
4999a196 1024
0fcf3b09 1025 synchingToTime(beginTime);
4999a196
GB
1026 }
1027 });
1028 }
1029
1030 /**
0fcf3b09 1031 * Handler for the range synch signal
4999a196
GB
1032 *
1033 * @param signal
1034 * The signal that's received
1035 */
1036 @TmfSignalHandler
1037 public void synchToRange(final TmfRangeSynchSignal signal) {
1038 if (signal.getSource() == this || fTrace == null) {
1039 return;
1040 }
1041 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1042 return;
1043 }
1044 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1045 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
4999a196
GB
1046 Display.getDefault().asyncExec(new Runnable() {
1047 @Override
1048 public void run() {
747adf5c 1049 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1050 return;
1051 }
747adf5c 1052 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196
GB
1053 startZoomThread(startTime, endTime);
1054 }
1055 });
1056 }
1057
c1cd9635
MAL
1058 /**
1059 * @param signal the format of the timestamps was updated.
bec1f1ac 1060 * @since 2.1
c1cd9635
MAL
1061 */
1062 @TmfSignalHandler
1063 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
747adf5c 1064 fTimeGraphWrapper.refresh();
c1cd9635
MAL
1065 }
1066
4999a196
GB
1067 // ------------------------------------------------------------------------
1068 // Internal
1069 // ------------------------------------------------------------------------
1070
1071 private void loadTrace() {
1072 synchronized (fEntryListMap) {
1073 fEntryList = fEntryListMap.get(fTrace);
1074 if (fEntryList == null) {
50c2da9e 1075 rebuild();
4999a196
GB
1076 } else {
1077 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1078 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1079 refresh();
1080 }
1081 }
1082 }
1083
50c2da9e
GB
1084 /**
1085 * Forces a rebuild of the entries list, even if entries already exist for this trace
1086 * @since 3.0
1087 */
1088 protected void rebuild() {
1089 setStartTime(Long.MAX_VALUE);
1090 setEndTime(Long.MIN_VALUE);
6b8d11bd 1091 refresh();
dfa0ef96
GB
1092 ITmfTrace viewTrace = fTrace;
1093 if (viewTrace == null) {
1094 return;
1095 }
50c2da9e 1096 synchronized (fBuildThreadMap) {
dfa0ef96
GB
1097 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1098 if (trace == null) {
1099 break;
1100 }
1101 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
50c2da9e
GB
1102 fBuildThreadMap.put(trace, buildThread);
1103 buildThread.start();
1104 }
1105 }
1106 }
1107
4999a196
GB
1108 /**
1109 * Method called when synching to a given timestamp. Inheriting classes can
1110 * perform actions here to update the view at the given timestamp.
1111 *
1112 * @param time
1113 * The currently selected time
1114 */
1115 protected void synchingToTime(long time) {
1116
1117 }
1118
41cc4f90
GB
1119 /**
1120 * Return the list of traces whose data or analysis results will be used to
1121 * populate the view. By default, if the trace is an experiment, the traces
1122 * under it will be returned, otherwise, the trace itself is returned.
1123 *
1124 * A build thread will be started for each trace returned by this method,
1125 * some of which may receive events in live streaming mode.
1126 *
1127 * @param trace
1128 * The trace associated with this view
1129 * @return List of traces with data to display
1130 * @since 3.0
1131 */
dfa0ef96 1132 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
5db5a3a4 1133 return checkNotNull(Arrays.asList(TmfTraceManager.getTraceSet(trace)));
41cc4f90
GB
1134 }
1135
4999a196
GB
1136 /**
1137 * Build the entries list to show in this time graph
1138 *
1139 * Called from the BuildThread
1140 *
1141 * @param trace
1142 * The trace being built
1cf25311
PT
1143 * @param parentTrace
1144 * The parent of the trace set, or the trace itself
4999a196
GB
1145 * @param monitor
1146 * The progress monitor object
1cf25311 1147 * @since 3.0
4999a196 1148 */
dfa0ef96 1149 protected abstract void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
4999a196
GB
1150
1151 /**
1152 * Gets the list of event for an entry in a given timerange
1153 *
1154 * @param entry
1155 * The entry to get events for
1156 * @param startTime
1157 * Start of the time range
1158 * @param endTime
1159 * End of the time range
1160 * @param resolution
1161 * The resolution
1162 * @param monitor
1163 * The progress monitor object
1164 * @return The list of events for the entry
1165 */
dfa0ef96 1166 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
4999a196 1167 long startTime, long endTime, long resolution,
dfa0ef96 1168 @NonNull IProgressMonitor monitor);
4999a196 1169
bec1f1ac
GB
1170 /**
1171 * Gets the list of links (displayed as arrows) for a trace in a given
1172 * timerange. Default implementation returns an empty list.
1173 *
1174 * @param startTime
1175 * Start of the time range
1176 * @param endTime
1177 * End of the time range
1178 * @param resolution
1179 * The resolution
1180 * @param monitor
1181 * The progress monitor object
1182 * @return The list of link events
1183 * @since 2.1
1184 */
dfa0ef96
GB
1185 protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime,
1186 long resolution, @NonNull IProgressMonitor monitor) {
507b1336 1187 return new ArrayList<>();
bec1f1ac
GB
1188 }
1189
1190
4999a196
GB
1191 /**
1192 * Refresh the display
1193 */
1194 protected void refresh() {
08593856 1195 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
4999a196
GB
1196 @Override
1197 public void run() {
747adf5c 1198 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1199 return;
1200 }
1cf25311 1201 boolean hasEntries = false;
4999a196
GB
1202 synchronized (fEntryListMap) {
1203 fEntryList = fEntryListMap.get(fTrace);
1204 if (fEntryList == null) {
1cf25311
PT
1205 fEntryList = new CopyOnWriteArrayList<>();
1206 } else if (fEntryComparator != null) {
1207 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1208 Collections.sort(list, fEntryComparator);
1209 fEntryList.clear();
1210 fEntryList.addAll(list);
4999a196 1211 }
1cf25311 1212 hasEntries = fEntryList.size() != 0;
4999a196 1213 }
1cf25311
PT
1214 if (fEntryList != fTimeGraphWrapper.getInput()) {
1215 fTimeGraphWrapper.setInput(fEntryList);
1216 } else {
1217 fTimeGraphWrapper.refresh();
4999a196 1218 }
747adf5c 1219 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
4999a196 1220
0fcf3b09
PT
1221 long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1222 long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
4999a196
GB
1223 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1224 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1225 startTime = Math.max(startTime, fStartTime);
1226 endTime = Math.min(endTime, fEndTime);
747adf5c
PT
1227 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1228 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196 1229
1cf25311 1230 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
747adf5c
PT
1231 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1232 column.pack();
1233 }
1cf25311
PT
1234 if (hasEntries) {
1235 fPackDone = true;
1236 }
4999a196
GB
1237 }
1238
1239 startZoomThread(startTime, endTime);
1240 }
1241 });
1242 }
1243
1244 /**
1245 * Redraw the canvas
1246 */
1247 protected void redraw() {
1248 synchronized (fSyncObj) {
1249 if (fRedrawState == State.IDLE) {
1250 fRedrawState = State.BUSY;
1251 } else {
1252 fRedrawState = State.PENDING;
1253 return;
1254 }
1255 }
1256 Display.getDefault().asyncExec(new Runnable() {
1257 @Override
1258 public void run() {
747adf5c 1259 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1260 return;
1261 }
747adf5c
PT
1262 fTimeGraphWrapper.redraw();
1263 fTimeGraphWrapper.update();
4999a196
GB
1264 synchronized (fSyncObj) {
1265 if (fRedrawState == State.PENDING) {
1266 fRedrawState = State.IDLE;
1267 redraw();
1268 } else {
1269 fRedrawState = State.IDLE;
1270 }
1271 }
1272 }
1273 });
1274 }
1275
1276 private void startZoomThread(long startTime, long endTime) {
1277 if (fZoomThread != null) {
1278 fZoomThread.cancel();
1279 }
dfa0ef96
GB
1280 final List<TimeGraphEntry> entryList = fEntryList;
1281 if (entryList == null) {
1282 return;
1283 }
1284 fZoomThread = new ZoomThread(entryList, startTime, endTime, getName());
4999a196
GB
1285 fZoomThread.start();
1286 }
1287
1288 private void makeActions() {
747adf5c 1289 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
4999a196
GB
1290 fPreviousResourceAction.setText(getPrevText());
1291 fPreviousResourceAction.setToolTipText(getPrevTooltip());
747adf5c 1292 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
4999a196
GB
1293 fNextResourceAction.setText(getNextText());
1294 fNextResourceAction.setToolTipText(getNextTooltip());
1295 }
1296
1297 private void contributeToActionBars() {
1298 IActionBars bars = getViewSite().getActionBars();
1299 fillLocalToolBar(bars.getToolBarManager());
1300 }
1301
79ec0b89
PT
1302 /**
1303 * Add actions to local tool bar manager
1304 *
1305 * @param manager the tool bar manager
1306 */
1307 protected void fillLocalToolBar(IToolBarManager manager) {
747adf5c 1308 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
a03b7ee4 1309 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
747adf5c
PT
1310 manager.add(((TimeGraphComboWrapper) fTimeGraphWrapper).getShowFilterAction());
1311 }
4999a196 1312 }
747adf5c 1313 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
4999a196 1314 manager.add(new Separator());
747adf5c
PT
1315 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1316 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1317 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
4999a196
GB
1318 manager.add(fPreviousResourceAction);
1319 manager.add(fNextResourceAction);
747adf5c
PT
1320 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1321 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
4999a196
GB
1322 manager.add(new Separator());
1323 }
1324}
This page took 0.114649 seconds and 5 git commands to generate.