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