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