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
.IStatus
;
46 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
47 import org
.eclipse
.core
.runtime
.Status
;
48 import org
.eclipse
.core
.runtime
.jobs
.Job
;
49 import org
.eclipse
.jdt
.annotation
.NonNull
;
50 import org
.eclipse
.jdt
.annotation
.Nullable
;
51 import org
.eclipse
.jface
.action
.Action
;
52 import org
.eclipse
.jface
.action
.GroupMarker
;
53 import org
.eclipse
.jface
.action
.IAction
;
54 import org
.eclipse
.jface
.action
.IMenuListener
;
55 import org
.eclipse
.jface
.action
.IMenuManager
;
56 import org
.eclipse
.jface
.action
.IStatusLineManager
;
57 import org
.eclipse
.jface
.action
.IToolBarManager
;
58 import org
.eclipse
.jface
.action
.MenuManager
;
59 import org
.eclipse
.jface
.action
.Separator
;
60 import org
.eclipse
.jface
.commands
.ActionHandler
;
61 import org
.eclipse
.jface
.viewers
.AbstractTreeViewer
;
62 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
63 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
64 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
65 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
66 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
67 import org
.eclipse
.jface
.viewers
.TreeSelection
;
68 import org
.eclipse
.jface
.viewers
.TreeViewer
;
69 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
70 import org
.eclipse
.osgi
.util
.NLS
;
71 import org
.eclipse
.swt
.SWT
;
72 import org
.eclipse
.swt
.events
.MenuDetectEvent
;
73 import org
.eclipse
.swt
.events
.MenuDetectListener
;
74 import org
.eclipse
.swt
.events
.SelectionAdapter
;
75 import org
.eclipse
.swt
.events
.SelectionEvent
;
76 import org
.eclipse
.swt
.graphics
.Image
;
77 import org
.eclipse
.swt
.graphics
.Point
;
78 import org
.eclipse
.swt
.graphics
.RGBA
;
79 import org
.eclipse
.swt
.widgets
.Composite
;
80 import org
.eclipse
.swt
.widgets
.Display
;
81 import org
.eclipse
.swt
.widgets
.Menu
;
82 import org
.eclipse
.swt
.widgets
.Shell
;
83 import org
.eclipse
.swt
.widgets
.Tree
;
84 import org
.eclipse
.swt
.widgets
.TreeColumn
;
85 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
86 import org
.eclipse
.tracecompass
.common
.core
.log
.TraceCompassLog
;
87 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
88 import org
.eclipse
.tracecompass
.tmf
.core
.resources
.ITmfMarker
;
89 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfMarkerEventSourceUpdatedSignal
;
90 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
91 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
92 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
93 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
94 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
95 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
96 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
97 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
98 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
99 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
100 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
101 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceAdapterManager
;
102 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
103 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
104 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
105 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
106 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
107 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
108 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphBookmarkListener
;
109 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
110 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
111 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
112 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
113 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
114 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphBookmarkEvent
;
115 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
116 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
117 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
118 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
119 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
120 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
121 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
122 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
123 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEventSource
;
124 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
125 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
126 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.MarkerEvent
;
127 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
128 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
129 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
130 import org
.eclipse
.ui
.IActionBars
;
131 import org
.eclipse
.ui
.IPartListener
;
132 import org
.eclipse
.ui
.IWorkbenchActionConstants
;
133 import org
.eclipse
.ui
.IWorkbenchPart
;
134 import org
.eclipse
.ui
.PlatformUI
;
135 import org
.eclipse
.ui
.actions
.ActionFactory
;
136 import org
.eclipse
.ui
.handlers
.IHandlerActivation
;
137 import org
.eclipse
.ui
.handlers
.IHandlerService
;
140 * An abstract view all time graph views can inherit
142 * This view contains either a time graph viewer, or a time graph combo which is
143 * divided between a tree viewer on the left and a time graph viewer on the right.
145 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
, IResourceChangeListener
{
147 /** Constant indicating that all levels of the time graph should be expanded */
148 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
150 private static final Pattern RGBA_PATTERN
= Pattern
.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
152 private static final Logger LOGGER
= TraceCompassLog
.getLogger(AbstractTimeGraphView
.class);
153 private static final String LOG_STRING_WITH_PARAM
= "[TimeGraphView:%s] viewId=%s, %s"; //$NON-NLS-1$
154 private static final String LOG_STRING
= "[TimeGraphView:%s] viewId=%s"; //$NON-NLS-1$
163 // ------------------------------------------------------------------------
165 // ------------------------------------------------------------------------
167 /** The timegraph wrapper */
168 private ITimeGraphWrapper fTimeGraphWrapper
;
170 private AtomicInteger fDirty
= new AtomicInteger();
172 private final Object fZoomThreadResultLock
= new Object();
174 /** The selected trace */
175 private ITmfTrace fTrace
;
177 /** The selected trace editor file*/
178 private IFile fEditorFile
;
180 /** The timegraph entry list */
181 private List
<TimeGraphEntry
> fEntryList
;
183 /** The trace to entry list hash map */
184 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
186 /** The trace to filters hash map */
187 private final Map
<ITmfTrace
, @NonNull ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
189 /** The trace to view context hash map */
190 private final Map
<ITmfTrace
, ViewContext
> fViewContext
= new HashMap
<>();
192 /** The trace to marker event sources hash map */
193 private final Map
<ITmfTrace
, List
<IMarkerEventSource
>> fMarkerEventSourcesMap
= new HashMap
<>();
195 /** The trace to build thread hash map */
196 private final Map
<ITmfTrace
, Job
> fBuildJobMap
= new HashMap
<>();
198 /** The start time */
199 private long fStartTime
= SWT
.DEFAULT
;
202 private long fEndTime
= SWT
.DEFAULT
;
204 /** The display width */
205 private final int fDisplayWidth
;
207 /** The zoom thread */
208 private ZoomThread fZoomThread
;
210 /** The next resource action */
211 private Action fNextResourceAction
;
213 /** The previous resource action */
214 private Action fPreviousResourceAction
;
216 /** A comparator class */
217 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
219 /** The redraw state used to prevent unnecessary queuing of display runnables */
220 private State fRedrawState
= State
.IDLE
;
222 /** The redraw synchronization object */
223 private final Object fSyncObj
= new Object();
225 /** The presentation provider for this view */
226 private final TimeGraphPresentationProvider fPresentation
;
228 /** The tree column label array, or null if combo is not used */
229 private String
[] fColumns
;
231 private Comparator
<ITimeGraphEntry
>[] fColumnComparators
;
233 /** The tree label provider, or null if combo is not used */
234 private TreeLabelProvider fLabelProvider
= null;
236 /** The time graph content provider */
237 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
239 /** The relative weight of the sash, ignored if combo is not used */
240 private int[] fWeight
= { 1, 3 };
242 /** The filter column label array, or null if filter is not used */
243 private String
[] fFilterColumns
;
245 /** The pack done flag */
246 private boolean fPackDone
= false;
248 /** The filter content provider, or null if filter is not used */
249 private ITreeContentProvider fFilterContentProvider
;
251 /** The filter label provider, or null if filter is not used */
252 private TreeLabelProvider fFilterLabelProvider
;
254 private int fAutoExpandLevel
= ALL_LEVELS
;
256 /** The default column index for sorting */
257 private int fInitialSortColumn
= 0;
259 /** The default column index for sorting */
260 private int fCurrentSortColumn
= 0;
262 /** The current sort direction */
263 private int fSortDirection
= SWT
.DOWN
;
265 /** Flag to indicate to reveal selection */
266 private volatile boolean fIsRevealSelection
= false;
269 * Menu Manager for context-sensitive menu for time graph entries.
270 * This will be used on the tree viewer in case of the time graph combo
271 * or the on the namespace in case of a single time graph viewer.
273 private final @NonNull MenuManager fEntryMenuManager
= new MenuManager();
275 /** Time Graph View part listener */
276 private TimeGraphPartListener fPartListener
;
278 /** Action for the find command. There is only one for all Time Graph views */
279 private static final ShowFindDialogAction FIND_ACTION
= new ShowFindDialogAction();
281 /** The find action handler */
282 private ActionHandler fFindActionHandler
;
284 /** The find handler activation */
285 private IHandlerActivation fFindHandlerActivation
;
287 /** The find target to use */
288 private final FindTarget fFindTarget
;
290 // ------------------------------------------------------------------------
292 // ------------------------------------------------------------------------
294 private interface ITimeGraphWrapper
{
296 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
);
298 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
);
300 TimeGraphViewer
getTimeGraphViewer();
302 void addSelectionListener(ITimeGraphSelectionListener listener
);
304 ISelectionProvider
getSelectionProvider();
308 boolean isDisposed();
312 void setInput(Object input
);
316 void setFilters(@NonNull ViewerFilter
[] filters
);
318 @NonNull ViewerFilter
[] getFilters();
324 void setAutoExpandLevel(int level
);
326 boolean getExpandedState(ITimeGraphEntry entry
);
328 void setExpandedState(ITimeGraphEntry entry
, boolean expanded
);
330 void setFilterColumns(String
[] columnNames
);
332 void setFilterContentProvider(ITreeContentProvider contentProvider
);
334 void setFilterLabelProvider(ITableLabelProvider labelProvider
);
336 IAction
getShowFilterDialogAction();
338 void performAlign(int offset
, int width
);
340 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
342 int getAvailableWidth(int requestedOffset
);
344 ITimeGraphEntry
getSelection();
346 void setSelection(ITimeGraphEntry selection
);
348 void selectAndReveal(@NonNull ITimeGraphEntry selection
);
350 void setPinned(boolean pinned
);
354 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
355 private TimeGraphViewer viewer
;
357 private TimeGraphViewerWrapper(Composite parent
, int style
) {
358 viewer
= new TimeGraphViewer(parent
, style
);
362 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
363 viewer
.setTimeGraphContentProvider(timeGraphContentProvider
);
367 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
368 viewer
.setTimeGraphProvider(timeGraphPresentationProvider
);
372 public TimeGraphViewer
getTimeGraphViewer() {
377 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
378 viewer
.addSelectionListener(listener
);
382 public ISelectionProvider
getSelectionProvider() {
383 return viewer
.getSelectionProvider();
387 public void setFocus() {
392 public boolean isDisposed() {
393 return viewer
.getControl().isDisposed();
397 public void setInput(Object input
) {
398 viewer
.setInput(input
);
402 public Object
getInput() {
403 return viewer
.getInput();
407 public void setFilterColumns(String
[] columnNames
) {
408 viewer
.setFilterColumns(columnNames
);
412 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
413 viewer
.setFilterContentProvider(contentProvider
);
417 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
418 viewer
.setFilterLabelProvider(labelProvider
);
422 public void setFilters(@NonNull ViewerFilter
[] filters
) {
423 viewer
.setFilters(filters
);
427 public @NonNull ViewerFilter
[] getFilters() {
428 return viewer
.getFilters();
432 public IAction
getShowFilterDialogAction() {
433 return viewer
.getShowFilterDialogAction();
437 public void refresh() {
442 public void redraw() {
443 viewer
.getControl().redraw();
447 public void update() {
448 viewer
.getControl().update();
452 public void setAutoExpandLevel(int level
) {
453 viewer
.setAutoExpandLevel(level
);
457 public boolean getExpandedState(ITimeGraphEntry entry
) {
458 return viewer
.getExpandedState(entry
);
462 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
463 viewer
.setExpandedState(entry
, expanded
);
467 public void performAlign(int offset
, int width
) {
468 viewer
.performAlign(offset
, width
);
472 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
473 return viewer
.getTimeViewAlignmentInfo();
477 public int getAvailableWidth(int requestedOffset
) {
478 return viewer
.getAvailableWidth(requestedOffset
);
482 public ITimeGraphEntry
getSelection() {
483 return viewer
.getSelection();
487 public void setSelection(ITimeGraphEntry selection
) {
488 viewer
.setSelection(selection
);
492 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
493 viewer
.selectAndReveal(selection
);
497 public void setPinned(boolean pinned
) {
498 viewer
.setPinned(pinned
);
502 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
503 private TimeGraphCombo combo
;
505 private TimeGraphComboWrapper(Composite parent
, int style
) {
506 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
510 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
511 combo
.setTimeGraphContentProvider(timeGraphContentProvider
);
515 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
516 combo
.setTimeGraphProvider(timeGraphPresentationProvider
);
520 public TimeGraphViewer
getTimeGraphViewer() {
521 return combo
.getTimeGraphViewer();
525 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
526 combo
.addSelectionListener(listener
);
530 public ISelectionProvider
getSelectionProvider() {
531 return combo
.getTreeViewer();
535 public void setFocus() {
540 public boolean isDisposed() {
541 return combo
.isDisposed();
545 public void setInput(Object input
) {
546 combo
.setInput(input
);
550 public Object
getInput() {
551 return combo
.getInput();
555 public void setFilterColumns(String
[] columnNames
) {
556 combo
.setFilterColumns(columnNames
);
560 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
561 combo
.setFilterContentProvider(contentProvider
);
565 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
566 combo
.setFilterLabelProvider(labelProvider
);
570 public void setFilters(@NonNull ViewerFilter
[] filters
) {
571 combo
.setFilters(filters
);
575 public @NonNull ViewerFilter
[] getFilters() {
576 return combo
.getFilters();
580 public IAction
getShowFilterDialogAction() {
581 return combo
.getShowFilterDialogAction();
585 public void refresh() {
590 public void redraw() {
595 public void update() {
600 public void setAutoExpandLevel(int level
) {
601 combo
.setAutoExpandLevel(level
);
605 public boolean getExpandedState(ITimeGraphEntry entry
) {
606 return combo
.getExpandedState(entry
);
610 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
611 combo
.setExpandedState(entry
, expanded
);
614 TimeGraphCombo
getTimeGraphCombo() {
618 TreeViewer
getTreeViewer() {
619 return combo
.getTreeViewer();
623 public void performAlign(int offset
, int width
) {
624 combo
.performAlign(offset
, width
);
628 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
629 return combo
.getTimeViewAlignmentInfo();
633 public int getAvailableWidth(int requestedOffset
) {
634 return combo
.getAvailableWidth(requestedOffset
);
638 public ITimeGraphEntry
getSelection() {
639 return combo
.getTimeGraphViewer().getSelection();
643 public void setSelection(ITimeGraphEntry selection
) {
644 combo
.setSelection(selection
);
648 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
649 combo
.selectAndReveal(selection
);
653 public void setPinned(boolean pinned
) {
654 combo
.setPinned(pinned
);
659 * Base class to provide the labels for the tree viewer. Views extending
660 * this class typically need to override the getColumnText method if they
661 * have more than one column to display
663 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
666 public void addListener(ILabelProviderListener listener
) {
670 public void dispose() {
674 public boolean isLabelProperty(Object element
, String property
) {
679 public void removeListener(ILabelProviderListener listener
) {
683 public Image
getColumnImage(Object element
, int columnIndex
) {
688 public String
getColumnText(Object element
, int columnIndex
) {
689 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
690 if (columnIndex
== 0) {
691 return entry
.getName();
697 public Image
getImage(Object element
) {
702 public String
getText(Object element
) {
703 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
704 return entry
.getName();
709 // TODO: This can implement ICoreRunnable once support for Eclipse 4.5. is not necessary anymore.
710 private class BuildRunnable
{
711 private final @NonNull ITmfTrace fBuildTrace
;
712 private final @NonNull ITmfTrace fParentTrace
;
714 public BuildRunnable(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
) {
716 fParentTrace
= parentTrace
;
719 public void run(IProgressMonitor monitor
) {
720 LOGGER
.info(() -> getLogMessage("BuildThreadStart", "trace=" + fBuildTrace
.getName())); //$NON-NLS-1$ //$NON-NLS-2$
722 buildEntryList(fBuildTrace
, fParentTrace
, NonNullUtils
.checkNotNull(monitor
));
723 synchronized (fBuildJobMap
) {
724 fBuildJobMap
.remove(fBuildTrace
);
727 LOGGER
.info(() -> getLogMessage("BuildThreadEnd", null)); //$NON-NLS-1$
735 protected abstract class ZoomThread
extends Thread
{
736 private final long fZoomStartTime
;
737 private final long fZoomEndTime
;
738 private final long fResolution
;
739 private final @NonNull IProgressMonitor fMonitor
;
751 public ZoomThread(long startTime
, long endTime
, long resolution
) {
752 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
753 fZoomStartTime
= startTime
;
754 fZoomEndTime
= endTime
;
755 fResolution
= resolution
;
756 fMonitor
= new NullProgressMonitor();
760 * @return the zoom start time
762 public long getZoomStartTime() {
763 return fZoomStartTime
;
767 * @return the zoom end time
769 public long getZoomEndTime() {
774 * @return the resolution
776 public long getResolution() {
781 * @return the monitor
783 public @NonNull IProgressMonitor
getMonitor() {
788 * Cancel the zoom thread
790 public void cancel() {
791 fMonitor
.setCanceled(true);
795 public final void run() {
796 LOGGER
.info(() -> getLogMessage("ZoomThreadStart", "start=" + fZoomStartTime
+ ", end=" + fZoomEndTime
)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
799 fDirty
.decrementAndGet();
801 LOGGER
.info(() -> getLogMessage("ZoomThreadEnd", null)); //$NON-NLS-1$
805 * Applies the results of the ZoomThread calculations.
807 * Note: This method makes sure that only the results of the last
808 * created ZoomThread are applied.
811 * the code to run in order to apply the results
814 protected void applyResults(Runnable runnable
) {
815 synchronized (fZoomThreadResultLock
) {
816 if (this == fZoomThread
) {
823 * Run the zoom operation.
826 public abstract void doRun();
829 private class ZoomThreadByEntry
extends ZoomThread
{
830 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
832 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
833 super(startTime
, endTime
, resolution
);
834 fZoomEntryList
= entryList
;
838 public void doRun() {
839 LOGGER
.config(() -> getLogMessage("ZoomThreadGettingStates", null)); //$NON-NLS-1$
841 for (TimeGraphEntry entry
: fZoomEntryList
) {
842 if (getMonitor().isCanceled()) {
843 LOGGER
.info(() -> getLogMessage("ZoomThreadCanceled", null)); //$NON-NLS-1$
849 zoom(entry
, getMonitor());
851 /* Refresh the arrows when zooming */
852 LOGGER
.config(() -> getLogMessage("ZoomThreadGettingLinks", null)); //$NON-NLS-1$
853 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
855 /* Refresh the view-specific markers when zooming */
856 LOGGER
.config(() -> getLogMessage("ZoomThreadGettingMarkers", null)); //$NON-NLS-1$
857 List
<IMarkerEvent
> markers
= new ArrayList
<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
858 /* Refresh the trace-specific markers when zooming */
859 markers
.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
861 if (events
!= null) {
862 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
864 fTimeGraphWrapper
.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
865 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(markers
);
870 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
871 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
873 entry
.setZoomedEventList(null);
876 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
877 if (zoomedEventList
!= null) {
879 entry
.setZoomedEventList(zoomedEventList
);
884 for (TimeGraphEntry child
: entry
.getChildren()) {
885 if (monitor
.isCanceled()) {
888 zoom(child
, monitor
);
894 // ------------------------------------------------------------------------
896 // ------------------------------------------------------------------------
899 * Constructs a time graph view that contains either a time graph viewer or
900 * a time graph combo.
902 * By default, the view uses a time graph viewer. To use a time graph combo,
903 * the subclass constructor must call {@link #setTreeColumns(String[])} and
904 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
909 * The presentation provider
911 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
913 fPresentation
= pres
;
914 fDisplayWidth
= Display
.getDefault().getBounds().width
;
915 fFindTarget
= new FindTarget();
918 // ------------------------------------------------------------------------
919 // Getters and setters
920 // ------------------------------------------------------------------------
923 * Getter for the time graph combo
925 * @return The time graph combo, or null if combo is not used
927 protected TimeGraphCombo
getTimeGraphCombo() {
928 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
929 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
935 * Getter for the time graph viewer
937 * @return The time graph viewer
939 protected TimeGraphViewer
getTimeGraphViewer() {
940 return fTimeGraphWrapper
.getTimeGraphViewer();
944 * Getter for the presentation provider
946 * @return The time graph presentation provider
948 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
949 return fPresentation
;
953 * Sets the tree column labels.
955 * This should be called from the constructor.
958 * The array of tree column labels
960 protected void setTreeColumns(final String
[] columns
) {
961 setTreeColumns(columns
, null, 0);
965 * Sets the tree column labels.
967 * This should be called from the constructor.
970 * The array of tree column labels
972 * An array of column comparators for sorting of columns when
973 * clicking on column header
974 * @param initialSortColumn
975 * Index of column to sort initially
978 protected void setTreeColumns(final String
[] columns
, final Comparator
<ITimeGraphEntry
>[] comparators
, int initialSortColumn
) {
979 checkPartNotCreated();
981 fColumnComparators
= comparators
;
982 fInitialSortColumn
= initialSortColumn
;
986 * Sets the tree label provider.
988 * This should be called from the constructor.
991 * The tree label provider
993 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
994 checkPartNotCreated();
995 fLabelProvider
= tlp
;
999 * Sets the time graph content provider.
1001 * This should be called from the constructor.
1004 * The time graph content provider
1007 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
1008 checkPartNotCreated();
1009 fTimeGraphContentProvider
= tgcp
;
1013 * Sets the relative weight of each part of the time graph combo.
1015 * This should be called from the constructor.
1018 * The array (length 2) of relative weights of each part of the combo
1020 protected void setWeight(final int[] weights
) {
1021 checkPartNotCreated();
1026 * Sets the filter column labels.
1028 * This should be called from the constructor.
1030 * @param filterColumns
1031 * The array of filter column labels
1033 protected void setFilterColumns(final String
[] filterColumns
) {
1034 checkPartNotCreated();
1035 fFilterColumns
= filterColumns
;
1039 * Sets the filter content provider.
1041 * This should be called from the constructor.
1043 * @param contentProvider
1044 * The filter content provider
1047 protected void setFilterContentProvider(final ITreeContentProvider contentProvider
) {
1048 checkPartNotCreated();
1049 fFilterContentProvider
= contentProvider
;
1053 * Sets the filter label provider.
1055 * This should be called from the constructor.
1057 * @param labelProvider
1058 * The filter label provider
1060 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
1061 checkPartNotCreated();
1062 fFilterLabelProvider
= labelProvider
;
1065 private void checkPartNotCreated() {
1066 if (getParentComposite() != null) {
1067 throw new IllegalStateException("This method must be called before createPartControl."); //$NON-NLS-1$
1072 * Gets the display width
1074 * @return the display width
1076 protected int getDisplayWidth() {
1077 return fDisplayWidth
;
1081 * Gets the comparator for the entries
1083 * @return The entry comparator
1085 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
1086 return fEntryComparator
;
1090 * Sets the comparator class for the entries.
1092 * This comparator will apply recursively to entries that implement
1093 * {@link TimeGraphEntry#sortChildren(Comparator)}.
1096 * A comparator object
1098 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
1099 fEntryComparator
= comparator
;
1103 * Gets the trace displayed in the view
1107 protected ITmfTrace
getTrace() {
1112 * Gets the start time
1114 * @return The start time
1116 protected long getStartTime() {
1121 * Sets the start time
1126 protected void setStartTime(long time
) {
1133 * @return The end time
1135 protected long getEndTime() {
1145 protected void setEndTime(long time
) {
1150 * Sets the auto-expand level to be used for the input of the view. The
1151 * value 0 means that there is no auto-expand; 1 means that top-level
1152 * elements are expanded, but not their children; 2 means that top-level
1153 * elements are expanded, and their children, but not grand-children; and so
1156 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1160 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1161 * levels of the tree
1163 protected void setAutoExpandLevel(int level
) {
1164 fAutoExpandLevel
= level
;
1165 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
1166 if (tgWrapper
!= null) {
1167 tgWrapper
.setAutoExpandLevel(level
);
1172 * Gets the entry list for a trace
1177 * @return the entry list map
1179 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
1180 synchronized (fEntryListMap
) {
1181 return fEntryListMap
.get(trace
);
1186 * Adds a trace entry list to the entry list map
1191 * the list of time graph entries
1193 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1194 synchronized (fEntryListMap
) {
1195 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1200 * Adds a list of entries to a trace's entry list
1205 * the list of time graph entries to add
1207 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1208 synchronized (fEntryListMap
) {
1209 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1210 if (entryList
== null) {
1211 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1213 entryList
.addAll(list
);
1219 * Removes a list of entries from a trace's entry list
1224 * the list of time graph entries to remove
1226 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1227 synchronized (fEntryListMap
) {
1228 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1229 if (entryList
!= null) {
1230 entryList
.removeAll(list
);
1236 * Text for the "next" button
1238 * @return The "next" button text
1240 protected String
getNextText() {
1241 return Messages
.AbstractTimeGraphtView_NextText
;
1245 * Tooltip for the "next" button
1247 * @return Tooltip for the "next" button
1249 protected String
getNextTooltip() {
1250 return Messages
.AbstractTimeGraphView_NextTooltip
;
1254 * Text for the "Previous" button
1256 * @return The "Previous" button text
1258 protected String
getPrevText() {
1259 return Messages
.AbstractTimeGraphView_PreviousText
;
1263 * Tooltip for the "previous" button
1265 * @return Tooltip for the "previous" button
1267 protected String
getPrevTooltip() {
1268 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
1272 FindTarget
getFindTarget() {
1277 * Formats a log message for this class
1280 * The event to log, that will be appended to the class name to
1281 * make the full event name
1283 * The string of extra parameters to add to the log message, in
1284 * the format name=value[, name=value]*, or <code>null</code> for
1286 * @return The complete log message for this class
1288 private String
getLogMessage(String event
, @Nullable String parameters
) {
1289 if (parameters
== null) {
1290 return String
.format(LOG_STRING
, event
, getViewId());
1292 return String
.format(LOG_STRING_WITH_PARAM
, event
, getViewId(), parameters
);
1295 // ------------------------------------------------------------------------
1297 // ------------------------------------------------------------------------
1300 public void createPartControl(Composite parent
) {
1301 super.createPartControl(parent
);
1302 if (fColumns
== null || fLabelProvider
== null) {
1303 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
1305 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
1306 fTimeGraphWrapper
= wrapper
;
1307 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
1308 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
1309 combo
.setTreeLabelProvider(fLabelProvider
);
1310 combo
.setTreeColumns(fColumns
);
1311 if (fColumnComparators
!= null) {
1312 createColumnSelectionListener(combo
.getTreeViewer());
1314 // Add double click listener to tree viewer
1315 createDoubleClickListener(combo
.getTreeViewer());
1317 fTimeGraphWrapper
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
1318 fTimeGraphWrapper
.setFilterContentProvider(fFilterContentProvider
!= null ? fFilterContentProvider
: fTimeGraphContentProvider
);
1319 fTimeGraphWrapper
.setFilterLabelProvider(fFilterLabelProvider
);
1320 fTimeGraphWrapper
.setFilterColumns(fFilterColumns
);
1322 fTimeGraphWrapper
.setTimeGraphPresentationProvider(fPresentation
);
1323 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
1325 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1327 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
1328 final long startTime
= event
.getStartTime();
1329 final long endTime
= event
.getEndTime();
1330 TmfTimeRange range
= new TmfTimeRange(TmfTimestamp
.fromNanos(startTime
), TmfTimestamp
.fromNanos(endTime
));
1331 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
1332 startZoomThread(startTime
, endTime
);
1336 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1338 public void timeSelected(TimeGraphTimeEvent event
) {
1339 ITmfTimestamp startTime
= TmfTimestamp
.fromNanos(event
.getBeginTime());
1340 ITmfTimestamp endTime
= TmfTimestamp
.fromNanos(event
.getEndTime());
1341 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
1345 fTimeGraphWrapper
.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1347 public void bookmarkAdded(final TimeGraphBookmarkEvent event
) {
1349 ResourcesPlugin
.getWorkspace().run(new IWorkspaceRunnable() {
1351 public void run(IProgressMonitor monitor
) throws CoreException
{
1352 IMarkerEvent bookmark
= event
.getBookmark();
1353 IMarker marker
= fEditorFile
.createMarker(IMarker
.BOOKMARK
);
1354 marker
.setAttribute(IMarker
.MESSAGE
, bookmark
.getLabel());
1355 marker
.setAttribute(ITmfMarker
.MARKER_TIME
, Long
.toString(bookmark
.getTime()));
1356 if (bookmark
.getDuration() > 0) {
1357 marker
.setAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(bookmark
.getDuration()));
1358 marker
.setAttribute(IMarker
.LOCATION
,
1359 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTimeRange
,
1360 TmfTimestamp
.fromNanos(bookmark
.getTime()),
1361 TmfTimestamp
.fromNanos(bookmark
.getTime() + bookmark
.getDuration())));
1363 marker
.setAttribute(IMarker
.LOCATION
,
1364 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTime
,
1365 TmfTimestamp
.fromNanos(bookmark
.getTime())));
1367 marker
.setAttribute(ITmfMarker
.MARKER_COLOR
, bookmark
.getColor().toString());
1370 } catch (CoreException e
) {
1371 Activator
.getDefault().logError(e
.getMessage());
1376 public void bookmarkRemoved(TimeGraphBookmarkEvent event
) {
1378 IMarkerEvent bookmark
= event
.getBookmark();
1379 IMarker
[] markers
= fEditorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1380 for (IMarker marker
: markers
) {
1381 if (bookmark
.getLabel().equals(marker
.getAttribute(IMarker
.MESSAGE
)) &&
1382 Long
.toString(bookmark
.getTime()).equals(marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null)) &&
1383 Long
.toString(bookmark
.getDuration()).equals(marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0))) &&
1384 bookmark
.getColor().toString().equals(marker
.getAttribute(ITmfMarker
.MARKER_COLOR
))) {
1389 } catch (CoreException e
) {
1390 Activator
.getDefault().logError(e
.getMessage());
1395 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
1397 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
1398 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
1400 // View Action Handling
1402 contributeToActionBars();
1404 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
1405 if (trace
!= null) {
1406 traceSelected(new TmfTraceSelectedSignal(this, trace
));
1409 // make selection available to other views
1410 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
1412 ResourcesPlugin
.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent
.POST_CHANGE
);
1414 createContextMenu();
1415 fPartListener
= new TimeGraphPartListener();
1416 getSite().getPage().addPartListener(fPartListener
);
1420 public void setFocus() {
1421 fTimeGraphWrapper
.setFocus();
1425 public void dispose() {
1427 synchronized (fBuildJobMap
) {
1428 fBuildJobMap
.values().forEach(buildJob
-> {
1432 if (fZoomThread
!= null) {
1433 fZoomThread
.cancel();
1435 ResourcesPlugin
.getWorkspace().removeResourceChangeListener(this);
1436 getSite().getPage().removePartListener(fPartListener
);
1443 public void resourceChanged(final IResourceChangeEvent event
) {
1444 for (final IMarkerDelta delta
: event
.findMarkerDeltas(IMarker
.BOOKMARK
, false)) {
1445 if (delta
.getResource().equals(fEditorFile
)) {
1446 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1453 private static List
<IMarkerEvent
> refreshBookmarks(final IFile editorFile
) {
1454 List
<IMarkerEvent
> bookmarks
= new ArrayList
<>();
1455 if (editorFile
== null || !editorFile
.exists()) {
1459 IMarker
[] markers
= editorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1460 for (IMarker marker
: markers
) {
1461 String label
= marker
.getAttribute(IMarker
.MESSAGE
, (String
) null);
1462 String time
= marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null);
1463 String duration
= marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0));
1464 String rgba
= marker
.getAttribute(ITmfMarker
.MARKER_COLOR
, (String
) null);
1465 if (label
!= null && time
!= null && rgba
!= null) {
1466 Matcher matcher
= RGBA_PATTERN
.matcher(rgba
);
1467 if (matcher
.matches()) {
1469 int red
= Integer
.valueOf(matcher
.group(1));
1470 int green
= Integer
.valueOf(matcher
.group(2));
1471 int blue
= Integer
.valueOf(matcher
.group(3));
1472 int alpha
= Integer
.valueOf(matcher
.group(4));
1473 RGBA color
= new RGBA(red
, green
, blue
, alpha
);
1474 bookmarks
.add(new MarkerEvent(null, Long
.valueOf(time
), Long
.valueOf(duration
), IMarkerEvent
.BOOKMARKS
, color
, label
, true));
1475 } catch (NumberFormatException e
) {
1476 Activator
.getDefault().logError(e
.getMessage());
1481 } catch (CoreException e
) {
1482 Activator
.getDefault().logError(e
.getMessage());
1489 // ------------------------------------------------------------------------
1491 // ------------------------------------------------------------------------
1494 * Handler for the trace opened signal.
1497 * The incoming signal
1500 public void traceOpened(TmfTraceOpenedSignal signal
) {
1501 loadTrace(signal
.getTrace());
1505 * Handler for the trace selected signal
1508 * The incoming signal
1511 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1512 if (signal
.getTrace() == fTrace
) {
1515 loadTrace(signal
.getTrace());
1519 * Trace is closed: clear the data structures and the view
1522 * the signal received
1525 public void traceClosed(final TmfTraceClosedSignal signal
) {
1526 resetView(signal
.getTrace());
1527 if (signal
.getTrace() == fTrace
) {
1530 setStartTime(SWT
.DEFAULT
);
1531 setEndTime(SWT
.DEFAULT
);
1537 * Handler for the selection range signal.
1540 * The signal that's received
1544 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1545 if (signal
.getSource() == this || fTrace
== null) {
1548 final long beginTime
= signal
.getBeginTime().toNanos();
1549 final long endTime
= signal
.getEndTime().toNanos();
1551 Display
.getDefault().asyncExec(new Runnable() {
1554 if (fTimeGraphWrapper
.isDisposed()) {
1557 if (beginTime
== endTime
) {
1558 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1560 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
, true);
1562 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getSelectionBegin());
1568 * Handler for the window range signal.
1571 * The signal that's received
1575 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1576 if (signal
.getSource() == this || fTrace
== null) {
1579 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1582 final long startTime
= signal
.getCurrentRange().getStartTime().toNanos();
1583 final long endTime
= signal
.getCurrentRange().getEndTime().toNanos();
1584 Display
.getDefault().asyncExec(new Runnable() {
1587 if (fTimeGraphWrapper
.isDisposed()) {
1590 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1591 startZoomThread(startTime
, endTime
);
1597 * @param signal the format of the timestamps was updated.
1600 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1601 fTimeGraphWrapper
.refresh();
1605 * A marker event source has been updated
1612 public void markerEventSourceUpdated(final TmfMarkerEventSourceUpdatedSignal signal
) {
1613 getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1614 getTimeGraphViewer().setMarkers(null);
1618 // ------------------------------------------------------------------------
1620 // ------------------------------------------------------------------------
1622 private void loadTrace(final ITmfTrace trace
) {
1623 if (fZoomThread
!= null) {
1624 fZoomThread
.cancel();
1627 if (fTrace
!= null) {
1628 /* save the filters of the previous trace */
1629 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1630 fViewContext
.put(fTrace
, new ViewContext(fCurrentSortColumn
, fSortDirection
, fTimeGraphWrapper
.getSelection()));
1634 LOGGER
.info(() -> getLogMessage("LoadingTrace", "trace=" + trace
.getName())); //$NON-NLS-1$ //$NON-NLS-2$
1636 restoreViewContext();
1637 fEditorFile
= TmfTraceManager
.getInstance().getTraceEditorFile(trace
);
1638 synchronized (fEntryListMap
) {
1639 fEntryList
= fEntryListMap
.get(fTrace
);
1640 if (fEntryList
== null) {
1643 setStartTime(fTrace
.getStartTime().toNanos());
1644 setEndTime(fTrace
.getEndTime().toNanos());
1651 * Forces a rebuild of the entries list, even if entries already exist for this trace
1653 protected void rebuild() {
1654 setStartTime(Long
.MAX_VALUE
);
1655 setEndTime(Long
.MIN_VALUE
);
1657 ITmfTrace viewTrace
= fTrace
;
1658 if (viewTrace
== null) {
1661 resetView(viewTrace
);
1663 List
<IMarkerEventSource
> markerEventSources
= new ArrayList
<>();
1664 synchronized (fBuildJobMap
) {
1665 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1666 if (trace
== null) {
1669 markerEventSources
.addAll(TmfTraceAdapterManager
.getAdapters(trace
, IMarkerEventSource
.class));
1670 Job buildJob
= new Job(getTitle() + Messages
.AbstractTimeGraphView_BuildJob
) {
1672 protected IStatus
run(IProgressMonitor monitor
) {
1673 new BuildRunnable(trace
, viewTrace
).run(monitor
);
1675 return Status
.OK_STATUS
;
1678 fBuildJobMap
.put(trace
, buildJob
);
1679 buildJob
.schedule();
1682 fMarkerEventSourcesMap
.put(viewTrace
, markerEventSources
);
1686 * Method called when synching to a given timestamp. Inheriting classes can
1687 * perform actions here to update the view at the given timestamp.
1690 * The currently selected time
1692 protected void synchingToTime(long time
) {
1697 * Return the list of traces whose data or analysis results will be used to
1698 * populate the view. By default, if the trace is an experiment, the traces
1699 * under it will be returned, otherwise, the trace itself is returned.
1701 * A build thread will be started for each trace returned by this method,
1702 * some of which may receive events in live streaming mode.
1705 * The trace associated with this view, can be null
1706 * @return List of traces with data to display
1708 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@Nullable ITmfTrace trace
) {
1709 return TmfTraceManager
.getTraceSet(trace
);
1713 * Build the entry list to show in this time graph view.
1715 * Called from the BuildJob for each trace returned by
1716 * {@link #getTracesToBuild(ITmfTrace)}.
1718 * Root entries must be added to the entry list by calling the
1719 * {@link #addToEntryList(ITmfTrace, List)} method with the list of entries
1720 * to add and where the trace in parameter should be the parentTrace.
1721 * Entries that are children of other entries will be automatically picked
1722 * up after refreshing the root entries.
1724 * The full event list is also normally computed for every entry that is
1725 * created. It should be set for each entry by calling the
1726 * {@link TimeGraphEntry#setEventList(List)}. These full event lists will be
1727 * used to display something while the zoomed event lists are being
1728 * calculated when the window range is updated. Also, when fully zoomed out,
1729 * it is this list of events that is displayed.
1731 * Also, when all the entries have been added and their events set, this
1732 * method can finish by calling the refresh() method like this:
1735 * if (parentTrace.equals(getTrace())) {
1741 * The trace being built
1742 * @param parentTrace
1743 * The parent of the trace set, or the trace itself
1745 * The progress monitor object
1748 protected abstract void buildEntryList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1751 * Gets the list of event for an entry in a given time range.
1753 * Called from the ZoomThread for every entry to update the zoomed event
1754 * list. Can be an empty implementation if the view does not support zoomed
1755 * event lists. Can also be used to compute the full event list.
1758 * The entry to get events for
1760 * Start of the time range
1762 * End of the time range
1766 * The progress monitor object
1767 * @return The list of events for the entry
1769 protected abstract @Nullable List
<@NonNull ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1770 long startTime
, long endTime
, long resolution
,
1771 @NonNull IProgressMonitor monitor
);
1774 * Gets the list of links (displayed as arrows) for a trace in a given
1775 * timerange. Default implementation returns an empty list.
1778 * Start of the time range
1780 * End of the time range
1784 * The progress monitor object
1785 * @return The list of link events
1787 protected @Nullable List
<@NonNull ILinkEvent
> getLinkList(long startTime
, long endTime
,
1788 long resolution
, @NonNull IProgressMonitor monitor
) {
1789 return new ArrayList
<>();
1793 * Gets the list of view-specific marker categories. Default implementation
1794 * returns an empty list.
1796 * @return The list of marker categories
1799 protected @NonNull List
<String
> getViewMarkerCategories() {
1800 return new ArrayList
<>();
1804 * Gets the list of view-specific markers for a trace in a given time range.
1805 * Default implementation returns an empty list.
1808 * Start of the time range
1810 * End of the time range
1814 * The progress monitor object
1815 * @return The list of marker events
1818 protected @NonNull List
<IMarkerEvent
> getViewMarkerList(long startTime
, long endTime
,
1819 long resolution
, @NonNull IProgressMonitor monitor
) {
1820 return new ArrayList
<>();
1824 * Gets the list of trace-specific markers for a trace in a given time range.
1827 * Start of the time range
1829 * End of the time range
1833 * The progress monitor object
1834 * @return The list of marker events
1837 protected @NonNull List
<IMarkerEvent
> getTraceMarkerList(long startTime
, long endTime
,
1838 long resolution
, @NonNull IProgressMonitor monitor
) {
1839 List
<IMarkerEvent
> markers
= new ArrayList
<>();
1840 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1841 for (String category
: markerEventSource
.getMarkerCategories()) {
1842 if (monitor
.isCanceled()) {
1845 markers
.addAll(markerEventSource
.getMarkerList(category
, startTime
, endTime
, resolution
, monitor
));
1852 * Get the list of current marker categories.
1854 * @return The list of marker categories
1857 protected @NonNull List
<String
> getMarkerCategories() {
1858 Set
<String
> categories
= new LinkedHashSet
<>(getViewMarkerCategories());
1859 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1860 categories
.addAll(markerEventSource
.getMarkerCategories());
1862 return new ArrayList
<>(categories
);
1866 * Gets the list of marker event sources for a given trace.
1870 * @return The list of marker event sources
1873 private @NonNull List
<IMarkerEventSource
> getMarkerEventSources(ITmfTrace trace
) {
1874 List
<IMarkerEventSource
> markerEventSources
= fMarkerEventSourcesMap
.get(trace
);
1875 if (markerEventSources
== null) {
1876 markerEventSources
= Collections
.emptyList();
1878 return markerEventSources
;
1882 * Refresh the display
1884 protected void refresh() {
1885 LOGGER
.info(() -> getLogMessage("RefreshRequested", null)); //$NON-NLS-1$
1886 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1887 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1890 LOGGER
.info(() -> getLogMessage("RefreshStart", null)); //$NON-NLS-1$
1891 if (fTimeGraphWrapper
.isDisposed()) {
1894 fDirty
.incrementAndGet();
1896 boolean hasEntries
= false;
1897 synchronized (fEntryListMap
) {
1898 fEntryList
= fEntryListMap
.get(fTrace
);
1899 if (fEntryList
== null) {
1900 fEntryList
= new CopyOnWriteArrayList
<>();
1901 } else if (fEntryComparator
!= null) {
1902 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1903 Collections
.sort(list
, fEntryComparator
);
1904 for (ITimeGraphEntry entry
: list
) {
1905 sortChildren(entry
, fEntryComparator
);
1908 fEntryList
.addAll(list
);
1910 hasEntries
= !fEntryList
.isEmpty();
1912 boolean inputChanged
= fEntryList
!= fTimeGraphWrapper
.getInput();
1913 TimeGraphCombo combo
= getTimeGraphCombo();
1915 // Set redraw to false to only draw once
1916 if (combo
!= null) {
1917 combo
.getTreeViewer().getTree().setRedraw(false);
1919 getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
1921 fTimeGraphWrapper
.setInput(fEntryList
);
1922 /* restore the previously saved filters, if any */
1923 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1924 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1925 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1926 fTimeGraphWrapper
.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1927 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(null);
1930 fTimeGraphWrapper
.refresh();
1933 if (fIsRevealSelection
) {
1934 fIsRevealSelection
= false;
1935 ITimeGraphEntry entry1
= fTimeGraphWrapper
.getSelection();
1936 fTimeGraphWrapper
.setSelection(entry1
);
1939 if (combo
!= null) {
1940 combo
.getTreeViewer().getTree().setRedraw(true);
1942 getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
1944 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1945 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1946 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1948 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1949 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().toNanos();
1950 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().toNanos();
1951 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().toNanos();
1952 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().toNanos();
1953 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1954 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1955 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
, false);
1956 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1958 if (inputChanged
&& selectionBeginTime
!= SWT
.DEFAULT
) {
1959 synchingToTime(selectionBeginTime
);
1962 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1963 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1972 startZoomThread(startTime
, endTime
);
1974 fDirty
.decrementAndGet();
1975 LOGGER
.info(() -> getLogMessage("RefreshEnd", null)); //$NON-NLS-1$
1983 protected void redraw() {
1984 synchronized (fSyncObj
) {
1985 if (fRedrawState
== State
.IDLE
) {
1986 fRedrawState
= State
.BUSY
;
1988 fRedrawState
= State
.PENDING
;
1992 LOGGER
.info(() -> getLogMessage("RedrawRequested", null)); //$NON-NLS-1$
1993 Display
.getDefault().asyncExec(new Runnable() {
1996 LOGGER
.info(() -> getLogMessage("RedrawStart", null)); //$NON-NLS-1$
1997 if (fTimeGraphWrapper
.isDisposed()) {
2000 fTimeGraphWrapper
.redraw();
2001 fTimeGraphWrapper
.update();
2002 synchronized (fSyncObj
) {
2003 if (fRedrawState
== State
.PENDING
) {
2004 fRedrawState
= State
.IDLE
;
2007 fRedrawState
= State
.IDLE
;
2010 LOGGER
.info(() -> getLogMessage("RedrawEnd", null)); //$NON-NLS-1$
2015 private void sortChildren(ITimeGraphEntry entry
, Comparator
<ITimeGraphEntry
> comparator
) {
2016 if (entry
instanceof TimeGraphEntry
) {
2017 ((TimeGraphEntry
) entry
).sortChildren(comparator
);
2019 for (ITimeGraphEntry child
: entry
.getChildren()) {
2020 sortChildren(child
, comparator
);
2025 * Start or restart the zoom thread.
2028 * the zoom start time
2033 protected final void startZoomThread(long startTime
, long endTime
) {
2034 long clampedStartTime
= (fStartTime
== Long
.MAX_VALUE ? startTime
: Math
.min(Math
.max(startTime
, fStartTime
), fEndTime
));
2035 long clampedEndTime
= (fEndTime
== Long
.MIN_VALUE ? endTime
: Math
.max(Math
.min(endTime
, fEndTime
), fStartTime
));
2036 fDirty
.incrementAndGet();
2037 boolean restart
= false;
2038 if (fZoomThread
!= null) {
2039 fZoomThread
.cancel();
2040 if (fZoomThread
.fZoomStartTime
== clampedStartTime
&& fZoomThread
.fZoomEndTime
== clampedEndTime
) {
2044 long resolution
= Math
.max(1, (clampedEndTime
- clampedStartTime
) / fDisplayWidth
);
2045 fZoomThread
= createZoomThread(clampedStartTime
, clampedEndTime
, resolution
, restart
);
2046 if (fZoomThread
!= null) {
2047 // Don't start a new thread right away if results are being applied
2048 // from an old ZoomThread. Otherwise, the old results might
2049 // overwrite the new results if it finishes after.
2050 synchronized (fZoomThreadResultLock
) {
2051 fZoomThread
.start();
2054 fDirty
.decrementAndGet();
2059 * Create a zoom thread.
2062 * the zoom start time
2068 * true if restarting zoom for the same time range
2069 * @return a zoom thread
2072 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
2073 final List
<TimeGraphEntry
> entryList
= fEntryList
;
2074 if (entryList
== null) {
2077 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
2080 private void makeActions() {
2081 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
2082 fPreviousResourceAction
.setText(getPrevText());
2083 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
2084 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
2085 fNextResourceAction
.setText(getNextText());
2086 fNextResourceAction
.setToolTipText(getNextTooltip());
2089 private void contributeToActionBars() {
2090 IActionBars bars
= getViewSite().getActionBars();
2091 fillLocalToolBar(bars
.getToolBarManager());
2092 fillLocalMenu(bars
.getMenuManager());
2096 * Add actions to local tool bar manager
2098 * @param manager the tool bar manager
2100 protected void fillLocalToolBar(IToolBarManager manager
) {
2101 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
2102 manager
.add(fTimeGraphWrapper
.getShowFilterDialogAction());
2104 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
2105 manager
.add(new Separator());
2106 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
2107 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
2108 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
2109 manager
.add(new Separator());
2110 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getToggleBookmarkAction());
2111 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousMarkerAction());
2112 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextMarkerAction());
2113 manager
.add(new Separator());
2114 manager
.add(fPreviousResourceAction
);
2115 manager
.add(fNextResourceAction
);
2116 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
2117 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
2118 manager
.add(new Separator());
2122 * Add actions to local menu manager
2124 * @param manager the tool bar manager
2127 protected void fillLocalMenu(IMenuManager manager
) {
2128 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getMarkersMenu());
2135 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
2136 if (fTimeGraphWrapper
== null) {
2139 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
2146 public int getAvailableWidth(int requestedOffset
) {
2147 if (fTimeGraphWrapper
== null) {
2150 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
2157 public void performAlign(int offset
, int width
) {
2158 if (fTimeGraphWrapper
!= null) {
2159 fTimeGraphWrapper
.performAlign(offset
, width
);
2164 * Returns whether or not the time graph view is dirty. The time graph view
2165 * is considered dirty if it has yet to completely update its model.
2167 * This method is meant to be used by tests in order to know when it is safe
2170 * Note: If a trace is smaller than the initial window range (see
2171 * {@link ITmfTrace#getInitialRangeOffset}) this method will return true
2174 * @return true if the time graph view has yet to completely update its
2175 * model, false otherwise
2178 public boolean isDirty() {
2179 if (fTrace
== null) {
2183 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
2184 long startTime
= ctx
.getWindowRange().getStartTime().toNanos();
2185 long endTime
= ctx
.getWindowRange().getEndTime().toNanos();
2187 // If the time graph control hasn't updated all the way to the end of
2188 // the window range then it's dirty. A refresh should happen later.
2189 if (fTimeGraphWrapper
.getTimeGraphViewer().getTime0() != startTime
|| fTimeGraphWrapper
.getTimeGraphViewer().getTime1() != endTime
) {
2193 if (fZoomThread
== null) {
2194 // The zoom thread is null but we might be just about to create it (refresh called).
2195 return fDirty
.get() != 0;
2197 // Dirty if the zoom thread is not done or if it hasn't zoomed all the
2198 // way to the end of the window range. In the latter case, there should be
2199 // a subsequent zoom thread that will be triggered.
2200 return fDirty
.get() != 0 || fZoomThread
.getZoomStartTime() != startTime
|| fZoomThread
.getZoomEndTime() != endTime
;
2203 private void createColumnSelectionListener(TreeViewer treeViewer
) {
2204 for (int i
= 0; i
< fColumnComparators
.length
; i
++) {
2205 final int index
= i
;
2206 final Comparator
<ITimeGraphEntry
> comp
= fColumnComparators
[index
];
2207 final Tree tree
= treeViewer
.getTree();
2208 final TreeColumn column
= tree
.getColumn(i
);
2211 column
.addSelectionListener(new SelectionAdapter() {
2213 public void widgetSelected(SelectionEvent e
) {
2214 TreeColumn prevSortcolumn
= tree
.getSortColumn();
2215 int direction
= tree
.getSortDirection();
2216 if (prevSortcolumn
== column
) {
2217 direction
= (direction
== SWT
.DOWN
) ? SWT
.UP
: SWT
.DOWN
;
2219 direction
= SWT
.DOWN
;
2221 tree
.setSortColumn(column
);
2222 tree
.setSortDirection(direction
);
2223 fSortDirection
= direction
;
2224 fCurrentSortColumn
= index
;
2225 Comparator
<ITimeGraphEntry
> comparator
= comp
;
2227 if (comparator
instanceof ITimeGraphEntryComparator
) {
2228 ((ITimeGraphEntryComparator
) comparator
).setDirection(direction
);
2230 if (direction
!= SWT
.DOWN
) {
2231 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2233 setEntryComparator(comparator
);
2234 fIsRevealSelection
= true;
2235 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
2236 ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getControl().setFocus();
2245 private void createDoubleClickListener(TreeViewer treeViewer
) {
2246 treeViewer
.addDoubleClickListener(event
-> {
2247 if (event
.getSelection() instanceof TreeSelection
) {
2248 TreeSelection selection
= (TreeSelection
) event
.getSelection();
2249 if (selection
.getFirstElement() instanceof ITimeGraphEntry
) {
2250 ITimeGraphEntry entry
= (ITimeGraphEntry
) selection
.getFirstElement();
2251 if (entry
.hasChildren()) {
2252 fTimeGraphWrapper
.setExpandedState(entry
, !fTimeGraphWrapper
.getExpandedState(entry
));
2260 private void restoreViewContext() {
2261 TimeGraphCombo combo
= getTimeGraphCombo();
2262 ViewContext viewContext
= fViewContext
.get(fTrace
);
2263 if (combo
!= null) {
2264 if (fColumnComparators
!= null) {
2265 // restore sort settings
2266 fSortDirection
= SWT
.DOWN
;
2267 fCurrentSortColumn
= fInitialSortColumn
;
2268 if (viewContext
!= null) {
2269 fSortDirection
= viewContext
.getSortDirection();
2270 fCurrentSortColumn
= viewContext
.getSortColumn();
2272 if ((fCurrentSortColumn
< fColumnComparators
.length
) && (fColumnComparators
[fCurrentSortColumn
] != null)) {
2273 Comparator
<ITimeGraphEntry
> comparator
= fColumnComparators
[fCurrentSortColumn
];
2274 if (comparator
instanceof ITimeGraphEntryComparator
) {
2275 ((ITimeGraphEntryComparator
) comparator
).setDirection(fSortDirection
);
2277 if (fSortDirection
!= SWT
.DOWN
) {
2278 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2280 setEntryComparator(comparator
);
2286 private void applyViewContext() {
2287 TimeGraphCombo combo
= getTimeGraphCombo();
2288 ViewContext viewContext
= fViewContext
.get(fTrace
);
2289 if (combo
!= null) {
2290 TreeViewer treeViewer
= combo
.getTreeViewer();
2291 final Tree tree
= treeViewer
.getTree();
2292 final TreeColumn column
= tree
.getColumn(fCurrentSortColumn
);
2293 tree
.setSortDirection(fSortDirection
);
2294 tree
.setSortColumn(column
);
2295 combo
.getTreeViewer().getControl().setFocus();
2297 // restore and reveal selection
2298 if ((viewContext
!= null) && (viewContext
.getSelection() != null)) {
2299 fTimeGraphWrapper
.setSelection(viewContext
.getSelection());
2301 fViewContext
.remove(fTrace
);
2304 private static class ViewContext
{
2305 private int fSortColumnIndex
;
2306 private int fSortDirection
;
2307 private @Nullable ITimeGraphEntry fSelection
;
2309 ViewContext(int sortColunm
, int sortDirection
, ITimeGraphEntry selection
) {
2310 fSortColumnIndex
= sortColunm
;
2311 fSortDirection
= sortDirection
;
2312 fSelection
= selection
;
2315 * @return the sortColumn
2317 public int getSortColumn() {
2318 return fSortColumnIndex
;
2321 * @return the sortDirection
2323 public int getSortDirection() {
2324 return fSortDirection
;
2327 * @return the selection
2329 public ITimeGraphEntry
getSelection() {
2335 * Method to reset the view internal data for a given trace.
2337 * When overriding this method make sure to call the super
2341 * trace to reset the view for.
2344 protected void resetView(ITmfTrace viewTrace
) {
2345 if (viewTrace
== null) {
2348 synchronized (fBuildJobMap
) {
2349 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
2350 Job buildJob
= fBuildJobMap
.remove(trace
);
2351 if (buildJob
!= null) {
2356 synchronized (fEntryListMap
) {
2357 fEntryListMap
.remove(viewTrace
);
2359 fViewContext
.remove(viewTrace
);
2360 fFiltersMap
.remove(viewTrace
);
2361 fMarkerEventSourcesMap
.remove(viewTrace
);
2362 if (viewTrace
== fTrace
) {
2363 if (fZoomThread
!= null) {
2364 fZoomThread
.cancel();
2370 private void createContextMenu() {
2371 TimeGraphCombo combo
= getTimeGraphCombo();
2372 fEntryMenuManager
.setRemoveAllWhenShown(true);
2373 if (combo
!= null) {
2374 TreeViewer treeViewer
= combo
.getTreeViewer();
2375 Tree tree
= treeViewer
.getTree();
2376 Menu menu
= fEntryMenuManager
.createContextMenu(tree
);
2379 TimeGraphControl timeGraphControl
= getTimeGraphViewer().getTimeGraphControl();
2380 final Menu entryMenu
= fEntryMenuManager
.createContextMenu(timeGraphControl
);
2381 timeGraphControl
.addTimeGraphEntryMenuListener(new MenuDetectListener() {
2383 public void menuDetected(MenuDetectEvent event
) {
2384 Point p
= timeGraphControl
.toControl(event
.x
, event
.y
);
2386 * The TimeGraphControl will call the TimeGraphEntryMenuListener
2387 * before the TimeEventMenuListener. If the event is
2388 * triggered on the namespace then show the menu else
2391 if (p
.x
< getTimeGraphViewer().getNameSpace()) {
2392 timeGraphControl
.setMenu(entryMenu
);
2394 timeGraphControl
.setMenu(null);
2400 fEntryMenuManager
.addMenuListener(new IMenuListener() {
2402 public void menuAboutToShow(IMenuManager manager
) {
2403 fillTimeGraphEntryContextMenu(fEntryMenuManager
);
2404 fEntryMenuManager
.add(new GroupMarker(IWorkbenchActionConstants
.MB_ADDITIONS
));
2407 getSite().registerContextMenu(fEntryMenuManager
, fTimeGraphWrapper
.getSelectionProvider());
2413 * @param menuManager
2414 * a menuManager to fill
2417 protected void fillTimeGraphEntryContextMenu (@NonNull IMenuManager menuManager
) {
2421 * Inner classes used for searching
2424 public ITimeGraphEntry
getSelection() {
2425 return fTimeGraphWrapper
.getSelection();
2428 public void selectAndReveal(@NonNull ITimeGraphEntry entry
) {
2429 fTimeGraphWrapper
.selectAndReveal(entry
);
2432 public ITimeGraphEntry
[] getEntries() {
2433 TimeGraphViewer viewer
= getTimeGraphViewer();
2434 return viewer
.getTimeGraphContentProvider().getElements(viewer
.getInput());
2437 public Shell
getShell() {
2438 return getSite().getShell();
2442 class TimeGraphPartListener
implements IPartListener
{
2444 public void partActivated(IWorkbenchPart part
) {
2445 if (part
== AbstractTimeGraphView
.this) {
2446 synchronized (FIND_ACTION
) {
2447 if (fFindActionHandler
== null) {
2448 fFindActionHandler
= new ActionHandler(FIND_ACTION
);
2450 if (fFindHandlerActivation
== null) {
2451 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2452 fFindHandlerActivation
= ((IHandlerService
) service
).activateHandler(ActionFactory
.FIND
.getCommandId(), fFindActionHandler
);
2456 // Notify action for all parts
2457 FIND_ACTION
.partActivated(part
);
2460 public void partDeactivated(IWorkbenchPart part
) {
2461 if ((part
== AbstractTimeGraphView
.this) && (fFindHandlerActivation
!= null)) {
2462 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2463 ((IHandlerService
) service
).deactivateHandler(fFindHandlerActivation
);
2464 fFindHandlerActivation
= null;
2468 public void partBroughtToTop(IWorkbenchPart part
) {
2471 public void partClosed(IWorkbenchPart part
) {
2474 public void partOpened(IWorkbenchPart part
) {