1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
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
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 *******************************************************************************/
17 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
;
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
;
25 import java
.util
.concurrent
.CopyOnWriteArrayList
;
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
.ITreeContentProvider
;
42 import org
.eclipse
.jface
.viewers
.TreeViewer
;
43 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
44 import org
.eclipse
.swt
.SWT
;
45 import org
.eclipse
.swt
.graphics
.Image
;
46 import org
.eclipse
.swt
.widgets
.Composite
;
47 import org
.eclipse
.swt
.widgets
.Display
;
48 import org
.eclipse
.swt
.widgets
.TreeColumn
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
55 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
56 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
57 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
58 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
60 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
61 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
62 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
63 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
64 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
65 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
66 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
67 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
68 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
69 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
70 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
75 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
76 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
77 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
78 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
79 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
80 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
81 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
82 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
83 import org
.eclipse
.ui
.IActionBars
;
86 * An abstract view all time graph views can inherit
88 * This view contains either a time graph viewer, or a time graph combo which is
89 * divided between a tree viewer on the left and a time graph viewer on the right.
91 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
{
93 /** Constant indicating that all levels of the time graph should be expanded */
94 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
103 // ------------------------------------------------------------------------
105 // ------------------------------------------------------------------------
107 /** The timegraph wrapper */
108 private ITimeGraphWrapper fTimeGraphWrapper
;
110 /** The selected trace */
111 private ITmfTrace fTrace
;
113 /** The timegraph entry list */
114 private List
<TimeGraphEntry
> fEntryList
;
116 /** The trace to entry list hash map */
117 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
119 /** The trace to filters hash map */
120 private final Map
<ITmfTrace
, ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
122 /** The trace to build thread hash map */
123 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
125 /** The start time */
126 private long fStartTime
= SWT
.DEFAULT
;
129 private long fEndTime
= SWT
.DEFAULT
;
131 /** The display width */
132 private final int fDisplayWidth
;
134 /** The zoom thread */
135 private ZoomThread fZoomThread
;
137 /** The next resource action */
138 private Action fNextResourceAction
;
140 /** The previous resource action */
141 private Action fPreviousResourceAction
;
143 /** A comparator class */
144 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
146 /** The redraw state used to prevent unnecessary queuing of display runnables */
147 private State fRedrawState
= State
.IDLE
;
149 /** The redraw synchronization object */
150 private final Object fSyncObj
= new Object();
152 /** The presentation provider for this view */
153 private final TimeGraphPresentationProvider fPresentation
;
155 /** The tree column label array, or null if combo is not used */
156 private String
[] fColumns
;
158 /** The tree label provider, or null if combo is not used */
159 private TreeLabelProvider fLabelProvider
= null;
161 /** The time graph content provider */
162 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
164 /** The relative weight of the sash, ignored if combo is not used */
165 private int[] fWeight
= { 1, 3 };
167 /** The filter column label array, or null if filter is not used */
168 private String
[] fFilterColumns
;
170 /** The pack done flag */
171 private boolean fPackDone
= false;
173 /** The filter label provider, or null if filter is not used */
174 private TreeLabelProvider fFilterLabelProvider
;
176 private int fAutoExpandLevel
= ALL_LEVELS
;
178 // ------------------------------------------------------------------------
180 // ------------------------------------------------------------------------
182 private interface ITimeGraphWrapper
{
184 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
);
186 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
);
188 TimeGraphViewer
getTimeGraphViewer();
190 void addSelectionListener(ITimeGraphSelectionListener listener
);
192 ISelectionProvider
getSelectionProvider();
196 boolean isDisposed();
200 void setInput(Object input
);
204 void setFilters(ViewerFilter
[] filters
);
206 ViewerFilter
[] getFilters();
212 void setAutoExpandLevel(int level
);
214 void setFilterColumns(String
[] columnNames
);
216 void setFilterContentProvider(ITreeContentProvider contentProvider
);
218 void setFilterLabelProvider(ITableLabelProvider labelProvider
);
220 IAction
getShowFilterDialogAction();
222 void performAlign(int offset
, int width
);
224 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
226 int getAvailableWidth(int requestedOffset
);
229 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
230 private TimeGraphViewer viewer
;
232 private TimeGraphViewerWrapper(Composite parent
, int style
) {
233 viewer
= new TimeGraphViewer(parent
, style
);
237 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
238 viewer
.setTimeGraphContentProvider(timeGraphContentProvider
);
242 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
243 viewer
.setTimeGraphProvider(timeGraphPresentationProvider
);
247 public TimeGraphViewer
getTimeGraphViewer() {
252 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
253 viewer
.addSelectionListener(listener
);
257 public ISelectionProvider
getSelectionProvider() {
258 return viewer
.getSelectionProvider();
262 public void setFocus() {
267 public boolean isDisposed() {
268 return viewer
.getControl().isDisposed();
272 public void setInput(Object input
) {
273 viewer
.setInput(input
);
277 public Object
getInput() {
278 return viewer
.getInput();
282 public void setFilterColumns(String
[] columnNames
) {
283 viewer
.setFilterColumns(columnNames
);
287 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
288 viewer
.setFilterContentProvider(contentProvider
);
292 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
293 viewer
.setFilterLabelProvider(labelProvider
);
297 public void setFilters(ViewerFilter
[] filters
) {
298 viewer
.setFilters(filters
);
302 public ViewerFilter
[] getFilters() {
303 return viewer
.getFilters();
307 public IAction
getShowFilterDialogAction() {
308 return viewer
.getShowFilterDialogAction();
312 public void refresh() {
317 public void redraw() {
318 viewer
.getControl().redraw();
322 public void update() {
323 viewer
.getControl().update();
327 public void setAutoExpandLevel(int level
) {
328 viewer
.setAutoExpandLevel(level
);
332 public void performAlign(int offset
, int width
) {
333 viewer
.performAlign(offset
, width
);
337 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
338 return viewer
.getTimeViewAlignmentInfo();
342 public int getAvailableWidth(int requestedOffset
) {
343 return viewer
.getAvailableWidth(requestedOffset
);
347 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
348 private TimeGraphCombo combo
;
350 private TimeGraphComboWrapper(Composite parent
, int style
) {
351 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
355 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
356 combo
.setTimeGraphContentProvider(timeGraphContentProvider
);
360 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
361 combo
.setTimeGraphProvider(timeGraphPresentationProvider
);
365 public TimeGraphViewer
getTimeGraphViewer() {
366 return combo
.getTimeGraphViewer();
370 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
371 combo
.addSelectionListener(listener
);
375 public ISelectionProvider
getSelectionProvider() {
376 return combo
.getTreeViewer();
380 public void setFocus() {
385 public boolean isDisposed() {
386 return combo
.isDisposed();
390 public void setInput(Object input
) {
391 combo
.setInput(input
);
395 public Object
getInput() {
396 return combo
.getInput();
400 public void setFilterColumns(String
[] columnNames
) {
401 combo
.setFilterColumns(columnNames
);
405 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
406 combo
.setFilterContentProvider(contentProvider
);
410 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
411 combo
.setFilterLabelProvider(labelProvider
);
415 public void setFilters(ViewerFilter
[] filters
) {
416 combo
.setFilters(filters
);
420 public ViewerFilter
[] getFilters() {
421 return combo
.getFilters();
425 public IAction
getShowFilterDialogAction() {
426 return combo
.getShowFilterDialogAction();
430 public void refresh() {
435 public void redraw() {
440 public void update() {
445 public void setAutoExpandLevel(int level
) {
446 combo
.setAutoExpandLevel(level
);
449 TimeGraphCombo
getTimeGraphCombo() {
453 TreeViewer
getTreeViewer() {
454 return combo
.getTreeViewer();
458 public void performAlign(int offset
, int width
) {
459 combo
.performAlign(offset
, width
);
463 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
464 return combo
.getTimeViewAlignmentInfo();
468 public int getAvailableWidth(int requestedOffset
) {
469 return combo
.getAvailableWidth(requestedOffset
);
474 * Base class to provide the labels for the tree viewer. Views extending
475 * this class typically need to override the getColumnText method if they
476 * have more than one column to display
478 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
481 public void addListener(ILabelProviderListener listener
) {
485 public void dispose() {
489 public boolean isLabelProperty(Object element
, String property
) {
494 public void removeListener(ILabelProviderListener listener
) {
498 public Image
getColumnImage(Object element
, int columnIndex
) {
503 public String
getColumnText(Object element
, int columnIndex
) {
504 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
505 if (columnIndex
== 0) {
506 return entry
.getName();
512 public Image
getImage(Object element
) {
517 public String
getText(Object element
) {
518 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
519 return entry
.getName();
524 private class BuildThread
extends Thread
{
525 private final @NonNull ITmfTrace fBuildTrace
;
526 private final @NonNull ITmfTrace fParentTrace
;
527 private final @NonNull IProgressMonitor fMonitor
;
529 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
530 super(name
+ " build"); //$NON-NLS-1$
532 fParentTrace
= parentTrace
;
533 fMonitor
= new NullProgressMonitor();
538 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
539 synchronized (fBuildThreadMap
) {
540 fBuildThreadMap
.remove(fBuildTrace
);
544 public void cancel() {
545 fMonitor
.setCanceled(true);
553 protected abstract class ZoomThread
extends Thread
{
554 private final long fZoomStartTime
;
555 private final long fZoomEndTime
;
556 private final long fResolution
;
557 private final @NonNull IProgressMonitor fMonitor
;
569 public ZoomThread(long startTime
, long endTime
, long resolution
) {
570 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
571 fZoomStartTime
= startTime
;
572 fZoomEndTime
= endTime
;
573 fResolution
= resolution
;
574 fMonitor
= new NullProgressMonitor();
578 * @return the zoom start time
580 public long getZoomStartTime() {
581 return fZoomStartTime
;
585 * @return the zoom end time
587 public long getZoomEndTime() {
592 * @return the resolution
594 public long getResolution() {
599 * @return the monitor
601 public @NonNull IProgressMonitor
getMonitor() {
606 * Cancel the zoom thread
608 public void cancel() {
609 fMonitor
.setCanceled(true);
613 private class ZoomThreadByEntry
extends ZoomThread
{
614 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
616 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
617 super(startTime
, endTime
, resolution
);
618 fZoomEntryList
= entryList
;
623 for (TimeGraphEntry entry
: fZoomEntryList
) {
624 if (getMonitor().isCanceled()) {
630 zoom(entry
, getMonitor());
632 /* Refresh the arrows when zooming */
633 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
634 if (events
!= null) {
635 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
638 /* Refresh the markers when zooming */
639 List
<IMarkerEvent
> markers
= getMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
640 if (markers
!= null) {
641 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setMarkers(markers
);
646 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
647 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
648 entry
.setZoomedEventList(null);
650 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
651 if (zoomedEventList
!= null) {
652 entry
.setZoomedEventList(zoomedEventList
);
656 for (ITimeGraphEntry child
: entry
.getChildren()) {
657 if (monitor
.isCanceled()) {
660 if (child
instanceof TimeGraphEntry
) {
661 zoom((TimeGraphEntry
) child
, monitor
);
668 // ------------------------------------------------------------------------
670 // ------------------------------------------------------------------------
673 * Constructs a time graph view that contains either a time graph viewer or
674 * a time graph combo.
676 * By default, the view uses a time graph viewer. To use a time graph combo,
677 * the subclass constructor must call {@link #setTreeColumns(String[])} and
678 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
683 * The presentation provider
685 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
687 fPresentation
= pres
;
688 fDisplayWidth
= Display
.getDefault().getBounds().width
;
691 // ------------------------------------------------------------------------
692 // Getters and setters
693 // ------------------------------------------------------------------------
696 * Getter for the time graph combo
698 * @return The time graph combo, or null if combo is not used
700 protected TimeGraphCombo
getTimeGraphCombo() {
701 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
702 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
708 * Getter for the time graph viewer
710 * @return The time graph viewer
712 protected TimeGraphViewer
getTimeGraphViewer() {
713 return fTimeGraphWrapper
.getTimeGraphViewer();
717 * Getter for the presentation provider
719 * @return The time graph presentation provider
721 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
722 return fPresentation
;
726 * Sets the tree column labels.
727 * This should be called from the constructor.
730 * The array of tree column labels
732 protected void setTreeColumns(final String
[] columns
) {
737 * Sets the tree label provider.
738 * This should be called from the constructor.
741 * The tree label provider
743 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
744 fLabelProvider
= tlp
;
748 * Sets the time graph content provider. This should be called from the
752 * The time graph content provider
755 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
756 fTimeGraphContentProvider
= tgcp
;
760 * Sets the relative weight of each part of the time graph combo.
761 * This should be called from the constructor.
764 * The array (length 2) of relative weights of each part of the combo
766 protected void setWeight(final int[] weights
) {
771 * Sets the filter column labels.
772 * This should be called from the constructor.
774 * @param filterColumns
775 * The array of filter column labels
777 protected void setFilterColumns(final String
[] filterColumns
) {
778 fFilterColumns
= filterColumns
;
782 * Sets the filter label provider.
783 * This should be called from the constructor.
785 * @param labelProvider
786 * The filter label provider
788 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
789 fFilterLabelProvider
= labelProvider
;
793 * Gets the display width
795 * @return the display width
797 protected int getDisplayWidth() {
798 return fDisplayWidth
;
802 * Gets the comparator for the entries
804 * @return The entry comparator
806 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
807 return fEntryComparator
;
811 * Sets the comparator class for the entries
814 * A comparator object
816 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
817 fEntryComparator
= comparator
;
821 * Gets the trace displayed in the view
825 protected ITmfTrace
getTrace() {
830 * Gets the start time
832 * @return The start time
834 protected long getStartTime() {
839 * Sets the start time
844 protected void setStartTime(long time
) {
851 * @return The end time
853 protected long getEndTime() {
863 protected void setEndTime(long time
) {
868 * Sets the auto-expand level to be used for the input of the view. The
869 * value 0 means that there is no auto-expand; 1 means that top-level
870 * elements are expanded, but not their children; 2 means that top-level
871 * elements are expanded, and their children, but not grand-children; and so
874 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
878 * non-negative level, or <code>ALL_LEVELS</code> to expand all
881 protected void setAutoExpandLevel(int level
) {
882 fAutoExpandLevel
= level
;
883 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
884 if (tgWrapper
!= null) {
885 tgWrapper
.setAutoExpandLevel(level
);
890 * Gets the entry list for a trace
895 * @return the entry list map
897 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
898 synchronized (fEntryListMap
) {
899 return fEntryListMap
.get(trace
);
904 * Adds a trace entry list to the entry list map
909 * the list of time graph entries
911 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
912 synchronized (fEntryListMap
) {
913 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
918 * Adds a list of entries to a trace's entry list
923 * the list of time graph entries to add
925 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
926 synchronized (fEntryListMap
) {
927 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
928 if (entryList
== null) {
929 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
931 entryList
.addAll(list
);
937 * Removes a list of entries from a trace's entry list
942 * the list of time graph entries to remove
944 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
945 synchronized (fEntryListMap
) {
946 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
947 if (entryList
!= null) {
948 entryList
.removeAll(list
);
954 * Text for the "next" button
956 * @return The "next" button text
958 protected String
getNextText() {
959 return Messages
.AbstractTimeGraphtView_NextText
;
963 * Tooltip for the "next" button
965 * @return Tooltip for the "next" button
967 protected String
getNextTooltip() {
968 return Messages
.AbstractTimeGraphView_NextTooltip
;
972 * Text for the "Previous" button
974 * @return The "Previous" button text
976 protected String
getPrevText() {
977 return Messages
.AbstractTimeGraphView_PreviousText
;
981 * Tooltip for the "previous" button
983 * @return Tooltip for the "previous" button
985 protected String
getPrevTooltip() {
986 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
989 // ------------------------------------------------------------------------
991 // ------------------------------------------------------------------------
994 public void createPartControl(Composite parent
) {
995 super.createPartControl(parent
);
996 if (fColumns
== null || fLabelProvider
== null) {
997 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
999 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
1000 fTimeGraphWrapper
= wrapper
;
1001 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
1002 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
1003 combo
.setTreeLabelProvider(fLabelProvider
);
1004 combo
.setTreeColumns(fColumns
);
1006 fTimeGraphWrapper
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
1007 fTimeGraphWrapper
.setFilterContentProvider(fTimeGraphContentProvider
);
1008 fTimeGraphWrapper
.setFilterLabelProvider(fFilterLabelProvider
);
1009 fTimeGraphWrapper
.setFilterColumns(fFilterColumns
);
1011 fTimeGraphWrapper
.setTimeGraphPresentationProvider(fPresentation
);
1012 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
1014 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1016 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
1017 final long startTime
= event
.getStartTime();
1018 final long endTime
= event
.getEndTime();
1019 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
1020 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
1021 startZoomThread(startTime
, endTime
);
1025 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1027 public void timeSelected(TimeGraphTimeEvent event
) {
1028 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
1029 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
1030 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
1034 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
1036 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
1037 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
1039 // View Action Handling
1041 contributeToActionBars();
1043 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
1044 if (trace
!= null) {
1045 traceSelected(new TmfTraceSelectedSignal(this, trace
));
1048 // make selection available to other views
1049 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
1053 public void setFocus() {
1054 fTimeGraphWrapper
.setFocus();
1057 // ------------------------------------------------------------------------
1059 // ------------------------------------------------------------------------
1062 * Handler for the trace opened signal.
1065 * The incoming signal
1068 public void traceOpened(TmfTraceOpenedSignal signal
) {
1069 loadTrace(signal
.getTrace());
1073 * Handler for the trace selected signal
1076 * The incoming signal
1079 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1080 if (signal
.getTrace() == fTrace
) {
1083 loadTrace(signal
.getTrace());
1087 * Trace is closed: clear the data structures and the view
1090 * the signal received
1093 public void traceClosed(final TmfTraceClosedSignal signal
) {
1094 synchronized (fBuildThreadMap
) {
1095 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
1096 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
1097 if (buildThread
!= null) {
1098 buildThread
.cancel();
1102 synchronized (fEntryListMap
) {
1103 fEntryListMap
.remove(signal
.getTrace());
1105 fFiltersMap
.remove(signal
.getTrace());
1106 if (signal
.getTrace() == fTrace
) {
1108 fStartTime
= SWT
.DEFAULT
;
1109 fEndTime
= SWT
.DEFAULT
;
1110 if (fZoomThread
!= null) {
1111 fZoomThread
.cancel();
1119 * Handler for the selection range signal.
1122 * The signal that's received
1126 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1127 if (signal
.getSource() == this || fTrace
== null) {
1130 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1131 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1133 Display
.getDefault().asyncExec(new Runnable() {
1136 if (fTimeGraphWrapper
.isDisposed()) {
1139 if (beginTime
== endTime
) {
1140 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1142 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
1144 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getTime0());
1150 * Handler for the window range signal.
1153 * The signal that's received
1157 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1158 if (signal
.getSource() == this || fTrace
== null) {
1161 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1164 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1165 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1166 Display
.getDefault().asyncExec(new Runnable() {
1169 if (fTimeGraphWrapper
.isDisposed()) {
1172 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1173 startZoomThread(startTime
, endTime
);
1179 * @param signal the format of the timestamps was updated.
1182 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1183 fTimeGraphWrapper
.refresh();
1186 // ------------------------------------------------------------------------
1188 // ------------------------------------------------------------------------
1190 private void loadTrace(final ITmfTrace trace
) {
1191 if (fZoomThread
!= null) {
1192 fZoomThread
.cancel();
1195 if (fTrace
!= null) {
1196 /* save the filters of the previous trace */
1197 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1200 synchronized (fEntryListMap
) {
1201 fEntryList
= fEntryListMap
.get(fTrace
);
1202 if (fEntryList
== null) {
1205 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1206 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1213 * Forces a rebuild of the entries list, even if entries already exist for this trace
1215 protected void rebuild() {
1216 setStartTime(Long
.MAX_VALUE
);
1217 setEndTime(Long
.MIN_VALUE
);
1219 ITmfTrace viewTrace
= fTrace
;
1220 if (viewTrace
== null) {
1223 synchronized (fBuildThreadMap
) {
1224 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1225 if (trace
== null) {
1228 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1229 fBuildThreadMap
.put(trace
, buildThread
);
1230 buildThread
.start();
1236 * Method called when synching to a given timestamp. Inheriting classes can
1237 * perform actions here to update the view at the given timestamp.
1240 * The currently selected time
1242 protected void synchingToTime(long time
) {
1247 * Return the list of traces whose data or analysis results will be used to
1248 * populate the view. By default, if the trace is an experiment, the traces
1249 * under it will be returned, otherwise, the trace itself is returned.
1251 * A build thread will be started for each trace returned by this method,
1252 * some of which may receive events in live streaming mode.
1255 * The trace associated with this view
1256 * @return List of traces with data to display
1258 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1259 return TmfTraceManager
.getTraceSet(trace
);
1263 * Build the entries list to show in this time graph
1265 * Called from the BuildThread
1268 * The trace being built
1269 * @param parentTrace
1270 * The parent of the trace set, or the trace itself
1272 * The progress monitor object
1274 protected abstract void buildEventList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1277 * Gets the list of event for an entry in a given timerange
1280 * The entry to get events for
1282 * Start of the time range
1284 * End of the time range
1288 * The progress monitor object
1289 * @return The list of events for the entry
1291 protected abstract @Nullable List
<ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1292 long startTime
, long endTime
, long resolution
,
1293 @NonNull IProgressMonitor monitor
);
1296 * Gets the list of links (displayed as arrows) for a trace in a given
1297 * timerange. Default implementation returns an empty list.
1300 * Start of the time range
1302 * End of the time range
1306 * The progress monitor object
1307 * @return The list of link events
1309 protected @Nullable List
<ILinkEvent
> getLinkList(long startTime
, long endTime
,
1310 long resolution
, @NonNull IProgressMonitor monitor
) {
1311 return new ArrayList
<>();
1315 * Gets the list of markers for a trace in a given time range. Default
1316 * implementation returns an empty list.
1319 * Start of the time range
1321 * End of the time range
1325 * The progress monitor object
1326 * @return The list of marker events
1329 protected @Nullable List
<IMarkerEvent
> getMarkerList(long startTime
, long endTime
,
1330 long resolution
, @NonNull IProgressMonitor monitor
) {
1331 return new ArrayList
<>();
1335 * Refresh the display
1337 protected void refresh() {
1338 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1339 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1342 if (fTimeGraphWrapper
.isDisposed()) {
1345 boolean hasEntries
= false;
1346 synchronized (fEntryListMap
) {
1347 fEntryList
= fEntryListMap
.get(fTrace
);
1348 if (fEntryList
== null) {
1349 fEntryList
= new CopyOnWriteArrayList
<>();
1350 } else if (fEntryComparator
!= null) {
1351 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1352 Collections
.sort(list
, fEntryComparator
);
1354 fEntryList
.addAll(list
);
1356 hasEntries
= fEntryList
.size() != 0;
1358 if (fEntryList
!= fTimeGraphWrapper
.getInput()) {
1359 fTimeGraphWrapper
.setInput(fEntryList
);
1360 /* restore the previously saved filters, if any */
1361 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1362 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1364 fTimeGraphWrapper
.refresh();
1366 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1367 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1368 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1370 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1371 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1372 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1373 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1374 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1375 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1376 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1377 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1378 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1380 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1381 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1390 startZoomThread(startTime
, endTime
);
1399 protected void redraw() {
1400 synchronized (fSyncObj
) {
1401 if (fRedrawState
== State
.IDLE
) {
1402 fRedrawState
= State
.BUSY
;
1404 fRedrawState
= State
.PENDING
;
1408 Display
.getDefault().asyncExec(new Runnable() {
1411 if (fTimeGraphWrapper
.isDisposed()) {
1414 fTimeGraphWrapper
.redraw();
1415 fTimeGraphWrapper
.update();
1416 synchronized (fSyncObj
) {
1417 if (fRedrawState
== State
.PENDING
) {
1418 fRedrawState
= State
.IDLE
;
1421 fRedrawState
= State
.IDLE
;
1428 private void startZoomThread(long startTime
, long endTime
) {
1429 boolean restart
= false;
1430 if (fZoomThread
!= null) {
1431 fZoomThread
.cancel();
1432 if (fZoomThread
.fZoomStartTime
== startTime
&& fZoomThread
.fZoomEndTime
== endTime
) {
1436 long resolution
= Math
.max(1, (endTime
- startTime
) / fDisplayWidth
);
1437 fZoomThread
= createZoomThread(startTime
, endTime
, resolution
, restart
);
1438 if (fZoomThread
!= null) {
1439 fZoomThread
.start();
1444 * Create a zoom thread.
1447 * the zoom start time
1453 * true if restarting zoom for the same time range
1454 * @return a zoom thread
1457 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1458 final List
<TimeGraphEntry
> entryList
= fEntryList
;
1459 if (entryList
== null) {
1462 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
1465 private void makeActions() {
1466 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1467 fPreviousResourceAction
.setText(getPrevText());
1468 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1469 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1470 fNextResourceAction
.setText(getNextText());
1471 fNextResourceAction
.setToolTipText(getNextTooltip());
1474 private void contributeToActionBars() {
1475 IActionBars bars
= getViewSite().getActionBars();
1476 fillLocalToolBar(bars
.getToolBarManager());
1480 * Add actions to local tool bar manager
1482 * @param manager the tool bar manager
1484 protected void fillLocalToolBar(IToolBarManager manager
) {
1485 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1486 manager
.add(fTimeGraphWrapper
.getShowFilterDialogAction());
1488 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1489 manager
.add(new Separator());
1490 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1491 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1492 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1493 manager
.add(fPreviousResourceAction
);
1494 manager
.add(fNextResourceAction
);
1495 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1496 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1497 manager
.add(new Separator());
1504 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
1505 if (fTimeGraphWrapper
== null) {
1508 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
1515 public int getAvailableWidth(int requestedOffset
) {
1516 if (fTimeGraphWrapper
== null) {
1519 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
1526 public void performAlign(int offset
, int width
) {
1527 if (fTimeGraphWrapper
!= null) {
1528 fTimeGraphWrapper
.performAlign(offset
, width
);