1 /*******************************************************************************
2 * Copyright (c) 2012, 2016 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 static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Collections
;
23 import java
.util
.Comparator
;
24 import java
.util
.HashMap
;
25 import java
.util
.LinkedHashSet
;
26 import java
.util
.List
;
29 import java
.util
.concurrent
.CopyOnWriteArrayList
;
30 import java
.util
.concurrent
.atomic
.AtomicInteger
;
31 import java
.util
.regex
.Matcher
;
32 import java
.util
.regex
.Pattern
;
34 import org
.eclipse
.core
.resources
.IFile
;
35 import org
.eclipse
.core
.resources
.IMarker
;
36 import org
.eclipse
.core
.resources
.IMarkerDelta
;
37 import org
.eclipse
.core
.resources
.IResource
;
38 import org
.eclipse
.core
.resources
.IResourceChangeEvent
;
39 import org
.eclipse
.core
.resources
.IResourceChangeListener
;
40 import org
.eclipse
.core
.resources
.IWorkspaceRunnable
;
41 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
42 import org
.eclipse
.core
.runtime
.CoreException
;
43 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
44 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
45 import org
.eclipse
.jdt
.annotation
.NonNull
;
46 import org
.eclipse
.jdt
.annotation
.Nullable
;
47 import org
.eclipse
.jface
.action
.Action
;
48 import org
.eclipse
.jface
.action
.IAction
;
49 import org
.eclipse
.jface
.action
.IMenuManager
;
50 import org
.eclipse
.jface
.action
.IStatusLineManager
;
51 import org
.eclipse
.jface
.action
.IToolBarManager
;
52 import org
.eclipse
.jface
.action
.Separator
;
53 import org
.eclipse
.jface
.viewers
.AbstractTreeViewer
;
54 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
55 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
56 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
57 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
58 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
59 import org
.eclipse
.jface
.viewers
.TreeViewer
;
60 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
61 import org
.eclipse
.osgi
.util
.NLS
;
62 import org
.eclipse
.swt
.SWT
;
63 import org
.eclipse
.swt
.events
.SelectionAdapter
;
64 import org
.eclipse
.swt
.events
.SelectionEvent
;
65 import org
.eclipse
.swt
.graphics
.Image
;
66 import org
.eclipse
.swt
.graphics
.RGBA
;
67 import org
.eclipse
.swt
.widgets
.Composite
;
68 import org
.eclipse
.swt
.widgets
.Display
;
69 import org
.eclipse
.swt
.widgets
.Tree
;
70 import org
.eclipse
.swt
.widgets
.TreeColumn
;
71 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
72 import org
.eclipse
.tracecompass
.tmf
.core
.resources
.ITmfMarker
;
73 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
74 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
75 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
76 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
77 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
78 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
79 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
80 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
81 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
82 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
83 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceAdapterManager
;
84 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
85 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
86 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
87 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
88 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
89 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
90 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphBookmarkListener
;
91 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
92 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
93 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
94 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
95 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
96 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphBookmarkEvent
;
97 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
98 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
99 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
100 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
101 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
102 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
103 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
104 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
105 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEventSource
;
106 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
107 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
108 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.MarkerEvent
;
109 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
110 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
111 import org
.eclipse
.ui
.IActionBars
;
114 * An abstract view all time graph views can inherit
116 * This view contains either a time graph viewer, or a time graph combo which is
117 * divided between a tree viewer on the left and a time graph viewer on the right.
119 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
, IResourceChangeListener
{
121 /** Constant indicating that all levels of the time graph should be expanded */
122 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
124 private static final Pattern RGBA_PATTERN
= Pattern
.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
133 // ------------------------------------------------------------------------
135 // ------------------------------------------------------------------------
137 /** The timegraph wrapper */
138 private ITimeGraphWrapper fTimeGraphWrapper
;
140 private AtomicInteger fDirty
= new AtomicInteger();
142 /** The selected trace */
143 private ITmfTrace fTrace
;
145 /** The selected trace editor file*/
146 private IFile fEditorFile
;
148 /** The timegraph entry list */
149 private List
<TimeGraphEntry
> fEntryList
;
151 /** The trace to entry list hash map */
152 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
154 /** The trace to filters hash map */
155 private final Map
<ITmfTrace
, @NonNull ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
157 /** The trace to view context hash map */
158 private final Map
<ITmfTrace
, ViewContext
> fViewContext
= new HashMap
<>();
160 /** The trace to marker event sources hash map */
161 private final Map
<ITmfTrace
, List
<IMarkerEventSource
>> fMarkerEventSourcesMap
= new HashMap
<>();
163 /** The trace to build thread hash map */
164 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
166 /** The start time */
167 private long fStartTime
= SWT
.DEFAULT
;
170 private long fEndTime
= SWT
.DEFAULT
;
172 /** The display width */
173 private final int fDisplayWidth
;
175 /** The zoom thread */
176 private ZoomThread fZoomThread
;
178 /** The next resource action */
179 private Action fNextResourceAction
;
181 /** The previous resource action */
182 private Action fPreviousResourceAction
;
184 /** A comparator class */
185 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
187 /** The redraw state used to prevent unnecessary queuing of display runnables */
188 private State fRedrawState
= State
.IDLE
;
190 /** The redraw synchronization object */
191 private final Object fSyncObj
= new Object();
193 /** The presentation provider for this view */
194 private final TimeGraphPresentationProvider fPresentation
;
196 /** The tree column label array, or null if combo is not used */
197 private String
[] fColumns
;
199 private Comparator
<ITimeGraphEntry
>[] fColumnComparators
;
201 /** The tree label provider, or null if combo is not used */
202 private TreeLabelProvider fLabelProvider
= null;
204 /** The time graph content provider */
205 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
207 /** The relative weight of the sash, ignored if combo is not used */
208 private int[] fWeight
= { 1, 3 };
210 /** The filter column label array, or null if filter is not used */
211 private String
[] fFilterColumns
;
213 /** The pack done flag */
214 private boolean fPackDone
= false;
216 /** The filter content provider, or null if filter is not used */
217 private ITreeContentProvider fFilterContentProvider
;
219 /** The filter label provider, or null if filter is not used */
220 private TreeLabelProvider fFilterLabelProvider
;
222 private int fAutoExpandLevel
= ALL_LEVELS
;
224 /** The default column index for sorting */
225 private int fInitialSortColumn
= 0;
227 /** The default column index for sorting */
228 private int fCurrentSortColumn
= 0;
230 /** The current sort direction */
231 private int fSortDirection
= SWT
.DOWN
;
233 /** Flag to indicate to reveal selection */
234 private volatile boolean fIsRevealSelection
= false;
236 // ------------------------------------------------------------------------
238 // ------------------------------------------------------------------------
240 private interface ITimeGraphWrapper
{
242 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
);
244 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
);
246 TimeGraphViewer
getTimeGraphViewer();
248 void addSelectionListener(ITimeGraphSelectionListener listener
);
250 ISelectionProvider
getSelectionProvider();
254 boolean isDisposed();
258 void setInput(Object input
);
262 void setFilters(@NonNull ViewerFilter
[] filters
);
264 @NonNull ViewerFilter
[] getFilters();
270 void setAutoExpandLevel(int level
);
272 void setFilterColumns(String
[] columnNames
);
274 void setFilterContentProvider(ITreeContentProvider contentProvider
);
276 void setFilterLabelProvider(ITableLabelProvider labelProvider
);
278 IAction
getShowFilterDialogAction();
280 void performAlign(int offset
, int width
);
282 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
284 int getAvailableWidth(int requestedOffset
);
286 ITimeGraphEntry
getSelection();
288 void setSelection(ITimeGraphEntry selection
);
291 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
292 private TimeGraphViewer viewer
;
294 private TimeGraphViewerWrapper(Composite parent
, int style
) {
295 viewer
= new TimeGraphViewer(parent
, style
);
299 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
300 viewer
.setTimeGraphContentProvider(timeGraphContentProvider
);
304 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
305 viewer
.setTimeGraphProvider(timeGraphPresentationProvider
);
309 public TimeGraphViewer
getTimeGraphViewer() {
314 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
315 viewer
.addSelectionListener(listener
);
319 public ISelectionProvider
getSelectionProvider() {
320 return viewer
.getSelectionProvider();
324 public void setFocus() {
329 public boolean isDisposed() {
330 return viewer
.getControl().isDisposed();
334 public void setInput(Object input
) {
335 viewer
.setInput(input
);
339 public Object
getInput() {
340 return viewer
.getInput();
344 public void setFilterColumns(String
[] columnNames
) {
345 viewer
.setFilterColumns(columnNames
);
349 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
350 viewer
.setFilterContentProvider(contentProvider
);
354 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
355 viewer
.setFilterLabelProvider(labelProvider
);
359 public void setFilters(@NonNull ViewerFilter
[] filters
) {
360 viewer
.setFilters(filters
);
364 public @NonNull ViewerFilter
[] getFilters() {
365 return viewer
.getFilters();
369 public IAction
getShowFilterDialogAction() {
370 return viewer
.getShowFilterDialogAction();
374 public void refresh() {
379 public void redraw() {
380 viewer
.getControl().redraw();
384 public void update() {
385 viewer
.getControl().update();
389 public void setAutoExpandLevel(int level
) {
390 viewer
.setAutoExpandLevel(level
);
394 public void performAlign(int offset
, int width
) {
395 viewer
.performAlign(offset
, width
);
399 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
400 return viewer
.getTimeViewAlignmentInfo();
404 public int getAvailableWidth(int requestedOffset
) {
405 return viewer
.getAvailableWidth(requestedOffset
);
409 public ITimeGraphEntry
getSelection() {
410 return viewer
.getSelection();
414 public void setSelection(ITimeGraphEntry selection
) {
415 viewer
.setSelection(selection
);
419 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
420 private TimeGraphCombo combo
;
422 private TimeGraphComboWrapper(Composite parent
, int style
) {
423 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
427 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
428 combo
.setTimeGraphContentProvider(timeGraphContentProvider
);
432 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
433 combo
.setTimeGraphProvider(timeGraphPresentationProvider
);
437 public TimeGraphViewer
getTimeGraphViewer() {
438 return combo
.getTimeGraphViewer();
442 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
443 combo
.addSelectionListener(listener
);
447 public ISelectionProvider
getSelectionProvider() {
448 return combo
.getTreeViewer();
452 public void setFocus() {
457 public boolean isDisposed() {
458 return combo
.isDisposed();
462 public void setInput(Object input
) {
463 combo
.setInput(input
);
467 public Object
getInput() {
468 return combo
.getInput();
472 public void setFilterColumns(String
[] columnNames
) {
473 combo
.setFilterColumns(columnNames
);
477 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
478 combo
.setFilterContentProvider(contentProvider
);
482 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
483 combo
.setFilterLabelProvider(labelProvider
);
487 public void setFilters(@NonNull ViewerFilter
[] filters
) {
488 combo
.setFilters(filters
);
492 public @NonNull ViewerFilter
[] getFilters() {
493 return combo
.getFilters();
497 public IAction
getShowFilterDialogAction() {
498 return combo
.getShowFilterDialogAction();
502 public void refresh() {
507 public void redraw() {
512 public void update() {
517 public void setAutoExpandLevel(int level
) {
518 combo
.setAutoExpandLevel(level
);
521 TimeGraphCombo
getTimeGraphCombo() {
525 TreeViewer
getTreeViewer() {
526 return combo
.getTreeViewer();
530 public void performAlign(int offset
, int width
) {
531 combo
.performAlign(offset
, width
);
535 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
536 return combo
.getTimeViewAlignmentInfo();
540 public int getAvailableWidth(int requestedOffset
) {
541 return combo
.getAvailableWidth(requestedOffset
);
545 public ITimeGraphEntry
getSelection() {
546 return combo
.getTimeGraphViewer().getSelection();
550 public void setSelection(ITimeGraphEntry selection
) {
551 combo
.setSelection(selection
);
556 * Base class to provide the labels for the tree viewer. Views extending
557 * this class typically need to override the getColumnText method if they
558 * have more than one column to display
560 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
563 public void addListener(ILabelProviderListener listener
) {
567 public void dispose() {
571 public boolean isLabelProperty(Object element
, String property
) {
576 public void removeListener(ILabelProviderListener listener
) {
580 public Image
getColumnImage(Object element
, int columnIndex
) {
585 public String
getColumnText(Object element
, int columnIndex
) {
586 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
587 if (columnIndex
== 0) {
588 return entry
.getName();
594 public Image
getImage(Object element
) {
599 public String
getText(Object element
) {
600 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
601 return entry
.getName();
606 private class BuildThread
extends Thread
{
607 private final @NonNull ITmfTrace fBuildTrace
;
608 private final @NonNull ITmfTrace fParentTrace
;
609 private final @NonNull IProgressMonitor fMonitor
;
611 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
612 super(name
+ " build"); //$NON-NLS-1$
614 fParentTrace
= parentTrace
;
615 fMonitor
= new NullProgressMonitor();
620 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
621 synchronized (fBuildThreadMap
) {
622 fBuildThreadMap
.remove(fBuildTrace
);
626 public void cancel() {
627 fMonitor
.setCanceled(true);
635 protected abstract class ZoomThread
extends Thread
{
636 private final long fZoomStartTime
;
637 private final long fZoomEndTime
;
638 private final long fResolution
;
639 private final @NonNull IProgressMonitor fMonitor
;
651 public ZoomThread(long startTime
, long endTime
, long resolution
) {
652 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
653 fZoomStartTime
= startTime
;
654 fZoomEndTime
= endTime
;
655 fResolution
= resolution
;
656 fMonitor
= new NullProgressMonitor();
660 * @return the zoom start time
662 public long getZoomStartTime() {
663 return fZoomStartTime
;
667 * @return the zoom end time
669 public long getZoomEndTime() {
674 * @return the resolution
676 public long getResolution() {
681 * @return the monitor
683 public @NonNull IProgressMonitor
getMonitor() {
688 * Cancel the zoom thread
690 public void cancel() {
691 fMonitor
.setCanceled(true);
695 public final void run() {
697 fDirty
.decrementAndGet();
701 * Run the zoom operation.
704 public abstract void doRun();
707 private class ZoomThreadByEntry
extends ZoomThread
{
708 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
710 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
711 super(startTime
, endTime
, resolution
);
712 fZoomEntryList
= entryList
;
716 public void doRun() {
717 for (TimeGraphEntry entry
: fZoomEntryList
) {
718 if (getMonitor().isCanceled()) {
724 zoom(entry
, getMonitor());
726 /* Refresh the arrows when zooming */
727 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
728 if (events
!= null) {
729 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
732 /* Refresh the view-specific markers when zooming */
733 List
<IMarkerEvent
> markers
= new ArrayList
<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
734 /* Refresh the trace-specific markers when zooming */
735 markers
.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
736 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(markers
);
740 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
741 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
742 entry
.setZoomedEventList(null);
744 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
745 if (zoomedEventList
!= null) {
746 entry
.setZoomedEventList(zoomedEventList
);
750 for (ITimeGraphEntry child
: entry
.getChildren()) {
751 if (monitor
.isCanceled()) {
754 if (child
instanceof TimeGraphEntry
) {
755 zoom((TimeGraphEntry
) child
, monitor
);
762 // ------------------------------------------------------------------------
764 // ------------------------------------------------------------------------
767 * Constructs a time graph view that contains either a time graph viewer or
768 * a time graph combo.
770 * By default, the view uses a time graph viewer. To use a time graph combo,
771 * the subclass constructor must call {@link #setTreeColumns(String[])} and
772 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
777 * The presentation provider
779 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
781 fPresentation
= pres
;
782 fDisplayWidth
= Display
.getDefault().getBounds().width
;
785 // ------------------------------------------------------------------------
786 // Getters and setters
787 // ------------------------------------------------------------------------
790 * Getter for the time graph combo
792 * @return The time graph combo, or null if combo is not used
794 protected TimeGraphCombo
getTimeGraphCombo() {
795 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
796 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
802 * Getter for the time graph viewer
804 * @return The time graph viewer
806 protected TimeGraphViewer
getTimeGraphViewer() {
807 return fTimeGraphWrapper
.getTimeGraphViewer();
811 * Getter for the presentation provider
813 * @return The time graph presentation provider
815 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
816 return fPresentation
;
820 * Sets the tree column labels.
822 * This should be called from the constructor.
825 * The array of tree column labels
827 protected void setTreeColumns(final String
[] columns
) {
828 setTreeColumns(columns
, null, 0);
832 * Sets the tree column labels.
834 * This should be called from the constructor.
837 * The array of tree column labels
839 * An array of column comparators for sorting of columns when
840 * clicking on column header
841 * @param initialSortColumn
842 * Index of column to sort initially
845 protected void setTreeColumns(final String
[] columns
, final Comparator
<ITimeGraphEntry
>[] comparators
, int initialSortColumn
) {
846 checkPartNotCreated();
848 fColumnComparators
= comparators
;
849 fInitialSortColumn
= initialSortColumn
;
853 * Sets the tree label provider.
855 * This should be called from the constructor.
858 * The tree label provider
860 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
861 checkPartNotCreated();
862 fLabelProvider
= tlp
;
866 * Sets the time graph content provider.
868 * This should be called from the constructor.
871 * The time graph content provider
874 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
875 checkPartNotCreated();
876 fTimeGraphContentProvider
= tgcp
;
880 * Sets the relative weight of each part of the time graph combo.
882 * This should be called from the constructor.
885 * The array (length 2) of relative weights of each part of the combo
887 protected void setWeight(final int[] weights
) {
888 checkPartNotCreated();
893 * Sets the filter column labels.
895 * This should be called from the constructor.
897 * @param filterColumns
898 * The array of filter column labels
900 protected void setFilterColumns(final String
[] filterColumns
) {
901 checkPartNotCreated();
902 fFilterColumns
= filterColumns
;
906 * Sets the filter content provider.
908 * This should be called from the constructor.
910 * @param contentProvider
911 * The filter content provider
914 protected void setFilterContentProvider(final ITreeContentProvider contentProvider
) {
915 checkPartNotCreated();
916 fFilterContentProvider
= contentProvider
;
920 * Sets the filter label provider.
922 * This should be called from the constructor.
924 * @param labelProvider
925 * The filter label provider
927 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
928 checkPartNotCreated();
929 fFilterLabelProvider
= labelProvider
;
932 private void checkPartNotCreated() {
933 if (getParentComposite() != null) {
934 throw new IllegalStateException("This method must be called before createPartControl."); //$NON-NLS-1$
939 * Gets the display width
941 * @return the display width
943 protected int getDisplayWidth() {
944 return fDisplayWidth
;
948 * Gets the comparator for the entries
950 * @return The entry comparator
952 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
953 return fEntryComparator
;
957 * Sets the comparator class for the entries.
959 * This comparator will apply recursively to entries that implement
960 * {@link TimeGraphEntry#sortChildren(Comparator)}.
963 * A comparator object
965 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
966 fEntryComparator
= comparator
;
970 * Gets the trace displayed in the view
974 protected ITmfTrace
getTrace() {
979 * Gets the start time
981 * @return The start time
983 protected long getStartTime() {
988 * Sets the start time
993 protected void setStartTime(long time
) {
1000 * @return The end time
1002 protected long getEndTime() {
1012 protected void setEndTime(long time
) {
1017 * Sets the auto-expand level to be used for the input of the view. The
1018 * value 0 means that there is no auto-expand; 1 means that top-level
1019 * elements are expanded, but not their children; 2 means that top-level
1020 * elements are expanded, and their children, but not grand-children; and so
1023 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1027 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1028 * levels of the tree
1030 protected void setAutoExpandLevel(int level
) {
1031 fAutoExpandLevel
= level
;
1032 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
1033 if (tgWrapper
!= null) {
1034 tgWrapper
.setAutoExpandLevel(level
);
1039 * Gets the entry list for a trace
1044 * @return the entry list map
1046 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
1047 synchronized (fEntryListMap
) {
1048 return fEntryListMap
.get(trace
);
1053 * Adds a trace entry list to the entry list map
1058 * the list of time graph entries
1060 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1061 synchronized (fEntryListMap
) {
1062 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1067 * Adds a list of entries to a trace's entry list
1072 * the list of time graph entries to add
1074 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1075 synchronized (fEntryListMap
) {
1076 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1077 if (entryList
== null) {
1078 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1080 entryList
.addAll(list
);
1086 * Removes a list of entries from a trace's entry list
1091 * the list of time graph entries to remove
1093 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1094 synchronized (fEntryListMap
) {
1095 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1096 if (entryList
!= null) {
1097 entryList
.removeAll(list
);
1103 * Text for the "next" button
1105 * @return The "next" button text
1107 protected String
getNextText() {
1108 return Messages
.AbstractTimeGraphtView_NextText
;
1112 * Tooltip for the "next" button
1114 * @return Tooltip for the "next" button
1116 protected String
getNextTooltip() {
1117 return Messages
.AbstractTimeGraphView_NextTooltip
;
1121 * Text for the "Previous" button
1123 * @return The "Previous" button text
1125 protected String
getPrevText() {
1126 return Messages
.AbstractTimeGraphView_PreviousText
;
1130 * Tooltip for the "previous" button
1132 * @return Tooltip for the "previous" button
1134 protected String
getPrevTooltip() {
1135 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
1138 // ------------------------------------------------------------------------
1140 // ------------------------------------------------------------------------
1143 public void createPartControl(Composite parent
) {
1144 super.createPartControl(parent
);
1145 if (fColumns
== null || fLabelProvider
== null) {
1146 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
1148 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
1149 fTimeGraphWrapper
= wrapper
;
1150 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
1151 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
1152 combo
.setTreeLabelProvider(fLabelProvider
);
1153 combo
.setTreeColumns(fColumns
);
1154 if (fColumnComparators
!= null) {
1155 createColumnSelectionListener(combo
.getTreeViewer());
1158 fTimeGraphWrapper
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
1159 fTimeGraphWrapper
.setFilterContentProvider(fFilterContentProvider
!= null ? fFilterContentProvider
: fTimeGraphContentProvider
);
1160 fTimeGraphWrapper
.setFilterLabelProvider(fFilterLabelProvider
);
1161 fTimeGraphWrapper
.setFilterColumns(fFilterColumns
);
1163 fTimeGraphWrapper
.setTimeGraphPresentationProvider(fPresentation
);
1164 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
1166 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1168 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
1169 final long startTime
= event
.getStartTime();
1170 final long endTime
= event
.getEndTime();
1171 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
1172 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
1173 startZoomThread(startTime
, endTime
);
1177 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1179 public void timeSelected(TimeGraphTimeEvent event
) {
1180 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
1181 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
1182 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
1186 fTimeGraphWrapper
.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1188 public void bookmarkAdded(final TimeGraphBookmarkEvent event
) {
1190 ResourcesPlugin
.getWorkspace().run(new IWorkspaceRunnable() {
1192 public void run(IProgressMonitor monitor
) throws CoreException
{
1193 IMarkerEvent bookmark
= event
.getBookmark();
1194 IMarker marker
= fEditorFile
.createMarker(IMarker
.BOOKMARK
);
1195 marker
.setAttribute(IMarker
.MESSAGE
, bookmark
.getLabel());
1196 marker
.setAttribute(ITmfMarker
.MARKER_TIME
, Long
.toString(bookmark
.getTime()));
1197 if (bookmark
.getDuration() > 0) {
1198 marker
.setAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(bookmark
.getDuration()));
1199 marker
.setAttribute(IMarker
.LOCATION
,
1200 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTimeRange
,
1201 new TmfNanoTimestamp(bookmark
.getTime()),
1202 new TmfNanoTimestamp(bookmark
.getTime() + bookmark
.getDuration())));
1204 marker
.setAttribute(IMarker
.LOCATION
,
1205 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTime
,
1206 new TmfNanoTimestamp(bookmark
.getTime())));
1208 marker
.setAttribute(ITmfMarker
.MARKER_COLOR
, bookmark
.getColor().toString());
1211 } catch (CoreException e
) {
1212 Activator
.getDefault().logError(e
.getMessage());
1217 public void bookmarkRemoved(TimeGraphBookmarkEvent event
) {
1219 IMarkerEvent bookmark
= event
.getBookmark();
1220 IMarker
[] markers
= fEditorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1221 for (IMarker marker
: markers
) {
1222 if (bookmark
.getLabel().equals(marker
.getAttribute(IMarker
.MESSAGE
)) &&
1223 Long
.toString(bookmark
.getTime()).equals(marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null)) &&
1224 Long
.toString(bookmark
.getDuration()).equals(marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0))) &&
1225 bookmark
.getColor().toString().equals(marker
.getAttribute(ITmfMarker
.MARKER_COLOR
))) {
1230 } catch (CoreException e
) {
1231 Activator
.getDefault().logError(e
.getMessage());
1236 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
1238 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
1239 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
1241 // View Action Handling
1243 contributeToActionBars();
1245 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
1246 if (trace
!= null) {
1247 traceSelected(new TmfTraceSelectedSignal(this, trace
));
1250 // make selection available to other views
1251 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
1253 ResourcesPlugin
.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent
.POST_CHANGE
);
1257 public void setFocus() {
1258 fTimeGraphWrapper
.setFocus();
1262 public void dispose() {
1264 ResourcesPlugin
.getWorkspace().removeResourceChangeListener(this);
1271 public void resourceChanged(final IResourceChangeEvent event
) {
1272 for (final IMarkerDelta delta
: event
.findMarkerDeltas(IMarker
.BOOKMARK
, false)) {
1273 if (delta
.getResource().equals(fEditorFile
)) {
1274 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1281 private static List
<IMarkerEvent
> refreshBookmarks(final IFile editorFile
) {
1282 List
<IMarkerEvent
> bookmarks
= new ArrayList
<>();
1283 if (editorFile
== null || !editorFile
.exists()) {
1287 IMarker
[] markers
= editorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1288 for (IMarker marker
: markers
) {
1289 String label
= marker
.getAttribute(IMarker
.MESSAGE
, (String
) null);
1290 String time
= marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null);
1291 String duration
= marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0));
1292 String rgba
= marker
.getAttribute(ITmfMarker
.MARKER_COLOR
, (String
) null);
1293 if (label
!= null && time
!= null && rgba
!= null) {
1294 Matcher matcher
= RGBA_PATTERN
.matcher(rgba
);
1295 if (matcher
.matches()) {
1297 int red
= Integer
.valueOf(matcher
.group(1));
1298 int green
= Integer
.valueOf(matcher
.group(2));
1299 int blue
= Integer
.valueOf(matcher
.group(3));
1300 int alpha
= Integer
.valueOf(matcher
.group(4));
1301 RGBA color
= new RGBA(red
, green
, blue
, alpha
);
1302 bookmarks
.add(new MarkerEvent(null, Long
.valueOf(time
), Long
.valueOf(duration
), IMarkerEvent
.BOOKMARKS
, color
, label
, true));
1303 } catch (NumberFormatException e
) {
1304 Activator
.getDefault().logError(e
.getMessage());
1309 } catch (CoreException e
) {
1310 Activator
.getDefault().logError(e
.getMessage());
1317 // ------------------------------------------------------------------------
1319 // ------------------------------------------------------------------------
1322 * Handler for the trace opened signal.
1325 * The incoming signal
1328 public void traceOpened(TmfTraceOpenedSignal signal
) {
1329 loadTrace(signal
.getTrace());
1333 * Handler for the trace selected signal
1336 * The incoming signal
1339 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1340 if (signal
.getTrace() == fTrace
) {
1343 loadTrace(signal
.getTrace());
1347 * Trace is closed: clear the data structures and the view
1350 * the signal received
1353 public void traceClosed(final TmfTraceClosedSignal signal
) {
1354 synchronized (fBuildThreadMap
) {
1355 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
1356 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
1357 if (buildThread
!= null) {
1358 buildThread
.cancel();
1362 fMarkerEventSourcesMap
.remove(signal
.getTrace());
1363 synchronized (fEntryListMap
) {
1364 fEntryListMap
.remove(signal
.getTrace());
1366 fFiltersMap
.remove(signal
.getTrace());
1367 fViewContext
.remove(signal
.getTrace());
1368 if (signal
.getTrace() == fTrace
) {
1371 fStartTime
= SWT
.DEFAULT
;
1372 fEndTime
= SWT
.DEFAULT
;
1373 if (fZoomThread
!= null) {
1374 fZoomThread
.cancel();
1382 * Handler for the selection range signal.
1385 * The signal that's received
1389 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1390 if (signal
.getSource() == this || fTrace
== null) {
1393 final long beginTime
= signal
.getBeginTime().toNanos();
1394 final long endTime
= signal
.getEndTime().toNanos();
1396 Display
.getDefault().asyncExec(new Runnable() {
1399 if (fTimeGraphWrapper
.isDisposed()) {
1402 if (beginTime
== endTime
) {
1403 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1405 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
, true);
1407 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getSelectionBegin());
1413 * Handler for the window range signal.
1416 * The signal that's received
1420 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1421 if (signal
.getSource() == this || fTrace
== null) {
1424 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1427 final long startTime
= signal
.getCurrentRange().getStartTime().toNanos();
1428 final long endTime
= signal
.getCurrentRange().getEndTime().toNanos();
1429 Display
.getDefault().asyncExec(new Runnable() {
1432 if (fTimeGraphWrapper
.isDisposed()) {
1435 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1436 startZoomThread(startTime
, endTime
);
1442 * @param signal the format of the timestamps was updated.
1445 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1446 fTimeGraphWrapper
.refresh();
1449 // ------------------------------------------------------------------------
1451 // ------------------------------------------------------------------------
1453 private void loadTrace(final ITmfTrace trace
) {
1454 if (fZoomThread
!= null) {
1455 fZoomThread
.cancel();
1458 if (fTrace
!= null) {
1459 /* save the filters of the previous trace */
1460 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1461 fViewContext
.put(fTrace
, new ViewContext(fCurrentSortColumn
, fSortDirection
, fTimeGraphWrapper
.getSelection()));
1464 restoreViewContext();
1465 fEditorFile
= TmfTraceManager
.getInstance().getTraceEditorFile(trace
);
1466 synchronized (fEntryListMap
) {
1467 fEntryList
= fEntryListMap
.get(fTrace
);
1468 if (fEntryList
== null) {
1471 fStartTime
= fTrace
.getStartTime().toNanos();
1472 fEndTime
= fTrace
.getEndTime().toNanos();
1479 * Forces a rebuild of the entries list, even if entries already exist for this trace
1481 protected void rebuild() {
1482 setStartTime(Long
.MAX_VALUE
);
1483 setEndTime(Long
.MIN_VALUE
);
1485 ITmfTrace viewTrace
= fTrace
;
1486 if (viewTrace
== null) {
1489 List
<IMarkerEventSource
> markerEventSources
= new ArrayList
<>();
1490 synchronized (fBuildThreadMap
) {
1491 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1492 if (trace
== null) {
1495 markerEventSources
.addAll(TmfTraceAdapterManager
.getAdapters(trace
, IMarkerEventSource
.class));
1496 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1497 fBuildThreadMap
.put(trace
, buildThread
);
1498 buildThread
.start();
1501 fMarkerEventSourcesMap
.put(viewTrace
, markerEventSources
);
1505 * Method called when synching to a given timestamp. Inheriting classes can
1506 * perform actions here to update the view at the given timestamp.
1509 * The currently selected time
1511 protected void synchingToTime(long time
) {
1516 * Return the list of traces whose data or analysis results will be used to
1517 * populate the view. By default, if the trace is an experiment, the traces
1518 * under it will be returned, otherwise, the trace itself is returned.
1520 * A build thread will be started for each trace returned by this method,
1521 * some of which may receive events in live streaming mode.
1524 * The trace associated with this view
1525 * @return List of traces with data to display
1527 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1528 return TmfTraceManager
.getTraceSet(trace
);
1532 * Build the entries list to show in this time graph
1534 * Called from the BuildThread
1537 * The trace being built
1538 * @param parentTrace
1539 * The parent of the trace set, or the trace itself
1541 * The progress monitor object
1543 protected abstract void buildEventList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1546 * Gets the list of event for an entry in a given timerange
1549 * The entry to get events for
1551 * Start of the time range
1553 * End of the time range
1557 * The progress monitor object
1558 * @return The list of events for the entry
1560 protected abstract @Nullable List
<@NonNull ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1561 long startTime
, long endTime
, long resolution
,
1562 @NonNull IProgressMonitor monitor
);
1565 * Gets the list of links (displayed as arrows) for a trace in a given
1566 * timerange. Default implementation returns an empty list.
1569 * Start of the time range
1571 * End of the time range
1575 * The progress monitor object
1576 * @return The list of link events
1578 protected @Nullable List
<@NonNull ILinkEvent
> getLinkList(long startTime
, long endTime
,
1579 long resolution
, @NonNull IProgressMonitor monitor
) {
1580 return new ArrayList
<>();
1584 * Gets the list of view-specific marker categories. Default implementation
1585 * returns an empty list.
1587 * @return The list of marker categories
1590 protected @NonNull List
<String
> getViewMarkerCategories() {
1591 return new ArrayList
<>();
1595 * Gets the list of view-specific markers for a trace in a given time range.
1596 * Default implementation returns an empty list.
1599 * Start of the time range
1601 * End of the time range
1605 * The progress monitor object
1606 * @return The list of marker events
1609 protected @NonNull List
<IMarkerEvent
> getViewMarkerList(long startTime
, long endTime
,
1610 long resolution
, @NonNull IProgressMonitor monitor
) {
1611 return new ArrayList
<>();
1615 * Gets the list of trace-specific markers for a trace in a given time range.
1618 * Start of the time range
1620 * End of the time range
1624 * The progress monitor object
1625 * @return The list of marker events
1628 protected @NonNull List
<IMarkerEvent
> getTraceMarkerList(long startTime
, long endTime
,
1629 long resolution
, @NonNull IProgressMonitor monitor
) {
1630 List
<IMarkerEvent
> markers
= new ArrayList
<>();
1631 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1632 for (String category
: markerEventSource
.getMarkerCategories()) {
1633 if (monitor
.isCanceled()) {
1636 markers
.addAll(markerEventSource
.getMarkerList(checkNotNull(category
), startTime
, endTime
, resolution
, monitor
));
1643 * Get the list of current marker categories.
1645 * @return The list of marker categories
1648 private @NonNull List
<String
> getMarkerCategories() {
1649 Set
<String
> categories
= new LinkedHashSet
<>(getViewMarkerCategories());
1650 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1651 categories
.addAll(markerEventSource
.getMarkerCategories());
1653 return new ArrayList
<>(categories
);
1657 * Gets the list of marker event sources for a given trace.
1661 * @return The list of marker event sources
1664 private @NonNull List
<IMarkerEventSource
> getMarkerEventSources(ITmfTrace trace
) {
1665 List
<IMarkerEventSource
> markerEventSources
= fMarkerEventSourcesMap
.get(trace
);
1666 if (markerEventSources
== null) {
1667 markerEventSources
= checkNotNull(Collections
.<IMarkerEventSource
>emptyList());
1669 return markerEventSources
;
1673 * Refresh the display
1675 protected void refresh() {
1676 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1677 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1680 if (fTimeGraphWrapper
.isDisposed()) {
1683 boolean hasEntries
= false;
1684 synchronized (fEntryListMap
) {
1685 fEntryList
= fEntryListMap
.get(fTrace
);
1686 if (fEntryList
== null) {
1687 fEntryList
= new CopyOnWriteArrayList
<>();
1688 } else if (fEntryComparator
!= null) {
1689 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1690 Collections
.sort(list
, fEntryComparator
);
1691 for (ITimeGraphEntry entry
: list
) {
1692 sortChildren(entry
, fEntryComparator
);
1695 fEntryList
.addAll(list
);
1697 hasEntries
= !fEntryList
.isEmpty();
1699 boolean inputChanged
= fEntryList
!= fTimeGraphWrapper
.getInput();
1700 TimeGraphCombo combo
= getTimeGraphCombo();
1702 // Set redraw to false to only draw once
1703 if (combo
!= null) {
1704 combo
.getTreeViewer().getTree().setRedraw(false);
1706 getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
1708 fTimeGraphWrapper
.setInput(fEntryList
);
1709 /* restore the previously saved filters, if any */
1710 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1711 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1712 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1713 fTimeGraphWrapper
.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1714 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(null);
1717 fTimeGraphWrapper
.refresh();
1720 if (fIsRevealSelection
) {
1721 fIsRevealSelection
= false;
1722 ITimeGraphEntry entry1
= fTimeGraphWrapper
.getSelection();
1723 fTimeGraphWrapper
.setSelection(entry1
);
1726 if (combo
!= null) {
1727 combo
.getTreeViewer().getTree().setRedraw(true);
1729 getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
1731 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1732 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1733 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1735 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1736 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().toNanos();
1737 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().toNanos();
1738 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().toNanos();
1739 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().toNanos();
1740 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1741 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1742 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
, false);
1743 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1745 if (inputChanged
&& selectionBeginTime
!= SWT
.DEFAULT
) {
1746 synchingToTime(selectionBeginTime
);
1749 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1750 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1759 startZoomThread(startTime
, endTime
);
1769 protected void redraw() {
1770 synchronized (fSyncObj
) {
1771 if (fRedrawState
== State
.IDLE
) {
1772 fRedrawState
= State
.BUSY
;
1774 fRedrawState
= State
.PENDING
;
1778 Display
.getDefault().asyncExec(new Runnable() {
1781 if (fTimeGraphWrapper
.isDisposed()) {
1784 fTimeGraphWrapper
.redraw();
1785 fTimeGraphWrapper
.update();
1786 synchronized (fSyncObj
) {
1787 if (fRedrawState
== State
.PENDING
) {
1788 fRedrawState
= State
.IDLE
;
1791 fRedrawState
= State
.IDLE
;
1798 private void sortChildren(ITimeGraphEntry entry
, Comparator
<ITimeGraphEntry
> comparator
) {
1799 if (entry
instanceof TimeGraphEntry
) {
1800 ((TimeGraphEntry
) entry
).sortChildren(comparator
);
1802 for (ITimeGraphEntry child
: entry
.getChildren()) {
1803 sortChildren(child
, comparator
);
1808 * Start or restart the zoom thread.
1811 * the zoom start time
1816 protected final void startZoomThread(long startTime
, long endTime
) {
1817 fDirty
.incrementAndGet();
1818 boolean restart
= false;
1819 if (fZoomThread
!= null) {
1820 fZoomThread
.cancel();
1821 if (fZoomThread
.fZoomStartTime
== startTime
&& fZoomThread
.fZoomEndTime
== endTime
) {
1825 long resolution
= Math
.max(1, (endTime
- startTime
) / fDisplayWidth
);
1826 fZoomThread
= createZoomThread(startTime
, endTime
, resolution
, restart
);
1827 if (fZoomThread
!= null) {
1828 fZoomThread
.start();
1830 fDirty
.decrementAndGet();
1835 * Create a zoom thread.
1838 * the zoom start time
1844 * true if restarting zoom for the same time range
1845 * @return a zoom thread
1848 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1849 final List
<TimeGraphEntry
> entryList
= fEntryList
;
1850 if (entryList
== null) {
1853 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
1856 private void makeActions() {
1857 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1858 fPreviousResourceAction
.setText(getPrevText());
1859 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1860 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1861 fNextResourceAction
.setText(getNextText());
1862 fNextResourceAction
.setToolTipText(getNextTooltip());
1865 private void contributeToActionBars() {
1866 IActionBars bars
= getViewSite().getActionBars();
1867 fillLocalToolBar(bars
.getToolBarManager());
1868 fillLocalMenu(bars
.getMenuManager());
1872 * Add actions to local tool bar manager
1874 * @param manager the tool bar manager
1876 protected void fillLocalToolBar(IToolBarManager manager
) {
1877 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1878 manager
.add(fTimeGraphWrapper
.getShowFilterDialogAction());
1880 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1881 manager
.add(new Separator());
1882 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1883 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1884 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1885 manager
.add(new Separator());
1886 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getToggleBookmarkAction());
1887 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousMarkerAction());
1888 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextMarkerAction());
1889 manager
.add(new Separator());
1890 manager
.add(fPreviousResourceAction
);
1891 manager
.add(fNextResourceAction
);
1892 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1893 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1894 manager
.add(new Separator());
1898 * Add actions to local menu manager
1900 * @param manager the tool bar manager
1903 protected void fillLocalMenu(IMenuManager manager
) {
1904 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getMarkersMenu());
1911 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
1912 if (fTimeGraphWrapper
== null) {
1915 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
1922 public int getAvailableWidth(int requestedOffset
) {
1923 if (fTimeGraphWrapper
== null) {
1926 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
1933 public void performAlign(int offset
, int width
) {
1934 if (fTimeGraphWrapper
!= null) {
1935 fTimeGraphWrapper
.performAlign(offset
, width
);
1940 * Returns whether or not the time graph view is dirty. The time graph view
1941 * is considered dirty if it has yet to completely update its model.
1943 * @return true if the time graph view has yet to completely update its
1944 * model, false otherwise
1947 public boolean isDirty() {
1948 if (fZoomThread
== null) {
1951 return fDirty
.get() != 0 || fZoomThread
.getZoomStartTime() != fTimeGraphWrapper
.getTimeGraphViewer().getTime0() || fZoomThread
.getZoomEndTime() != fTimeGraphWrapper
.getTimeGraphViewer().getTime1();
1954 private void createColumnSelectionListener(TreeViewer treeViewer
) {
1955 for (int i
= 0; i
< fColumnComparators
.length
; i
++) {
1956 final int index
= i
;
1957 final Comparator
<ITimeGraphEntry
> comp
= fColumnComparators
[index
];
1958 final Tree tree
= treeViewer
.getTree();
1959 final TreeColumn column
= tree
.getColumn(i
);
1962 column
.addSelectionListener(new SelectionAdapter() {
1964 public void widgetSelected(SelectionEvent e
) {
1965 TreeColumn prevSortcolumn
= tree
.getSortColumn();
1966 int direction
= tree
.getSortDirection();
1967 if (prevSortcolumn
== column
) {
1968 direction
= (direction
== SWT
.DOWN
) ? SWT
.UP
: SWT
.DOWN
;
1970 direction
= SWT
.DOWN
;
1972 tree
.setSortColumn(column
);
1973 tree
.setSortDirection(direction
);
1974 fSortDirection
= direction
;
1975 fCurrentSortColumn
= index
;
1976 Comparator
<ITimeGraphEntry
> comparator
= comp
;
1978 if (comparator
instanceof ITimeGraphEntryComparator
) {
1979 ((ITimeGraphEntryComparator
) comparator
).setDirection(direction
);
1981 if (direction
!= SWT
.DOWN
) {
1982 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
1984 setEntryComparator(comparator
);
1985 fIsRevealSelection
= true;
1986 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
1987 ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getControl().setFocus();
1996 private void restoreViewContext() {
1997 TimeGraphCombo combo
= getTimeGraphCombo();
1998 ViewContext viewContext
= fViewContext
.get(fTrace
);
1999 if (combo
!= null) {
2000 if (fColumnComparators
!= null) {
2001 // restore sort settings
2002 fSortDirection
= SWT
.DOWN
;
2003 fCurrentSortColumn
= fInitialSortColumn
;
2004 if (viewContext
!= null) {
2005 fSortDirection
= viewContext
.getSortDirection();
2006 fCurrentSortColumn
= viewContext
.getSortColumn();
2008 if ((fCurrentSortColumn
< fColumnComparators
.length
) && (fColumnComparators
[fCurrentSortColumn
] != null)) {
2009 Comparator
<ITimeGraphEntry
> comparator
= fColumnComparators
[fCurrentSortColumn
];
2010 if (comparator
instanceof ITimeGraphEntryComparator
) {
2011 ((ITimeGraphEntryComparator
) comparator
).setDirection(fSortDirection
);
2013 if (fSortDirection
!= SWT
.DOWN
) {
2014 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2016 setEntryComparator(comparator
);
2022 private void applyViewContext() {
2023 TimeGraphCombo combo
= getTimeGraphCombo();
2024 ViewContext viewContext
= fViewContext
.get(fTrace
);
2025 if (combo
!= null) {
2026 TreeViewer treeViewer
= combo
.getTreeViewer();
2027 final Tree tree
= treeViewer
.getTree();
2028 final TreeColumn column
= tree
.getColumn(fCurrentSortColumn
);
2029 tree
.setSortDirection(fSortDirection
);
2030 tree
.setSortColumn(column
);
2031 combo
.getTreeViewer().getControl().setFocus();
2033 // restore and reveal selection
2034 if ((viewContext
!= null) && (viewContext
.getSelection() != null)) {
2035 fTimeGraphWrapper
.setSelection(viewContext
.getSelection());
2037 fViewContext
.remove(fTrace
);
2040 private static class ViewContext
{
2041 private int fSortColumnIndex
;
2042 private int fSortDirection
;
2043 private @Nullable ITimeGraphEntry fSelection
;
2045 ViewContext(int sortColunm
, int sortDirection
, ITimeGraphEntry selection
) {
2046 fSortColumnIndex
= sortColunm
;
2047 fSortDirection
= sortDirection
;
2048 fSelection
= selection
;
2051 * @return the sortColumn
2053 public int getSortColumn() {
2054 return fSortColumnIndex
;
2057 * @return the sortDirection
2059 public int getSortDirection() {
2060 return fSortDirection
;
2063 * @return the selection
2065 public ITimeGraphEntry
getSelection() {