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
.logging
.Logger
;
32 import java
.util
.regex
.Matcher
;
33 import java
.util
.regex
.Pattern
;
35 import org
.eclipse
.core
.resources
.IFile
;
36 import org
.eclipse
.core
.resources
.IMarker
;
37 import org
.eclipse
.core
.resources
.IMarkerDelta
;
38 import org
.eclipse
.core
.resources
.IResource
;
39 import org
.eclipse
.core
.resources
.IResourceChangeEvent
;
40 import org
.eclipse
.core
.resources
.IResourceChangeListener
;
41 import org
.eclipse
.core
.resources
.IWorkspaceRunnable
;
42 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
43 import org
.eclipse
.core
.runtime
.CoreException
;
44 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
45 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
46 import org
.eclipse
.jdt
.annotation
.NonNull
;
47 import org
.eclipse
.jdt
.annotation
.Nullable
;
48 import org
.eclipse
.jface
.action
.Action
;
49 import org
.eclipse
.jface
.action
.GroupMarker
;
50 import org
.eclipse
.jface
.action
.IAction
;
51 import org
.eclipse
.jface
.action
.IMenuListener
;
52 import org
.eclipse
.jface
.action
.IMenuManager
;
53 import org
.eclipse
.jface
.action
.IStatusLineManager
;
54 import org
.eclipse
.jface
.action
.IToolBarManager
;
55 import org
.eclipse
.jface
.action
.MenuManager
;
56 import org
.eclipse
.jface
.action
.Separator
;
57 import org
.eclipse
.jface
.commands
.ActionHandler
;
58 import org
.eclipse
.jface
.viewers
.AbstractTreeViewer
;
59 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
60 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
61 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
62 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
63 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
64 import org
.eclipse
.jface
.viewers
.TreeSelection
;
65 import org
.eclipse
.jface
.viewers
.TreeViewer
;
66 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
67 import org
.eclipse
.osgi
.util
.NLS
;
68 import org
.eclipse
.swt
.SWT
;
69 import org
.eclipse
.swt
.events
.MenuDetectEvent
;
70 import org
.eclipse
.swt
.events
.MenuDetectListener
;
71 import org
.eclipse
.swt
.events
.SelectionAdapter
;
72 import org
.eclipse
.swt
.events
.SelectionEvent
;
73 import org
.eclipse
.swt
.graphics
.Image
;
74 import org
.eclipse
.swt
.graphics
.Point
;
75 import org
.eclipse
.swt
.graphics
.RGBA
;
76 import org
.eclipse
.swt
.widgets
.Composite
;
77 import org
.eclipse
.swt
.widgets
.Display
;
78 import org
.eclipse
.swt
.widgets
.Menu
;
79 import org
.eclipse
.swt
.widgets
.Shell
;
80 import org
.eclipse
.swt
.widgets
.Tree
;
81 import org
.eclipse
.swt
.widgets
.TreeColumn
;
82 import org
.eclipse
.tracecompass
.common
.core
.log
.TraceCompassLog
;
83 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
84 import org
.eclipse
.tracecompass
.tmf
.core
.resources
.ITmfMarker
;
85 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
86 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
87 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
88 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
89 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
90 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
91 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
92 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
93 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
94 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
95 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
96 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceAdapterManager
;
97 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
98 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
99 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
100 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
101 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
102 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
103 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphBookmarkListener
;
104 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
105 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
106 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
107 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
108 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
109 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphBookmarkEvent
;
110 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
111 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
112 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
113 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
114 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
115 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
116 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
117 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
118 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEventSource
;
119 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
120 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
121 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.MarkerEvent
;
122 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
123 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
124 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
125 import org
.eclipse
.ui
.IActionBars
;
126 import org
.eclipse
.ui
.IPartListener
;
127 import org
.eclipse
.ui
.IWorkbenchActionConstants
;
128 import org
.eclipse
.ui
.IWorkbenchPart
;
129 import org
.eclipse
.ui
.PlatformUI
;
130 import org
.eclipse
.ui
.actions
.ActionFactory
;
131 import org
.eclipse
.ui
.handlers
.IHandlerActivation
;
132 import org
.eclipse
.ui
.handlers
.IHandlerService
;
135 * An abstract view all time graph views can inherit
137 * This view contains either a time graph viewer, or a time graph combo which is
138 * divided between a tree viewer on the left and a time graph viewer on the right.
140 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
, IResourceChangeListener
{
142 /** Constant indicating that all levels of the time graph should be expanded */
143 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
145 private static final Pattern RGBA_PATTERN
= Pattern
.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
147 private static final Logger LOGGER
= TraceCompassLog
.getLogger(AbstractTimeGraphView
.class);
156 // ------------------------------------------------------------------------
158 // ------------------------------------------------------------------------
160 /** The timegraph wrapper */
161 private ITimeGraphWrapper fTimeGraphWrapper
;
163 private AtomicInteger fDirty
= new AtomicInteger();
165 private final Object fZoomThreadResultLock
= new Object();
167 /** The selected trace */
168 private ITmfTrace fTrace
;
170 /** The selected trace editor file*/
171 private IFile fEditorFile
;
173 /** The timegraph entry list */
174 private List
<TimeGraphEntry
> fEntryList
;
176 /** The trace to entry list hash map */
177 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
179 /** The trace to filters hash map */
180 private final Map
<ITmfTrace
, @NonNull ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
182 /** The trace to view context hash map */
183 private final Map
<ITmfTrace
, ViewContext
> fViewContext
= new HashMap
<>();
185 /** The trace to marker event sources hash map */
186 private final Map
<ITmfTrace
, List
<IMarkerEventSource
>> fMarkerEventSourcesMap
= new HashMap
<>();
188 /** The trace to build thread hash map */
189 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
191 /** The start time */
192 private long fStartTime
= SWT
.DEFAULT
;
195 private long fEndTime
= SWT
.DEFAULT
;
197 /** The display width */
198 private final int fDisplayWidth
;
200 /** The zoom thread */
201 private ZoomThread fZoomThread
;
203 /** The next resource action */
204 private Action fNextResourceAction
;
206 /** The previous resource action */
207 private Action fPreviousResourceAction
;
209 /** A comparator class */
210 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
212 /** The redraw state used to prevent unnecessary queuing of display runnables */
213 private State fRedrawState
= State
.IDLE
;
215 /** The redraw synchronization object */
216 private final Object fSyncObj
= new Object();
218 /** The presentation provider for this view */
219 private final TimeGraphPresentationProvider fPresentation
;
221 /** The tree column label array, or null if combo is not used */
222 private String
[] fColumns
;
224 private Comparator
<ITimeGraphEntry
>[] fColumnComparators
;
226 /** The tree label provider, or null if combo is not used */
227 private TreeLabelProvider fLabelProvider
= null;
229 /** The time graph content provider */
230 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
232 /** The relative weight of the sash, ignored if combo is not used */
233 private int[] fWeight
= { 1, 3 };
235 /** The filter column label array, or null if filter is not used */
236 private String
[] fFilterColumns
;
238 /** The pack done flag */
239 private boolean fPackDone
= false;
241 /** The filter content provider, or null if filter is not used */
242 private ITreeContentProvider fFilterContentProvider
;
244 /** The filter label provider, or null if filter is not used */
245 private TreeLabelProvider fFilterLabelProvider
;
247 private int fAutoExpandLevel
= ALL_LEVELS
;
249 /** The default column index for sorting */
250 private int fInitialSortColumn
= 0;
252 /** The default column index for sorting */
253 private int fCurrentSortColumn
= 0;
255 /** The current sort direction */
256 private int fSortDirection
= SWT
.DOWN
;
258 /** Flag to indicate to reveal selection */
259 private volatile boolean fIsRevealSelection
= false;
262 * Menu Manager for context-sensitive menu for time graph entries.
263 * This will be used on the tree viewer in case of the time graph combo
264 * or the on the namespace in case of a single time graph viewer.
266 private final @NonNull MenuManager fEntryMenuManager
= new MenuManager();
268 /** Time Graph View part listener */
269 private TimeGraphPartListener fPartListener
;
271 /** Action for the find command. There is only one for all Time Graph views */
272 private static final ShowFindDialogAction FIND_ACTION
= new ShowFindDialogAction();
274 /** The find action handler */
275 private ActionHandler fFindActionHandler
;
277 /** The find handler activation */
278 private IHandlerActivation fFindHandlerActivation
;
280 /** The find target to use */
281 private final FindTarget fFindTarget
;
283 // ------------------------------------------------------------------------
285 // ------------------------------------------------------------------------
287 private interface ITimeGraphWrapper
{
289 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
);
291 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
);
293 TimeGraphViewer
getTimeGraphViewer();
295 void addSelectionListener(ITimeGraphSelectionListener listener
);
297 ISelectionProvider
getSelectionProvider();
301 boolean isDisposed();
305 void setInput(Object input
);
309 void setFilters(@NonNull ViewerFilter
[] filters
);
311 @NonNull ViewerFilter
[] getFilters();
317 void setAutoExpandLevel(int level
);
319 boolean getExpandedState(ITimeGraphEntry entry
);
321 void setExpandedState(ITimeGraphEntry entry
, boolean expanded
);
323 void setFilterColumns(String
[] columnNames
);
325 void setFilterContentProvider(ITreeContentProvider contentProvider
);
327 void setFilterLabelProvider(ITableLabelProvider labelProvider
);
329 IAction
getShowFilterDialogAction();
331 void performAlign(int offset
, int width
);
333 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
335 int getAvailableWidth(int requestedOffset
);
337 ITimeGraphEntry
getSelection();
339 void setSelection(ITimeGraphEntry selection
);
341 void selectAndReveal(@NonNull ITimeGraphEntry selection
);
345 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
346 private TimeGraphViewer viewer
;
348 private TimeGraphViewerWrapper(Composite parent
, int style
) {
349 viewer
= new TimeGraphViewer(parent
, style
);
353 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
354 viewer
.setTimeGraphContentProvider(timeGraphContentProvider
);
358 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
359 viewer
.setTimeGraphProvider(timeGraphPresentationProvider
);
363 public TimeGraphViewer
getTimeGraphViewer() {
368 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
369 viewer
.addSelectionListener(listener
);
373 public ISelectionProvider
getSelectionProvider() {
374 return viewer
.getSelectionProvider();
378 public void setFocus() {
383 public boolean isDisposed() {
384 return viewer
.getControl().isDisposed();
388 public void setInput(Object input
) {
389 viewer
.setInput(input
);
393 public Object
getInput() {
394 return viewer
.getInput();
398 public void setFilterColumns(String
[] columnNames
) {
399 viewer
.setFilterColumns(columnNames
);
403 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
404 viewer
.setFilterContentProvider(contentProvider
);
408 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
409 viewer
.setFilterLabelProvider(labelProvider
);
413 public void setFilters(@NonNull ViewerFilter
[] filters
) {
414 viewer
.setFilters(filters
);
418 public @NonNull ViewerFilter
[] getFilters() {
419 return viewer
.getFilters();
423 public IAction
getShowFilterDialogAction() {
424 return viewer
.getShowFilterDialogAction();
428 public void refresh() {
433 public void redraw() {
434 viewer
.getControl().redraw();
438 public void update() {
439 viewer
.getControl().update();
443 public void setAutoExpandLevel(int level
) {
444 viewer
.setAutoExpandLevel(level
);
448 public boolean getExpandedState(ITimeGraphEntry entry
) {
449 return viewer
.getExpandedState(entry
);
453 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
454 viewer
.setExpandedState(entry
, expanded
);
458 public void performAlign(int offset
, int width
) {
459 viewer
.performAlign(offset
, width
);
463 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
464 return viewer
.getTimeViewAlignmentInfo();
468 public int getAvailableWidth(int requestedOffset
) {
469 return viewer
.getAvailableWidth(requestedOffset
);
473 public ITimeGraphEntry
getSelection() {
474 return viewer
.getSelection();
478 public void setSelection(ITimeGraphEntry selection
) {
479 viewer
.setSelection(selection
);
483 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
484 viewer
.selectAndReveal(selection
);
488 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
489 private TimeGraphCombo combo
;
491 private TimeGraphComboWrapper(Composite parent
, int style
) {
492 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
496 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
497 combo
.setTimeGraphContentProvider(timeGraphContentProvider
);
501 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
502 combo
.setTimeGraphProvider(timeGraphPresentationProvider
);
506 public TimeGraphViewer
getTimeGraphViewer() {
507 return combo
.getTimeGraphViewer();
511 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
512 combo
.addSelectionListener(listener
);
516 public ISelectionProvider
getSelectionProvider() {
517 return combo
.getTreeViewer();
521 public void setFocus() {
526 public boolean isDisposed() {
527 return combo
.isDisposed();
531 public void setInput(Object input
) {
532 combo
.setInput(input
);
536 public Object
getInput() {
537 return combo
.getInput();
541 public void setFilterColumns(String
[] columnNames
) {
542 combo
.setFilterColumns(columnNames
);
546 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
547 combo
.setFilterContentProvider(contentProvider
);
551 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
552 combo
.setFilterLabelProvider(labelProvider
);
556 public void setFilters(@NonNull ViewerFilter
[] filters
) {
557 combo
.setFilters(filters
);
561 public @NonNull ViewerFilter
[] getFilters() {
562 return combo
.getFilters();
566 public IAction
getShowFilterDialogAction() {
567 return combo
.getShowFilterDialogAction();
571 public void refresh() {
576 public void redraw() {
581 public void update() {
586 public void setAutoExpandLevel(int level
) {
587 combo
.setAutoExpandLevel(level
);
591 public boolean getExpandedState(ITimeGraphEntry entry
) {
592 return combo
.getExpandedState(entry
);
596 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
597 combo
.setExpandedState(entry
, expanded
);
600 TimeGraphCombo
getTimeGraphCombo() {
604 TreeViewer
getTreeViewer() {
605 return combo
.getTreeViewer();
609 public void performAlign(int offset
, int width
) {
610 combo
.performAlign(offset
, width
);
614 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
615 return combo
.getTimeViewAlignmentInfo();
619 public int getAvailableWidth(int requestedOffset
) {
620 return combo
.getAvailableWidth(requestedOffset
);
624 public ITimeGraphEntry
getSelection() {
625 return combo
.getTimeGraphViewer().getSelection();
629 public void setSelection(ITimeGraphEntry selection
) {
630 combo
.setSelection(selection
);
634 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
635 combo
.selectAndReveal(selection
);
640 * Base class to provide the labels for the tree viewer. Views extending
641 * this class typically need to override the getColumnText method if they
642 * have more than one column to display
644 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
647 public void addListener(ILabelProviderListener listener
) {
651 public void dispose() {
655 public boolean isLabelProperty(Object element
, String property
) {
660 public void removeListener(ILabelProviderListener listener
) {
664 public Image
getColumnImage(Object element
, int columnIndex
) {
669 public String
getColumnText(Object element
, int columnIndex
) {
670 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
671 if (columnIndex
== 0) {
672 return entry
.getName();
678 public Image
getImage(Object element
) {
683 public String
getText(Object element
) {
684 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
685 return entry
.getName();
690 private class BuildThread
extends Thread
{
691 private final @NonNull ITmfTrace fBuildTrace
;
692 private final @NonNull ITmfTrace fParentTrace
;
693 private final @NonNull IProgressMonitor fMonitor
;
695 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
696 super(name
+ " build"); //$NON-NLS-1$
698 fParentTrace
= parentTrace
;
699 fMonitor
= new NullProgressMonitor();
704 LOGGER
.info(() -> "[TimeGraphView:BuildThreadStart] trace=" + fBuildTrace
.getName()); //$NON-NLS-1$
706 buildEntryList(fBuildTrace
, fParentTrace
, fMonitor
);
707 synchronized (fBuildThreadMap
) {
708 fBuildThreadMap
.remove(fBuildTrace
);
711 LOGGER
.info(() -> "[TimeGraphView:BuildThreadEnd]"); //$NON-NLS-1$
714 public void cancel() {
715 fMonitor
.setCanceled(true);
723 protected abstract class ZoomThread
extends Thread
{
724 private final long fZoomStartTime
;
725 private final long fZoomEndTime
;
726 private final long fResolution
;
727 private final @NonNull IProgressMonitor fMonitor
;
739 public ZoomThread(long startTime
, long endTime
, long resolution
) {
740 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
741 fZoomStartTime
= startTime
;
742 fZoomEndTime
= endTime
;
743 fResolution
= resolution
;
744 fMonitor
= new NullProgressMonitor();
748 * @return the zoom start time
750 public long getZoomStartTime() {
751 return fZoomStartTime
;
755 * @return the zoom end time
757 public long getZoomEndTime() {
762 * @return the resolution
764 public long getResolution() {
769 * @return the monitor
771 public @NonNull IProgressMonitor
getMonitor() {
776 * Cancel the zoom thread
778 public void cancel() {
779 fMonitor
.setCanceled(true);
783 public final void run() {
784 LOGGER
.info(() -> "[TimeGraphView:ZoomThreadStart] start=" + fZoomStartTime
+ ", end=" + fZoomEndTime
); //$NON-NLS-1$ //$NON-NLS-2$
787 fDirty
.decrementAndGet();
789 LOGGER
.info(() -> "[TimeGraphView:ZoomThreadEnd]"); //$NON-NLS-1$
793 * Applies the results of the ZoomThread calculations.
795 * Note: This method makes sure that only the results of the last
796 * created ZoomThread are applied.
799 * the code to run in order to apply the results
802 protected void applyResults(Runnable runnable
) {
803 synchronized (fZoomThreadResultLock
) {
804 if (this == fZoomThread
) {
811 * Run the zoom operation.
814 public abstract void doRun();
817 private class ZoomThreadByEntry
extends ZoomThread
{
818 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
820 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
821 super(startTime
, endTime
, resolution
);
822 fZoomEntryList
= entryList
;
826 public void doRun() {
827 LOGGER
.config(() -> "[TimeGraphView:ZoomThreadGettingStates]"); //$NON-NLS-1$
829 for (TimeGraphEntry entry
: fZoomEntryList
) {
830 if (getMonitor().isCanceled()) {
831 LOGGER
.info(() -> "[TimeGraphView:ZoomThreadCanceled]"); //$NON-NLS-1$
837 zoom(entry
, getMonitor());
839 /* Refresh the arrows when zooming */
840 LOGGER
.config(() -> "[TimeGraphView:ZoomThreadGettingLinks]"); //$NON-NLS-1$
841 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
843 /* Refresh the view-specific markers when zooming */
844 LOGGER
.config(() -> "[TimeGraphView:ZoomThreadGettingMarkers]"); //$NON-NLS-1$
845 List
<IMarkerEvent
> markers
= new ArrayList
<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
846 /* Refresh the trace-specific markers when zooming */
847 markers
.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
849 if (events
!= null) {
850 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
852 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(markers
);
857 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
858 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
860 entry
.setZoomedEventList(null);
863 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
864 if (zoomedEventList
!= null) {
866 entry
.setZoomedEventList(zoomedEventList
);
871 for (TimeGraphEntry child
: entry
.getChildren()) {
872 if (monitor
.isCanceled()) {
875 zoom(child
, monitor
);
881 // ------------------------------------------------------------------------
883 // ------------------------------------------------------------------------
886 * Constructs a time graph view that contains either a time graph viewer or
887 * a time graph combo.
889 * By default, the view uses a time graph viewer. To use a time graph combo,
890 * the subclass constructor must call {@link #setTreeColumns(String[])} and
891 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
896 * The presentation provider
898 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
900 fPresentation
= pres
;
901 fDisplayWidth
= Display
.getDefault().getBounds().width
;
902 fFindTarget
= new FindTarget();
905 // ------------------------------------------------------------------------
906 // Getters and setters
907 // ------------------------------------------------------------------------
910 * Getter for the time graph combo
912 * @return The time graph combo, or null if combo is not used
914 protected TimeGraphCombo
getTimeGraphCombo() {
915 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
916 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
922 * Getter for the time graph viewer
924 * @return The time graph viewer
926 protected TimeGraphViewer
getTimeGraphViewer() {
927 return fTimeGraphWrapper
.getTimeGraphViewer();
931 * Getter for the presentation provider
933 * @return The time graph presentation provider
935 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
936 return fPresentation
;
940 * Sets the tree column labels.
942 * This should be called from the constructor.
945 * The array of tree column labels
947 protected void setTreeColumns(final String
[] columns
) {
948 setTreeColumns(columns
, null, 0);
952 * Sets the tree column labels.
954 * This should be called from the constructor.
957 * The array of tree column labels
959 * An array of column comparators for sorting of columns when
960 * clicking on column header
961 * @param initialSortColumn
962 * Index of column to sort initially
965 protected void setTreeColumns(final String
[] columns
, final Comparator
<ITimeGraphEntry
>[] comparators
, int initialSortColumn
) {
966 checkPartNotCreated();
968 fColumnComparators
= comparators
;
969 fInitialSortColumn
= initialSortColumn
;
973 * Sets the tree label provider.
975 * This should be called from the constructor.
978 * The tree label provider
980 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
981 checkPartNotCreated();
982 fLabelProvider
= tlp
;
986 * Sets the time graph content provider.
988 * This should be called from the constructor.
991 * The time graph content provider
994 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
995 checkPartNotCreated();
996 fTimeGraphContentProvider
= tgcp
;
1000 * Sets the relative weight of each part of the time graph combo.
1002 * This should be called from the constructor.
1005 * The array (length 2) of relative weights of each part of the combo
1007 protected void setWeight(final int[] weights
) {
1008 checkPartNotCreated();
1013 * Sets the filter column labels.
1015 * This should be called from the constructor.
1017 * @param filterColumns
1018 * The array of filter column labels
1020 protected void setFilterColumns(final String
[] filterColumns
) {
1021 checkPartNotCreated();
1022 fFilterColumns
= filterColumns
;
1026 * Sets the filter content provider.
1028 * This should be called from the constructor.
1030 * @param contentProvider
1031 * The filter content provider
1034 protected void setFilterContentProvider(final ITreeContentProvider contentProvider
) {
1035 checkPartNotCreated();
1036 fFilterContentProvider
= contentProvider
;
1040 * Sets the filter label provider.
1042 * This should be called from the constructor.
1044 * @param labelProvider
1045 * The filter label provider
1047 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
1048 checkPartNotCreated();
1049 fFilterLabelProvider
= labelProvider
;
1052 private void checkPartNotCreated() {
1053 if (getParentComposite() != null) {
1054 throw new IllegalStateException("This method must be called before createPartControl."); //$NON-NLS-1$
1059 * Gets the display width
1061 * @return the display width
1063 protected int getDisplayWidth() {
1064 return fDisplayWidth
;
1068 * Gets the comparator for the entries
1070 * @return The entry comparator
1072 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
1073 return fEntryComparator
;
1077 * Sets the comparator class for the entries.
1079 * This comparator will apply recursively to entries that implement
1080 * {@link TimeGraphEntry#sortChildren(Comparator)}.
1083 * A comparator object
1085 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
1086 fEntryComparator
= comparator
;
1090 * Gets the trace displayed in the view
1094 protected ITmfTrace
getTrace() {
1099 * Gets the start time
1101 * @return The start time
1103 protected long getStartTime() {
1108 * Sets the start time
1113 protected void setStartTime(long time
) {
1120 * @return The end time
1122 protected long getEndTime() {
1132 protected void setEndTime(long time
) {
1137 * Sets the auto-expand level to be used for the input of the view. The
1138 * value 0 means that there is no auto-expand; 1 means that top-level
1139 * elements are expanded, but not their children; 2 means that top-level
1140 * elements are expanded, and their children, but not grand-children; and so
1143 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1147 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1148 * levels of the tree
1150 protected void setAutoExpandLevel(int level
) {
1151 fAutoExpandLevel
= level
;
1152 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
1153 if (tgWrapper
!= null) {
1154 tgWrapper
.setAutoExpandLevel(level
);
1159 * Gets the entry list for a trace
1164 * @return the entry list map
1166 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
1167 synchronized (fEntryListMap
) {
1168 return fEntryListMap
.get(trace
);
1173 * Adds a trace entry list to the entry list map
1178 * the list of time graph entries
1180 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1181 synchronized (fEntryListMap
) {
1182 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1187 * Adds a list of entries to a trace's entry list
1192 * the list of time graph entries to add
1194 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1195 synchronized (fEntryListMap
) {
1196 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1197 if (entryList
== null) {
1198 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1200 entryList
.addAll(list
);
1206 * Removes a list of entries from a trace's entry list
1211 * the list of time graph entries to remove
1213 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1214 synchronized (fEntryListMap
) {
1215 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1216 if (entryList
!= null) {
1217 entryList
.removeAll(list
);
1223 * Text for the "next" button
1225 * @return The "next" button text
1227 protected String
getNextText() {
1228 return Messages
.AbstractTimeGraphtView_NextText
;
1232 * Tooltip for the "next" button
1234 * @return Tooltip for the "next" button
1236 protected String
getNextTooltip() {
1237 return Messages
.AbstractTimeGraphView_NextTooltip
;
1241 * Text for the "Previous" button
1243 * @return The "Previous" button text
1245 protected String
getPrevText() {
1246 return Messages
.AbstractTimeGraphView_PreviousText
;
1250 * Tooltip for the "previous" button
1252 * @return Tooltip for the "previous" button
1254 protected String
getPrevTooltip() {
1255 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
1259 FindTarget
getFindTarget() {
1263 // ------------------------------------------------------------------------
1265 // ------------------------------------------------------------------------
1268 public void createPartControl(Composite parent
) {
1269 super.createPartControl(parent
);
1270 if (fColumns
== null || fLabelProvider
== null) {
1271 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
1273 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
1274 fTimeGraphWrapper
= wrapper
;
1275 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
1276 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
1277 combo
.setTreeLabelProvider(fLabelProvider
);
1278 combo
.setTreeColumns(fColumns
);
1279 if (fColumnComparators
!= null) {
1280 createColumnSelectionListener(combo
.getTreeViewer());
1282 // Add double click listener to tree viewer
1283 createDoubleClickListener(combo
.getTreeViewer());
1285 fTimeGraphWrapper
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
1286 fTimeGraphWrapper
.setFilterContentProvider(fFilterContentProvider
!= null ? fFilterContentProvider
: fTimeGraphContentProvider
);
1287 fTimeGraphWrapper
.setFilterLabelProvider(fFilterLabelProvider
);
1288 fTimeGraphWrapper
.setFilterColumns(fFilterColumns
);
1290 fTimeGraphWrapper
.setTimeGraphPresentationProvider(fPresentation
);
1291 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
1293 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1295 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
1296 final long startTime
= event
.getStartTime();
1297 final long endTime
= event
.getEndTime();
1298 TmfTimeRange range
= new TmfTimeRange(TmfTimestamp
.fromNanos(startTime
), TmfTimestamp
.fromNanos(endTime
));
1299 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
1300 startZoomThread(startTime
, endTime
);
1304 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1306 public void timeSelected(TimeGraphTimeEvent event
) {
1307 ITmfTimestamp startTime
= TmfTimestamp
.fromNanos(event
.getBeginTime());
1308 ITmfTimestamp endTime
= TmfTimestamp
.fromNanos(event
.getEndTime());
1309 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
1313 fTimeGraphWrapper
.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1315 public void bookmarkAdded(final TimeGraphBookmarkEvent event
) {
1317 ResourcesPlugin
.getWorkspace().run(new IWorkspaceRunnable() {
1319 public void run(IProgressMonitor monitor
) throws CoreException
{
1320 IMarkerEvent bookmark
= event
.getBookmark();
1321 IMarker marker
= fEditorFile
.createMarker(IMarker
.BOOKMARK
);
1322 marker
.setAttribute(IMarker
.MESSAGE
, bookmark
.getLabel());
1323 marker
.setAttribute(ITmfMarker
.MARKER_TIME
, Long
.toString(bookmark
.getTime()));
1324 if (bookmark
.getDuration() > 0) {
1325 marker
.setAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(bookmark
.getDuration()));
1326 marker
.setAttribute(IMarker
.LOCATION
,
1327 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTimeRange
,
1328 TmfTimestamp
.fromNanos(bookmark
.getTime()),
1329 TmfTimestamp
.fromNanos(bookmark
.getTime() + bookmark
.getDuration())));
1331 marker
.setAttribute(IMarker
.LOCATION
,
1332 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTime
,
1333 TmfTimestamp
.fromNanos(bookmark
.getTime())));
1335 marker
.setAttribute(ITmfMarker
.MARKER_COLOR
, bookmark
.getColor().toString());
1338 } catch (CoreException e
) {
1339 Activator
.getDefault().logError(e
.getMessage());
1344 public void bookmarkRemoved(TimeGraphBookmarkEvent event
) {
1346 IMarkerEvent bookmark
= event
.getBookmark();
1347 IMarker
[] markers
= fEditorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1348 for (IMarker marker
: markers
) {
1349 if (bookmark
.getLabel().equals(marker
.getAttribute(IMarker
.MESSAGE
)) &&
1350 Long
.toString(bookmark
.getTime()).equals(marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null)) &&
1351 Long
.toString(bookmark
.getDuration()).equals(marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0))) &&
1352 bookmark
.getColor().toString().equals(marker
.getAttribute(ITmfMarker
.MARKER_COLOR
))) {
1357 } catch (CoreException e
) {
1358 Activator
.getDefault().logError(e
.getMessage());
1363 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
1365 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
1366 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
1368 // View Action Handling
1370 contributeToActionBars();
1372 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
1373 if (trace
!= null) {
1374 traceSelected(new TmfTraceSelectedSignal(this, trace
));
1377 // make selection available to other views
1378 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
1380 ResourcesPlugin
.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent
.POST_CHANGE
);
1382 createContextMenu();
1383 fPartListener
= new TimeGraphPartListener();
1384 getSite().getPage().addPartListener(fPartListener
);
1388 public void setFocus() {
1389 fTimeGraphWrapper
.setFocus();
1393 public void dispose() {
1395 synchronized (fBuildThreadMap
) {
1396 fBuildThreadMap
.values().forEach(buildThread
-> {
1397 buildThread
.cancel();
1400 if (fZoomThread
!= null) {
1401 fZoomThread
.cancel();
1403 ResourcesPlugin
.getWorkspace().removeResourceChangeListener(this);
1404 getSite().getPage().removePartListener(fPartListener
);
1411 public void resourceChanged(final IResourceChangeEvent event
) {
1412 for (final IMarkerDelta delta
: event
.findMarkerDeltas(IMarker
.BOOKMARK
, false)) {
1413 if (delta
.getResource().equals(fEditorFile
)) {
1414 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1421 private static List
<IMarkerEvent
> refreshBookmarks(final IFile editorFile
) {
1422 List
<IMarkerEvent
> bookmarks
= new ArrayList
<>();
1423 if (editorFile
== null || !editorFile
.exists()) {
1427 IMarker
[] markers
= editorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1428 for (IMarker marker
: markers
) {
1429 String label
= marker
.getAttribute(IMarker
.MESSAGE
, (String
) null);
1430 String time
= marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null);
1431 String duration
= marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0));
1432 String rgba
= marker
.getAttribute(ITmfMarker
.MARKER_COLOR
, (String
) null);
1433 if (label
!= null && time
!= null && rgba
!= null) {
1434 Matcher matcher
= RGBA_PATTERN
.matcher(rgba
);
1435 if (matcher
.matches()) {
1437 int red
= Integer
.valueOf(matcher
.group(1));
1438 int green
= Integer
.valueOf(matcher
.group(2));
1439 int blue
= Integer
.valueOf(matcher
.group(3));
1440 int alpha
= Integer
.valueOf(matcher
.group(4));
1441 RGBA color
= new RGBA(red
, green
, blue
, alpha
);
1442 bookmarks
.add(new MarkerEvent(null, Long
.valueOf(time
), Long
.valueOf(duration
), IMarkerEvent
.BOOKMARKS
, color
, label
, true));
1443 } catch (NumberFormatException e
) {
1444 Activator
.getDefault().logError(e
.getMessage());
1449 } catch (CoreException e
) {
1450 Activator
.getDefault().logError(e
.getMessage());
1457 // ------------------------------------------------------------------------
1459 // ------------------------------------------------------------------------
1462 * Handler for the trace opened signal.
1465 * The incoming signal
1468 public void traceOpened(TmfTraceOpenedSignal signal
) {
1469 loadTrace(signal
.getTrace());
1473 * Handler for the trace selected signal
1476 * The incoming signal
1479 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1480 if (signal
.getTrace() == fTrace
) {
1483 loadTrace(signal
.getTrace());
1487 * Trace is closed: clear the data structures and the view
1490 * the signal received
1493 public void traceClosed(final TmfTraceClosedSignal signal
) {
1494 resetView(signal
.getTrace());
1495 if (signal
.getTrace() == fTrace
) {
1498 setStartTime(SWT
.DEFAULT
);
1499 setEndTime(SWT
.DEFAULT
);
1505 * Handler for the selection range signal.
1508 * The signal that's received
1512 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1513 if (signal
.getSource() == this || fTrace
== null) {
1516 final long beginTime
= signal
.getBeginTime().toNanos();
1517 final long endTime
= signal
.getEndTime().toNanos();
1519 Display
.getDefault().asyncExec(new Runnable() {
1522 if (fTimeGraphWrapper
.isDisposed()) {
1525 if (beginTime
== endTime
) {
1526 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1528 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
, true);
1530 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getSelectionBegin());
1536 * Handler for the window range signal.
1539 * The signal that's received
1543 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1544 if (signal
.getSource() == this || fTrace
== null) {
1547 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1550 final long startTime
= signal
.getCurrentRange().getStartTime().toNanos();
1551 final long endTime
= signal
.getCurrentRange().getEndTime().toNanos();
1552 Display
.getDefault().asyncExec(new Runnable() {
1555 if (fTimeGraphWrapper
.isDisposed()) {
1558 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1559 startZoomThread(startTime
, endTime
);
1565 * @param signal the format of the timestamps was updated.
1568 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1569 fTimeGraphWrapper
.refresh();
1572 // ------------------------------------------------------------------------
1574 // ------------------------------------------------------------------------
1576 private void loadTrace(final ITmfTrace trace
) {
1577 if (fZoomThread
!= null) {
1578 fZoomThread
.cancel();
1581 if (fTrace
!= null) {
1582 /* save the filters of the previous trace */
1583 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1584 fViewContext
.put(fTrace
, new ViewContext(fCurrentSortColumn
, fSortDirection
, fTimeGraphWrapper
.getSelection()));
1588 LOGGER
.info(() -> "[TimeGraphView:LoadingTrace] trace=" + trace
.getName()); //$NON-NLS-1$
1590 restoreViewContext();
1591 fEditorFile
= TmfTraceManager
.getInstance().getTraceEditorFile(trace
);
1592 synchronized (fEntryListMap
) {
1593 fEntryList
= fEntryListMap
.get(fTrace
);
1594 if (fEntryList
== null) {
1597 setStartTime(fTrace
.getStartTime().toNanos());
1598 setEndTime(fTrace
.getEndTime().toNanos());
1605 * Forces a rebuild of the entries list, even if entries already exist for this trace
1607 protected void rebuild() {
1608 setStartTime(Long
.MAX_VALUE
);
1609 setEndTime(Long
.MIN_VALUE
);
1611 ITmfTrace viewTrace
= fTrace
;
1612 if (viewTrace
== null) {
1615 resetView(viewTrace
);
1617 List
<IMarkerEventSource
> markerEventSources
= new ArrayList
<>();
1618 synchronized (fBuildThreadMap
) {
1619 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1620 if (trace
== null) {
1623 markerEventSources
.addAll(TmfTraceAdapterManager
.getAdapters(trace
, IMarkerEventSource
.class));
1624 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1625 fBuildThreadMap
.put(trace
, buildThread
);
1626 buildThread
.start();
1629 fMarkerEventSourcesMap
.put(viewTrace
, markerEventSources
);
1633 * Method called when synching to a given timestamp. Inheriting classes can
1634 * perform actions here to update the view at the given timestamp.
1637 * The currently selected time
1639 protected void synchingToTime(long time
) {
1644 * Return the list of traces whose data or analysis results will be used to
1645 * populate the view. By default, if the trace is an experiment, the traces
1646 * under it will be returned, otherwise, the trace itself is returned.
1648 * A build thread will be started for each trace returned by this method,
1649 * some of which may receive events in live streaming mode.
1652 * The trace associated with this view
1653 * @return List of traces with data to display
1655 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1656 return TmfTraceManager
.getTraceSet(trace
);
1660 * Build the entry list to show in this time graph view.
1662 * Called from the BuildThread for each trace returned by
1663 * {@link #getTracesToBuild(ITmfTrace)}. The full event list is also
1664 * normally computed for every entry that is created.
1667 * The trace being built
1668 * @param parentTrace
1669 * The parent of the trace set, or the trace itself
1671 * The progress monitor object
1674 protected abstract void buildEntryList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1677 * Gets the list of event for an entry in a given time range.
1679 * Called from the ZoomThread for every entry to update the zoomed event
1680 * list. Can be an empty implementation if the view does not support zoomed
1681 * event lists. Can also be used to compute the full event list.
1684 * The entry to get events for
1686 * Start of the time range
1688 * End of the time range
1692 * The progress monitor object
1693 * @return The list of events for the entry
1695 protected abstract @Nullable List
<@NonNull ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1696 long startTime
, long endTime
, long resolution
,
1697 @NonNull IProgressMonitor monitor
);
1700 * Gets the list of links (displayed as arrows) for a trace in a given
1701 * timerange. Default implementation returns an empty list.
1704 * Start of the time range
1706 * End of the time range
1710 * The progress monitor object
1711 * @return The list of link events
1713 protected @Nullable List
<@NonNull ILinkEvent
> getLinkList(long startTime
, long endTime
,
1714 long resolution
, @NonNull IProgressMonitor monitor
) {
1715 return new ArrayList
<>();
1719 * Gets the list of view-specific marker categories. Default implementation
1720 * returns an empty list.
1722 * @return The list of marker categories
1725 protected @NonNull List
<String
> getViewMarkerCategories() {
1726 return new ArrayList
<>();
1730 * Gets the list of view-specific markers for a trace in a given time range.
1731 * Default implementation returns an empty list.
1734 * Start of the time range
1736 * End of the time range
1740 * The progress monitor object
1741 * @return The list of marker events
1744 protected @NonNull List
<IMarkerEvent
> getViewMarkerList(long startTime
, long endTime
,
1745 long resolution
, @NonNull IProgressMonitor monitor
) {
1746 return new ArrayList
<>();
1750 * Gets the list of trace-specific markers for a trace in a given time range.
1753 * Start of the time range
1755 * End of the time range
1759 * The progress monitor object
1760 * @return The list of marker events
1763 protected @NonNull List
<IMarkerEvent
> getTraceMarkerList(long startTime
, long endTime
,
1764 long resolution
, @NonNull IProgressMonitor monitor
) {
1765 List
<IMarkerEvent
> markers
= new ArrayList
<>();
1766 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1767 for (String category
: markerEventSource
.getMarkerCategories()) {
1768 if (monitor
.isCanceled()) {
1771 markers
.addAll(markerEventSource
.getMarkerList(category
, startTime
, endTime
, resolution
, monitor
));
1778 * Get the list of current marker categories.
1780 * @return The list of marker categories
1783 private @NonNull List
<String
> getMarkerCategories() {
1784 Set
<String
> categories
= new LinkedHashSet
<>(getViewMarkerCategories());
1785 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1786 categories
.addAll(markerEventSource
.getMarkerCategories());
1788 return new ArrayList
<>(categories
);
1792 * Gets the list of marker event sources for a given trace.
1796 * @return The list of marker event sources
1799 private @NonNull List
<IMarkerEventSource
> getMarkerEventSources(ITmfTrace trace
) {
1800 List
<IMarkerEventSource
> markerEventSources
= fMarkerEventSourcesMap
.get(trace
);
1801 if (markerEventSources
== null) {
1802 markerEventSources
= Collections
.emptyList();
1804 return markerEventSources
;
1808 * Refresh the display
1810 protected void refresh() {
1811 LOGGER
.info(() -> "[TimeGraphView:RefreshRequested]"); //$NON-NLS-1$
1812 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1813 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1816 LOGGER
.info(() -> "[TimeGraphView:RefreshStart]"); //$NON-NLS-1$
1817 if (fTimeGraphWrapper
.isDisposed()) {
1820 fDirty
.incrementAndGet();
1822 boolean hasEntries
= false;
1823 synchronized (fEntryListMap
) {
1824 fEntryList
= fEntryListMap
.get(fTrace
);
1825 if (fEntryList
== null) {
1826 fEntryList
= new CopyOnWriteArrayList
<>();
1827 } else if (fEntryComparator
!= null) {
1828 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1829 Collections
.sort(list
, fEntryComparator
);
1830 for (ITimeGraphEntry entry
: list
) {
1831 sortChildren(entry
, fEntryComparator
);
1834 fEntryList
.addAll(list
);
1836 hasEntries
= !fEntryList
.isEmpty();
1838 boolean inputChanged
= fEntryList
!= fTimeGraphWrapper
.getInput();
1839 TimeGraphCombo combo
= getTimeGraphCombo();
1841 // Set redraw to false to only draw once
1842 if (combo
!= null) {
1843 combo
.getTreeViewer().getTree().setRedraw(false);
1845 getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
1847 fTimeGraphWrapper
.setInput(fEntryList
);
1848 /* restore the previously saved filters, if any */
1849 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1850 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1851 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1852 fTimeGraphWrapper
.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1853 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(null);
1856 fTimeGraphWrapper
.refresh();
1859 if (fIsRevealSelection
) {
1860 fIsRevealSelection
= false;
1861 ITimeGraphEntry entry1
= fTimeGraphWrapper
.getSelection();
1862 fTimeGraphWrapper
.setSelection(entry1
);
1865 if (combo
!= null) {
1866 combo
.getTreeViewer().getTree().setRedraw(true);
1868 getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
1870 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1871 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1872 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1874 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1875 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().toNanos();
1876 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().toNanos();
1877 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().toNanos();
1878 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().toNanos();
1879 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1880 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1881 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
, false);
1882 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1884 if (inputChanged
&& selectionBeginTime
!= SWT
.DEFAULT
) {
1885 synchingToTime(selectionBeginTime
);
1888 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1889 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1898 startZoomThread(startTime
, endTime
);
1900 fDirty
.decrementAndGet();
1901 LOGGER
.info(() -> "[TimeGraphView:RefreshEnd]"); //$NON-NLS-1$
1909 protected void redraw() {
1910 synchronized (fSyncObj
) {
1911 if (fRedrawState
== State
.IDLE
) {
1912 fRedrawState
= State
.BUSY
;
1914 fRedrawState
= State
.PENDING
;
1918 LOGGER
.info(() -> "[TimeGraphView:RedrawRequested]"); //$NON-NLS-1$
1919 Display
.getDefault().asyncExec(new Runnable() {
1922 LOGGER
.info(() -> "[TimeGraphView:RedrawStart]"); //$NON-NLS-1$
1923 if (fTimeGraphWrapper
.isDisposed()) {
1926 fTimeGraphWrapper
.redraw();
1927 fTimeGraphWrapper
.update();
1928 synchronized (fSyncObj
) {
1929 if (fRedrawState
== State
.PENDING
) {
1930 fRedrawState
= State
.IDLE
;
1933 fRedrawState
= State
.IDLE
;
1936 LOGGER
.info(() -> "[TimeGraphView:RedrawEnd]"); //$NON-NLS-1$
1941 private void sortChildren(ITimeGraphEntry entry
, Comparator
<ITimeGraphEntry
> comparator
) {
1942 if (entry
instanceof TimeGraphEntry
) {
1943 ((TimeGraphEntry
) entry
).sortChildren(comparator
);
1945 for (ITimeGraphEntry child
: entry
.getChildren()) {
1946 sortChildren(child
, comparator
);
1951 * Start or restart the zoom thread.
1954 * the zoom start time
1959 protected final void startZoomThread(long startTime
, long endTime
) {
1960 long clampedStartTime
= (fStartTime
== Long
.MAX_VALUE ? startTime
: Math
.min(Math
.max(startTime
, fStartTime
), fEndTime
));
1961 long clampedEndTime
= (fEndTime
== Long
.MIN_VALUE ? endTime
: Math
.max(Math
.min(endTime
, fEndTime
), fStartTime
));
1962 fDirty
.incrementAndGet();
1963 boolean restart
= false;
1964 if (fZoomThread
!= null) {
1965 fZoomThread
.cancel();
1966 if (fZoomThread
.fZoomStartTime
== clampedStartTime
&& fZoomThread
.fZoomEndTime
== clampedEndTime
) {
1970 long resolution
= Math
.max(1, (clampedEndTime
- clampedStartTime
) / fDisplayWidth
);
1971 fZoomThread
= createZoomThread(clampedStartTime
, clampedEndTime
, resolution
, restart
);
1972 if (fZoomThread
!= null) {
1973 // Don't start a new thread right away if results are being applied
1974 // from an old ZoomThread. Otherwise, the old results might
1975 // overwrite the new results if it finishes after.
1976 synchronized (fZoomThreadResultLock
) {
1977 fZoomThread
.start();
1980 fDirty
.decrementAndGet();
1985 * Create a zoom thread.
1988 * the zoom start time
1994 * true if restarting zoom for the same time range
1995 * @return a zoom thread
1998 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1999 final List
<TimeGraphEntry
> entryList
= fEntryList
;
2000 if (entryList
== null) {
2003 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
2006 private void makeActions() {
2007 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
2008 fPreviousResourceAction
.setText(getPrevText());
2009 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
2010 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
2011 fNextResourceAction
.setText(getNextText());
2012 fNextResourceAction
.setToolTipText(getNextTooltip());
2015 private void contributeToActionBars() {
2016 IActionBars bars
= getViewSite().getActionBars();
2017 fillLocalToolBar(bars
.getToolBarManager());
2018 fillLocalMenu(bars
.getMenuManager());
2022 * Add actions to local tool bar manager
2024 * @param manager the tool bar manager
2026 protected void fillLocalToolBar(IToolBarManager manager
) {
2027 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
2028 manager
.add(fTimeGraphWrapper
.getShowFilterDialogAction());
2030 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
2031 manager
.add(new Separator());
2032 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
2033 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
2034 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
2035 manager
.add(new Separator());
2036 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getToggleBookmarkAction());
2037 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousMarkerAction());
2038 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextMarkerAction());
2039 manager
.add(new Separator());
2040 manager
.add(fPreviousResourceAction
);
2041 manager
.add(fNextResourceAction
);
2042 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
2043 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
2044 manager
.add(new Separator());
2048 * Add actions to local menu manager
2050 * @param manager the tool bar manager
2053 protected void fillLocalMenu(IMenuManager manager
) {
2054 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getMarkersMenu());
2061 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
2062 if (fTimeGraphWrapper
== null) {
2065 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
2072 public int getAvailableWidth(int requestedOffset
) {
2073 if (fTimeGraphWrapper
== null) {
2076 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
2083 public void performAlign(int offset
, int width
) {
2084 if (fTimeGraphWrapper
!= null) {
2085 fTimeGraphWrapper
.performAlign(offset
, width
);
2090 * Returns whether or not the time graph view is dirty. The time graph view
2091 * is considered dirty if it has yet to completely update its model.
2093 * This method is meant to be used by tests in order to know when it is safe
2096 * Note: If a trace is smaller than the initial window range (see
2097 * {@link ITmfTrace#getInitialRangeOffset}) this method will return true
2100 * @return true if the time graph view has yet to completely update its
2101 * model, false otherwise
2104 public boolean isDirty() {
2105 if (fTrace
== null) {
2109 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
2110 long startTime
= ctx
.getWindowRange().getStartTime().toNanos();
2111 long endTime
= ctx
.getWindowRange().getEndTime().toNanos();
2113 // If the time graph control hasn't updated all the way to the end of
2114 // the window range then it's dirty. A refresh should happen later.
2115 if (fTimeGraphWrapper
.getTimeGraphViewer().getTime0() != startTime
|| fTimeGraphWrapper
.getTimeGraphViewer().getTime1() != endTime
) {
2119 if (fZoomThread
== null) {
2120 // The zoom thread is null but we might be just about to create it (refresh called).
2121 return fDirty
.get() != 0;
2123 // Dirty if the zoom thread is not done or if it hasn't zoomed all the
2124 // way to the end of the window range. In the latter case, there should be
2125 // a subsequent zoom thread that will be triggered.
2126 return fDirty
.get() != 0 || fZoomThread
.getZoomStartTime() != startTime
|| fZoomThread
.getZoomEndTime() != endTime
;
2129 private void createColumnSelectionListener(TreeViewer treeViewer
) {
2130 for (int i
= 0; i
< fColumnComparators
.length
; i
++) {
2131 final int index
= i
;
2132 final Comparator
<ITimeGraphEntry
> comp
= fColumnComparators
[index
];
2133 final Tree tree
= treeViewer
.getTree();
2134 final TreeColumn column
= tree
.getColumn(i
);
2137 column
.addSelectionListener(new SelectionAdapter() {
2139 public void widgetSelected(SelectionEvent e
) {
2140 TreeColumn prevSortcolumn
= tree
.getSortColumn();
2141 int direction
= tree
.getSortDirection();
2142 if (prevSortcolumn
== column
) {
2143 direction
= (direction
== SWT
.DOWN
) ? SWT
.UP
: SWT
.DOWN
;
2145 direction
= SWT
.DOWN
;
2147 tree
.setSortColumn(column
);
2148 tree
.setSortDirection(direction
);
2149 fSortDirection
= direction
;
2150 fCurrentSortColumn
= index
;
2151 Comparator
<ITimeGraphEntry
> comparator
= comp
;
2153 if (comparator
instanceof ITimeGraphEntryComparator
) {
2154 ((ITimeGraphEntryComparator
) comparator
).setDirection(direction
);
2156 if (direction
!= SWT
.DOWN
) {
2157 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2159 setEntryComparator(comparator
);
2160 fIsRevealSelection
= true;
2161 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
2162 ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getControl().setFocus();
2171 private void createDoubleClickListener(TreeViewer treeViewer
) {
2172 treeViewer
.addDoubleClickListener(event
-> {
2173 if (event
.getSelection() instanceof TreeSelection
) {
2174 TreeSelection selection
= (TreeSelection
) event
.getSelection();
2175 if (selection
.getFirstElement() instanceof ITimeGraphEntry
) {
2176 ITimeGraphEntry entry
= (ITimeGraphEntry
) selection
.getFirstElement();
2177 if (entry
.hasChildren()) {
2178 fTimeGraphWrapper
.setExpandedState(entry
, !fTimeGraphWrapper
.getExpandedState(entry
));
2186 private void restoreViewContext() {
2187 TimeGraphCombo combo
= getTimeGraphCombo();
2188 ViewContext viewContext
= fViewContext
.get(fTrace
);
2189 if (combo
!= null) {
2190 if (fColumnComparators
!= null) {
2191 // restore sort settings
2192 fSortDirection
= SWT
.DOWN
;
2193 fCurrentSortColumn
= fInitialSortColumn
;
2194 if (viewContext
!= null) {
2195 fSortDirection
= viewContext
.getSortDirection();
2196 fCurrentSortColumn
= viewContext
.getSortColumn();
2198 if ((fCurrentSortColumn
< fColumnComparators
.length
) && (fColumnComparators
[fCurrentSortColumn
] != null)) {
2199 Comparator
<ITimeGraphEntry
> comparator
= fColumnComparators
[fCurrentSortColumn
];
2200 if (comparator
instanceof ITimeGraphEntryComparator
) {
2201 ((ITimeGraphEntryComparator
) comparator
).setDirection(fSortDirection
);
2203 if (fSortDirection
!= SWT
.DOWN
) {
2204 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2206 setEntryComparator(comparator
);
2212 private void applyViewContext() {
2213 TimeGraphCombo combo
= getTimeGraphCombo();
2214 ViewContext viewContext
= fViewContext
.get(fTrace
);
2215 if (combo
!= null) {
2216 TreeViewer treeViewer
= combo
.getTreeViewer();
2217 final Tree tree
= treeViewer
.getTree();
2218 final TreeColumn column
= tree
.getColumn(fCurrentSortColumn
);
2219 tree
.setSortDirection(fSortDirection
);
2220 tree
.setSortColumn(column
);
2221 combo
.getTreeViewer().getControl().setFocus();
2223 // restore and reveal selection
2224 if ((viewContext
!= null) && (viewContext
.getSelection() != null)) {
2225 fTimeGraphWrapper
.setSelection(viewContext
.getSelection());
2227 fViewContext
.remove(fTrace
);
2230 private static class ViewContext
{
2231 private int fSortColumnIndex
;
2232 private int fSortDirection
;
2233 private @Nullable ITimeGraphEntry fSelection
;
2235 ViewContext(int sortColunm
, int sortDirection
, ITimeGraphEntry selection
) {
2236 fSortColumnIndex
= sortColunm
;
2237 fSortDirection
= sortDirection
;
2238 fSelection
= selection
;
2241 * @return the sortColumn
2243 public int getSortColumn() {
2244 return fSortColumnIndex
;
2247 * @return the sortDirection
2249 public int getSortDirection() {
2250 return fSortDirection
;
2253 * @return the selection
2255 public ITimeGraphEntry
getSelection() {
2261 * Method to reset the view internal data for a given trace.
2263 * When overriding this method make sure to call the super
2267 * trace to reset the view for.
2270 protected void resetView(ITmfTrace viewTrace
) {
2271 if (viewTrace
== null) {
2274 synchronized (fBuildThreadMap
) {
2275 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
2276 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
2277 if (buildThread
!= null) {
2278 buildThread
.cancel();
2282 synchronized (fEntryListMap
) {
2283 fEntryListMap
.remove(viewTrace
);
2285 fViewContext
.remove(viewTrace
);
2286 fFiltersMap
.remove(viewTrace
);
2287 fMarkerEventSourcesMap
.remove(viewTrace
);
2288 if (viewTrace
== fTrace
) {
2289 if (fZoomThread
!= null) {
2290 fZoomThread
.cancel();
2296 private void createContextMenu() {
2297 TimeGraphCombo combo
= getTimeGraphCombo();
2298 fEntryMenuManager
.setRemoveAllWhenShown(true);
2299 if (combo
!= null) {
2300 TreeViewer treeViewer
= combo
.getTreeViewer();
2301 Tree tree
= treeViewer
.getTree();
2302 Menu menu
= fEntryMenuManager
.createContextMenu(tree
);
2305 TimeGraphControl timeGraphControl
= getTimeGraphViewer().getTimeGraphControl();
2306 final Menu entryMenu
= fEntryMenuManager
.createContextMenu(timeGraphControl
);
2307 timeGraphControl
.addTimeGraphEntryMenuListener(new MenuDetectListener() {
2309 public void menuDetected(MenuDetectEvent event
) {
2310 Point p
= timeGraphControl
.toControl(event
.x
, event
.y
);
2312 * The TimeGraphControl will call the TimeGraphEntryMenuListener
2313 * before the TimeEventMenuListener. If the event is
2314 * triggered on the namespace then show the menu else
2317 if (p
.x
< getTimeGraphViewer().getNameSpace()) {
2318 timeGraphControl
.setMenu(entryMenu
);
2320 timeGraphControl
.setMenu(null);
2326 fEntryMenuManager
.addMenuListener(new IMenuListener() {
2328 public void menuAboutToShow(IMenuManager manager
) {
2329 fillTimeGraphEntryContextMenu(fEntryMenuManager
);
2330 fEntryMenuManager
.add(new GroupMarker(IWorkbenchActionConstants
.MB_ADDITIONS
));
2333 getSite().registerContextMenu(fEntryMenuManager
, fTimeGraphWrapper
.getSelectionProvider());
2339 * @param menuManager
2340 * a menuManager to fill
2343 protected void fillTimeGraphEntryContextMenu (@NonNull IMenuManager menuManager
) {
2347 * Inner classes used for searching
2350 public ITimeGraphEntry
getSelection() {
2351 return fTimeGraphWrapper
.getSelection();
2354 public void selectAndReveal(@NonNull ITimeGraphEntry entry
) {
2355 fTimeGraphWrapper
.selectAndReveal(entry
);
2358 public ITimeGraphEntry
[] getEntries() {
2359 TimeGraphViewer viewer
= getTimeGraphViewer();
2360 return viewer
.getTimeGraphContentProvider().getElements(viewer
.getInput());
2363 public Shell
getShell() {
2364 return getSite().getShell();
2368 class TimeGraphPartListener
implements IPartListener
{
2370 public void partActivated(IWorkbenchPart part
) {
2371 if (part
== AbstractTimeGraphView
.this) {
2372 synchronized (FIND_ACTION
) {
2373 if (fFindActionHandler
== null) {
2374 fFindActionHandler
= new ActionHandler(FIND_ACTION
);
2376 if (fFindHandlerActivation
== null) {
2377 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2378 fFindHandlerActivation
= ((IHandlerService
) service
).activateHandler(ActionFactory
.FIND
.getCommandId(), fFindActionHandler
);
2382 // Notify action for all parts
2383 FIND_ACTION
.partActivated(part
);
2386 public void partDeactivated(IWorkbenchPart part
) {
2387 if ((part
== AbstractTimeGraphView
.this) && (fFindHandlerActivation
!= null)) {
2388 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2389 ((IHandlerService
) service
).deactivateHandler(fFindHandlerActivation
);
2390 fFindHandlerActivation
= null;
2394 public void partBroughtToTop(IWorkbenchPart part
) {
2397 public void partClosed(IWorkbenchPart part
) {
2400 public void partOpened(IWorkbenchPart part
) {