1 /*******************************************************************************
2 * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 * Geneviève Bastien - Move code to provide base classes for time graph view
13 * Marc-Andre Laperle - Add time zone preference
14 * Geneviève Bastien - Add event links between entries
15 *******************************************************************************/
17 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
;
19 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Collections
;
23 import java
.util
.Comparator
;
24 import java
.util
.HashMap
;
25 import java
.util
.LinkedHashSet
;
26 import java
.util
.List
;
29 import java
.util
.concurrent
.CopyOnWriteArrayList
;
30 import java
.util
.concurrent
.atomic
.AtomicInteger
;
31 import java
.util
.regex
.Matcher
;
32 import java
.util
.regex
.Pattern
;
34 import org
.eclipse
.core
.resources
.IFile
;
35 import org
.eclipse
.core
.resources
.IMarker
;
36 import org
.eclipse
.core
.resources
.IMarkerDelta
;
37 import org
.eclipse
.core
.resources
.IResource
;
38 import org
.eclipse
.core
.resources
.IResourceChangeEvent
;
39 import org
.eclipse
.core
.resources
.IResourceChangeListener
;
40 import org
.eclipse
.core
.resources
.IWorkspaceRunnable
;
41 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
42 import org
.eclipse
.core
.runtime
.CoreException
;
43 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
44 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
45 import org
.eclipse
.jdt
.annotation
.NonNull
;
46 import org
.eclipse
.jdt
.annotation
.Nullable
;
47 import org
.eclipse
.jface
.action
.Action
;
48 import org
.eclipse
.jface
.action
.GroupMarker
;
49 import org
.eclipse
.jface
.action
.IAction
;
50 import org
.eclipse
.jface
.action
.IMenuListener
;
51 import org
.eclipse
.jface
.action
.IMenuManager
;
52 import org
.eclipse
.jface
.action
.IStatusLineManager
;
53 import org
.eclipse
.jface
.action
.IToolBarManager
;
54 import org
.eclipse
.jface
.action
.MenuManager
;
55 import org
.eclipse
.jface
.action
.Separator
;
56 import org
.eclipse
.jface
.commands
.ActionHandler
;
57 import org
.eclipse
.jface
.viewers
.AbstractTreeViewer
;
58 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
59 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
60 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
61 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
62 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
63 import org
.eclipse
.jface
.viewers
.TreeSelection
;
64 import org
.eclipse
.jface
.viewers
.TreeViewer
;
65 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
66 import org
.eclipse
.osgi
.util
.NLS
;
67 import org
.eclipse
.swt
.SWT
;
68 import org
.eclipse
.swt
.events
.MenuDetectEvent
;
69 import org
.eclipse
.swt
.events
.MenuDetectListener
;
70 import org
.eclipse
.swt
.events
.SelectionAdapter
;
71 import org
.eclipse
.swt
.events
.SelectionEvent
;
72 import org
.eclipse
.swt
.graphics
.Image
;
73 import org
.eclipse
.swt
.graphics
.Point
;
74 import org
.eclipse
.swt
.graphics
.RGBA
;
75 import org
.eclipse
.swt
.widgets
.Composite
;
76 import org
.eclipse
.swt
.widgets
.Display
;
77 import org
.eclipse
.swt
.widgets
.Menu
;
78 import org
.eclipse
.swt
.widgets
.Shell
;
79 import org
.eclipse
.swt
.widgets
.Tree
;
80 import org
.eclipse
.swt
.widgets
.TreeColumn
;
81 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
82 import org
.eclipse
.tracecompass
.tmf
.core
.resources
.ITmfMarker
;
83 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
84 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
85 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
86 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
87 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
88 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
89 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
90 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
91 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
92 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
93 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceAdapterManager
;
94 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
95 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
96 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
97 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
98 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
99 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
100 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphBookmarkListener
;
101 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
102 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
103 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
104 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
105 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
106 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphBookmarkEvent
;
107 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
108 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
109 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
110 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
111 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
112 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
113 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
114 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
115 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEventSource
;
116 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
117 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
118 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.MarkerEvent
;
119 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
120 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
121 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
122 import org
.eclipse
.ui
.IActionBars
;
123 import org
.eclipse
.ui
.IPartListener
;
124 import org
.eclipse
.ui
.IWorkbenchActionConstants
;
125 import org
.eclipse
.ui
.IWorkbenchPart
;
126 import org
.eclipse
.ui
.PlatformUI
;
127 import org
.eclipse
.ui
.actions
.ActionFactory
;
128 import org
.eclipse
.ui
.handlers
.IHandlerActivation
;
129 import org
.eclipse
.ui
.handlers
.IHandlerService
;
132 * An abstract view all time graph views can inherit
134 * This view contains either a time graph viewer, or a time graph combo which is
135 * divided between a tree viewer on the left and a time graph viewer on the right.
137 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
, IResourceChangeListener
{
139 /** Constant indicating that all levels of the time graph should be expanded */
140 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
142 private static final Pattern RGBA_PATTERN
= Pattern
.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
151 // ------------------------------------------------------------------------
153 // ------------------------------------------------------------------------
155 /** The timegraph wrapper */
156 private ITimeGraphWrapper fTimeGraphWrapper
;
158 private AtomicInteger fDirty
= new AtomicInteger();
160 /** The selected trace */
161 private ITmfTrace fTrace
;
163 /** The selected trace editor file*/
164 private IFile fEditorFile
;
166 /** The timegraph entry list */
167 private List
<TimeGraphEntry
> fEntryList
;
169 /** The trace to entry list hash map */
170 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
172 /** The trace to filters hash map */
173 private final Map
<ITmfTrace
, @NonNull ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
175 /** The trace to view context hash map */
176 private final Map
<ITmfTrace
, ViewContext
> fViewContext
= new HashMap
<>();
178 /** The trace to marker event sources hash map */
179 private final Map
<ITmfTrace
, List
<IMarkerEventSource
>> fMarkerEventSourcesMap
= new HashMap
<>();
181 /** The trace to build thread hash map */
182 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
184 /** The start time */
185 private long fStartTime
= SWT
.DEFAULT
;
188 private long fEndTime
= SWT
.DEFAULT
;
190 /** The display width */
191 private final int fDisplayWidth
;
193 /** The zoom thread */
194 private ZoomThread fZoomThread
;
196 /** The next resource action */
197 private Action fNextResourceAction
;
199 /** The previous resource action */
200 private Action fPreviousResourceAction
;
202 /** A comparator class */
203 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
205 /** The redraw state used to prevent unnecessary queuing of display runnables */
206 private State fRedrawState
= State
.IDLE
;
208 /** The redraw synchronization object */
209 private final Object fSyncObj
= new Object();
211 /** The presentation provider for this view */
212 private final TimeGraphPresentationProvider fPresentation
;
214 /** The tree column label array, or null if combo is not used */
215 private String
[] fColumns
;
217 private Comparator
<ITimeGraphEntry
>[] fColumnComparators
;
219 /** The tree label provider, or null if combo is not used */
220 private TreeLabelProvider fLabelProvider
= null;
222 /** The time graph content provider */
223 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
225 /** The relative weight of the sash, ignored if combo is not used */
226 private int[] fWeight
= { 1, 3 };
228 /** The filter column label array, or null if filter is not used */
229 private String
[] fFilterColumns
;
231 /** The pack done flag */
232 private boolean fPackDone
= false;
234 /** The filter content provider, or null if filter is not used */
235 private ITreeContentProvider fFilterContentProvider
;
237 /** The filter label provider, or null if filter is not used */
238 private TreeLabelProvider fFilterLabelProvider
;
240 private int fAutoExpandLevel
= ALL_LEVELS
;
242 /** The default column index for sorting */
243 private int fInitialSortColumn
= 0;
245 /** The default column index for sorting */
246 private int fCurrentSortColumn
= 0;
248 /** The current sort direction */
249 private int fSortDirection
= SWT
.DOWN
;
251 /** Flag to indicate to reveal selection */
252 private volatile boolean fIsRevealSelection
= false;
255 * Menu Manager for context-sensitive menu for time graph entries.
256 * This will be used on the tree viewer in case of the time graph combo
257 * or the on the namespace in case of a single time graph viewer.
259 private final @NonNull MenuManager fEntryMenuManager
= new MenuManager();
261 /** Time Graph View part listener */
262 private TimeGraphPartListener fPartListener
;
264 /** Action for the find command. There is only one for all Time Graph views */
265 private static final ShowFindDialogAction FIND_ACTION
= new ShowFindDialogAction();
267 /** The find action handler */
268 private static ActionHandler fFindActionHandler
;
270 /** The find handler activation */
271 private static IHandlerActivation fFindHandlerActivation
;
273 /** The find target to use */
274 private final FindTarget fFindTarget
;
276 // ------------------------------------------------------------------------
278 // ------------------------------------------------------------------------
280 private interface ITimeGraphWrapper
{
282 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
);
284 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
);
286 TimeGraphViewer
getTimeGraphViewer();
288 void addSelectionListener(ITimeGraphSelectionListener listener
);
290 ISelectionProvider
getSelectionProvider();
294 boolean isDisposed();
298 void setInput(Object input
);
302 void setFilters(@NonNull ViewerFilter
[] filters
);
304 @NonNull ViewerFilter
[] getFilters();
310 void setAutoExpandLevel(int level
);
312 boolean getExpandedState(ITimeGraphEntry entry
);
314 void setExpandedState(ITimeGraphEntry entry
, boolean expanded
);
316 void setFilterColumns(String
[] columnNames
);
318 void setFilterContentProvider(ITreeContentProvider contentProvider
);
320 void setFilterLabelProvider(ITableLabelProvider labelProvider
);
322 IAction
getShowFilterDialogAction();
324 void performAlign(int offset
, int width
);
326 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
328 int getAvailableWidth(int requestedOffset
);
330 ITimeGraphEntry
getSelection();
332 void setSelection(ITimeGraphEntry selection
);
334 void selectAndReveal(@NonNull ITimeGraphEntry selection
);
338 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
339 private TimeGraphViewer viewer
;
341 private TimeGraphViewerWrapper(Composite parent
, int style
) {
342 viewer
= new TimeGraphViewer(parent
, style
);
346 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
347 viewer
.setTimeGraphContentProvider(timeGraphContentProvider
);
351 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
352 viewer
.setTimeGraphProvider(timeGraphPresentationProvider
);
356 public TimeGraphViewer
getTimeGraphViewer() {
361 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
362 viewer
.addSelectionListener(listener
);
366 public ISelectionProvider
getSelectionProvider() {
367 return viewer
.getSelectionProvider();
371 public void setFocus() {
376 public boolean isDisposed() {
377 return viewer
.getControl().isDisposed();
381 public void setInput(Object input
) {
382 viewer
.setInput(input
);
386 public Object
getInput() {
387 return viewer
.getInput();
391 public void setFilterColumns(String
[] columnNames
) {
392 viewer
.setFilterColumns(columnNames
);
396 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
397 viewer
.setFilterContentProvider(contentProvider
);
401 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
402 viewer
.setFilterLabelProvider(labelProvider
);
406 public void setFilters(@NonNull ViewerFilter
[] filters
) {
407 viewer
.setFilters(filters
);
411 public @NonNull ViewerFilter
[] getFilters() {
412 return viewer
.getFilters();
416 public IAction
getShowFilterDialogAction() {
417 return viewer
.getShowFilterDialogAction();
421 public void refresh() {
426 public void redraw() {
427 viewer
.getControl().redraw();
431 public void update() {
432 viewer
.getControl().update();
436 public void setAutoExpandLevel(int level
) {
437 viewer
.setAutoExpandLevel(level
);
441 public boolean getExpandedState(ITimeGraphEntry entry
) {
442 return viewer
.getExpandedState(entry
);
446 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
447 viewer
.setExpandedState(entry
, expanded
);
451 public void performAlign(int offset
, int width
) {
452 viewer
.performAlign(offset
, width
);
456 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
457 return viewer
.getTimeViewAlignmentInfo();
461 public int getAvailableWidth(int requestedOffset
) {
462 return viewer
.getAvailableWidth(requestedOffset
);
466 public ITimeGraphEntry
getSelection() {
467 return viewer
.getSelection();
471 public void setSelection(ITimeGraphEntry selection
) {
472 viewer
.setSelection(selection
);
476 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
477 viewer
.selectAndReveal(selection
);
481 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
482 private TimeGraphCombo combo
;
484 private TimeGraphComboWrapper(Composite parent
, int style
) {
485 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
489 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider
) {
490 combo
.setTimeGraphContentProvider(timeGraphContentProvider
);
494 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider
) {
495 combo
.setTimeGraphProvider(timeGraphPresentationProvider
);
499 public TimeGraphViewer
getTimeGraphViewer() {
500 return combo
.getTimeGraphViewer();
504 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
505 combo
.addSelectionListener(listener
);
509 public ISelectionProvider
getSelectionProvider() {
510 return combo
.getTreeViewer();
514 public void setFocus() {
519 public boolean isDisposed() {
520 return combo
.isDisposed();
524 public void setInput(Object input
) {
525 combo
.setInput(input
);
529 public Object
getInput() {
530 return combo
.getInput();
534 public void setFilterColumns(String
[] columnNames
) {
535 combo
.setFilterColumns(columnNames
);
539 public void setFilterContentProvider(ITreeContentProvider contentProvider
) {
540 combo
.setFilterContentProvider(contentProvider
);
544 public void setFilterLabelProvider(ITableLabelProvider labelProvider
) {
545 combo
.setFilterLabelProvider(labelProvider
);
549 public void setFilters(@NonNull ViewerFilter
[] filters
) {
550 combo
.setFilters(filters
);
554 public @NonNull ViewerFilter
[] getFilters() {
555 return combo
.getFilters();
559 public IAction
getShowFilterDialogAction() {
560 return combo
.getShowFilterDialogAction();
564 public void refresh() {
569 public void redraw() {
574 public void update() {
579 public void setAutoExpandLevel(int level
) {
580 combo
.setAutoExpandLevel(level
);
584 public boolean getExpandedState(ITimeGraphEntry entry
) {
585 return combo
.getExpandedState(entry
);
589 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
590 combo
.setExpandedState(entry
, expanded
);
593 TimeGraphCombo
getTimeGraphCombo() {
597 TreeViewer
getTreeViewer() {
598 return combo
.getTreeViewer();
602 public void performAlign(int offset
, int width
) {
603 combo
.performAlign(offset
, width
);
607 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
608 return combo
.getTimeViewAlignmentInfo();
612 public int getAvailableWidth(int requestedOffset
) {
613 return combo
.getAvailableWidth(requestedOffset
);
617 public ITimeGraphEntry
getSelection() {
618 return combo
.getTimeGraphViewer().getSelection();
622 public void setSelection(ITimeGraphEntry selection
) {
623 combo
.setSelection(selection
);
627 public void selectAndReveal(@NonNull ITimeGraphEntry selection
) {
628 combo
.selectAndReveal(selection
);
633 * Base class to provide the labels for the tree viewer. Views extending
634 * this class typically need to override the getColumnText method if they
635 * have more than one column to display
637 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
640 public void addListener(ILabelProviderListener listener
) {
644 public void dispose() {
648 public boolean isLabelProperty(Object element
, String property
) {
653 public void removeListener(ILabelProviderListener listener
) {
657 public Image
getColumnImage(Object element
, int columnIndex
) {
662 public String
getColumnText(Object element
, int columnIndex
) {
663 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
664 if (columnIndex
== 0) {
665 return entry
.getName();
671 public Image
getImage(Object element
) {
676 public String
getText(Object element
) {
677 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
678 return entry
.getName();
683 private class BuildThread
extends Thread
{
684 private final @NonNull ITmfTrace fBuildTrace
;
685 private final @NonNull ITmfTrace fParentTrace
;
686 private final @NonNull IProgressMonitor fMonitor
;
688 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
689 super(name
+ " build"); //$NON-NLS-1$
691 fParentTrace
= parentTrace
;
692 fMonitor
= new NullProgressMonitor();
697 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
698 synchronized (fBuildThreadMap
) {
699 fBuildThreadMap
.remove(fBuildTrace
);
703 public void cancel() {
704 fMonitor
.setCanceled(true);
712 protected abstract class ZoomThread
extends Thread
{
713 private final long fZoomStartTime
;
714 private final long fZoomEndTime
;
715 private final long fResolution
;
716 private final @NonNull IProgressMonitor fMonitor
;
728 public ZoomThread(long startTime
, long endTime
, long resolution
) {
729 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
730 fZoomStartTime
= startTime
;
731 fZoomEndTime
= endTime
;
732 fResolution
= resolution
;
733 fMonitor
= new NullProgressMonitor();
737 * @return the zoom start time
739 public long getZoomStartTime() {
740 return fZoomStartTime
;
744 * @return the zoom end time
746 public long getZoomEndTime() {
751 * @return the resolution
753 public long getResolution() {
758 * @return the monitor
760 public @NonNull IProgressMonitor
getMonitor() {
765 * Cancel the zoom thread
767 public void cancel() {
768 fMonitor
.setCanceled(true);
772 public final void run() {
774 fDirty
.decrementAndGet();
778 * Run the zoom operation.
781 public abstract void doRun();
784 private class ZoomThreadByEntry
extends ZoomThread
{
785 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
787 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
788 super(startTime
, endTime
, resolution
);
789 fZoomEntryList
= entryList
;
793 public void doRun() {
794 for (TimeGraphEntry entry
: fZoomEntryList
) {
795 if (getMonitor().isCanceled()) {
801 zoom(entry
, getMonitor());
803 /* Refresh the arrows when zooming */
804 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
805 if (events
!= null) {
806 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
809 /* Refresh the view-specific markers when zooming */
810 List
<IMarkerEvent
> markers
= new ArrayList
<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
811 /* Refresh the trace-specific markers when zooming */
812 markers
.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
813 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(markers
);
817 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
818 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
819 entry
.setZoomedEventList(null);
821 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
822 if (zoomedEventList
!= null) {
823 entry
.setZoomedEventList(zoomedEventList
);
827 for (ITimeGraphEntry child
: entry
.getChildren()) {
828 if (monitor
.isCanceled()) {
831 if (child
instanceof TimeGraphEntry
) {
832 zoom((TimeGraphEntry
) child
, monitor
);
839 // ------------------------------------------------------------------------
841 // ------------------------------------------------------------------------
844 * Constructs a time graph view that contains either a time graph viewer or
845 * a time graph combo.
847 * By default, the view uses a time graph viewer. To use a time graph combo,
848 * the subclass constructor must call {@link #setTreeColumns(String[])} and
849 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
854 * The presentation provider
856 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
858 fPresentation
= pres
;
859 fDisplayWidth
= Display
.getDefault().getBounds().width
;
860 fFindTarget
= new FindTarget();
863 // ------------------------------------------------------------------------
864 // Getters and setters
865 // ------------------------------------------------------------------------
868 * Getter for the time graph combo
870 * @return The time graph combo, or null if combo is not used
872 protected TimeGraphCombo
getTimeGraphCombo() {
873 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
874 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
880 * Getter for the time graph viewer
882 * @return The time graph viewer
884 protected TimeGraphViewer
getTimeGraphViewer() {
885 return fTimeGraphWrapper
.getTimeGraphViewer();
889 * Getter for the presentation provider
891 * @return The time graph presentation provider
893 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
894 return fPresentation
;
898 * Sets the tree column labels.
900 * This should be called from the constructor.
903 * The array of tree column labels
905 protected void setTreeColumns(final String
[] columns
) {
906 setTreeColumns(columns
, null, 0);
910 * Sets the tree column labels.
912 * This should be called from the constructor.
915 * The array of tree column labels
917 * An array of column comparators for sorting of columns when
918 * clicking on column header
919 * @param initialSortColumn
920 * Index of column to sort initially
923 protected void setTreeColumns(final String
[] columns
, final Comparator
<ITimeGraphEntry
>[] comparators
, int initialSortColumn
) {
924 checkPartNotCreated();
926 fColumnComparators
= comparators
;
927 fInitialSortColumn
= initialSortColumn
;
931 * Sets the tree label provider.
933 * This should be called from the constructor.
936 * The tree label provider
938 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
939 checkPartNotCreated();
940 fLabelProvider
= tlp
;
944 * Sets the time graph content provider.
946 * This should be called from the constructor.
949 * The time graph content provider
952 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
953 checkPartNotCreated();
954 fTimeGraphContentProvider
= tgcp
;
958 * Sets the relative weight of each part of the time graph combo.
960 * This should be called from the constructor.
963 * The array (length 2) of relative weights of each part of the combo
965 protected void setWeight(final int[] weights
) {
966 checkPartNotCreated();
971 * Sets the filter column labels.
973 * This should be called from the constructor.
975 * @param filterColumns
976 * The array of filter column labels
978 protected void setFilterColumns(final String
[] filterColumns
) {
979 checkPartNotCreated();
980 fFilterColumns
= filterColumns
;
984 * Sets the filter content provider.
986 * This should be called from the constructor.
988 * @param contentProvider
989 * The filter content provider
992 protected void setFilterContentProvider(final ITreeContentProvider contentProvider
) {
993 checkPartNotCreated();
994 fFilterContentProvider
= contentProvider
;
998 * Sets the filter label provider.
1000 * This should be called from the constructor.
1002 * @param labelProvider
1003 * The filter label provider
1005 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
1006 checkPartNotCreated();
1007 fFilterLabelProvider
= labelProvider
;
1010 private void checkPartNotCreated() {
1011 if (getParentComposite() != null) {
1012 throw new IllegalStateException("This method must be called before createPartControl."); //$NON-NLS-1$
1017 * Gets the display width
1019 * @return the display width
1021 protected int getDisplayWidth() {
1022 return fDisplayWidth
;
1026 * Gets the comparator for the entries
1028 * @return The entry comparator
1030 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
1031 return fEntryComparator
;
1035 * Sets the comparator class for the entries.
1037 * This comparator will apply recursively to entries that implement
1038 * {@link TimeGraphEntry#sortChildren(Comparator)}.
1041 * A comparator object
1043 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
1044 fEntryComparator
= comparator
;
1048 * Gets the trace displayed in the view
1052 protected ITmfTrace
getTrace() {
1057 * Gets the start time
1059 * @return The start time
1061 protected long getStartTime() {
1066 * Sets the start time
1071 protected void setStartTime(long time
) {
1078 * @return The end time
1080 protected long getEndTime() {
1090 protected void setEndTime(long time
) {
1095 * Sets the auto-expand level to be used for the input of the view. The
1096 * value 0 means that there is no auto-expand; 1 means that top-level
1097 * elements are expanded, but not their children; 2 means that top-level
1098 * elements are expanded, and their children, but not grand-children; and so
1101 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1105 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1106 * levels of the tree
1108 protected void setAutoExpandLevel(int level
) {
1109 fAutoExpandLevel
= level
;
1110 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
1111 if (tgWrapper
!= null) {
1112 tgWrapper
.setAutoExpandLevel(level
);
1117 * Gets the entry list for a trace
1122 * @return the entry list map
1124 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
1125 synchronized (fEntryListMap
) {
1126 return fEntryListMap
.get(trace
);
1131 * Adds a trace entry list to the entry list map
1136 * the list of time graph entries
1138 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1139 synchronized (fEntryListMap
) {
1140 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1145 * Adds a list of entries to a trace's entry list
1150 * the list of time graph entries to add
1152 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1153 synchronized (fEntryListMap
) {
1154 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1155 if (entryList
== null) {
1156 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
1158 entryList
.addAll(list
);
1164 * Removes a list of entries from a trace's entry list
1169 * the list of time graph entries to remove
1171 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
1172 synchronized (fEntryListMap
) {
1173 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
1174 if (entryList
!= null) {
1175 entryList
.removeAll(list
);
1181 * Text for the "next" button
1183 * @return The "next" button text
1185 protected String
getNextText() {
1186 return Messages
.AbstractTimeGraphtView_NextText
;
1190 * Tooltip for the "next" button
1192 * @return Tooltip for the "next" button
1194 protected String
getNextTooltip() {
1195 return Messages
.AbstractTimeGraphView_NextTooltip
;
1199 * Text for the "Previous" button
1201 * @return The "Previous" button text
1203 protected String
getPrevText() {
1204 return Messages
.AbstractTimeGraphView_PreviousText
;
1208 * Tooltip for the "previous" button
1210 * @return Tooltip for the "previous" button
1212 protected String
getPrevTooltip() {
1213 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
1217 FindTarget
getFindTarget() {
1221 // ------------------------------------------------------------------------
1223 // ------------------------------------------------------------------------
1226 public void createPartControl(Composite parent
) {
1227 super.createPartControl(parent
);
1228 if (fColumns
== null || fLabelProvider
== null) {
1229 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
1231 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
1232 fTimeGraphWrapper
= wrapper
;
1233 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
1234 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
1235 combo
.setTreeLabelProvider(fLabelProvider
);
1236 combo
.setTreeColumns(fColumns
);
1237 if (fColumnComparators
!= null) {
1238 createColumnSelectionListener(combo
.getTreeViewer());
1240 // Add double click listener to tree viewer
1241 createDoubleClickListener(combo
.getTreeViewer());
1243 fTimeGraphWrapper
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
1244 fTimeGraphWrapper
.setFilterContentProvider(fFilterContentProvider
!= null ? fFilterContentProvider
: fTimeGraphContentProvider
);
1245 fTimeGraphWrapper
.setFilterLabelProvider(fFilterLabelProvider
);
1246 fTimeGraphWrapper
.setFilterColumns(fFilterColumns
);
1248 fTimeGraphWrapper
.setTimeGraphPresentationProvider(fPresentation
);
1249 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
1251 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1253 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
1254 final long startTime
= event
.getStartTime();
1255 final long endTime
= event
.getEndTime();
1256 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
1257 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
1258 startZoomThread(startTime
, endTime
);
1262 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1264 public void timeSelected(TimeGraphTimeEvent event
) {
1265 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
1266 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
1267 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
1271 fTimeGraphWrapper
.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1273 public void bookmarkAdded(final TimeGraphBookmarkEvent event
) {
1275 ResourcesPlugin
.getWorkspace().run(new IWorkspaceRunnable() {
1277 public void run(IProgressMonitor monitor
) throws CoreException
{
1278 IMarkerEvent bookmark
= event
.getBookmark();
1279 IMarker marker
= fEditorFile
.createMarker(IMarker
.BOOKMARK
);
1280 marker
.setAttribute(IMarker
.MESSAGE
, bookmark
.getLabel());
1281 marker
.setAttribute(ITmfMarker
.MARKER_TIME
, Long
.toString(bookmark
.getTime()));
1282 if (bookmark
.getDuration() > 0) {
1283 marker
.setAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(bookmark
.getDuration()));
1284 marker
.setAttribute(IMarker
.LOCATION
,
1285 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTimeRange
,
1286 new TmfNanoTimestamp(bookmark
.getTime()),
1287 new TmfNanoTimestamp(bookmark
.getTime() + bookmark
.getDuration())));
1289 marker
.setAttribute(IMarker
.LOCATION
,
1290 NLS
.bind(org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
.TmfMarker_LocationTime
,
1291 new TmfNanoTimestamp(bookmark
.getTime())));
1293 marker
.setAttribute(ITmfMarker
.MARKER_COLOR
, bookmark
.getColor().toString());
1296 } catch (CoreException e
) {
1297 Activator
.getDefault().logError(e
.getMessage());
1302 public void bookmarkRemoved(TimeGraphBookmarkEvent event
) {
1304 IMarkerEvent bookmark
= event
.getBookmark();
1305 IMarker
[] markers
= fEditorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1306 for (IMarker marker
: markers
) {
1307 if (bookmark
.getLabel().equals(marker
.getAttribute(IMarker
.MESSAGE
)) &&
1308 Long
.toString(bookmark
.getTime()).equals(marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null)) &&
1309 Long
.toString(bookmark
.getDuration()).equals(marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0))) &&
1310 bookmark
.getColor().toString().equals(marker
.getAttribute(ITmfMarker
.MARKER_COLOR
))) {
1315 } catch (CoreException e
) {
1316 Activator
.getDefault().logError(e
.getMessage());
1321 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
1323 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
1324 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
1326 // View Action Handling
1328 contributeToActionBars();
1330 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
1331 if (trace
!= null) {
1332 traceSelected(new TmfTraceSelectedSignal(this, trace
));
1335 // make selection available to other views
1336 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
1338 ResourcesPlugin
.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent
.POST_CHANGE
);
1340 createContextMenu();
1341 fPartListener
= new TimeGraphPartListener();
1342 getSite().getPage().addPartListener(fPartListener
);
1346 public void setFocus() {
1347 fTimeGraphWrapper
.setFocus();
1351 public void dispose() {
1353 ResourcesPlugin
.getWorkspace().removeResourceChangeListener(this);
1354 getSite().getPage().removePartListener(fPartListener
);
1361 public void resourceChanged(final IResourceChangeEvent event
) {
1362 for (final IMarkerDelta delta
: event
.findMarkerDeltas(IMarker
.BOOKMARK
, false)) {
1363 if (delta
.getResource().equals(fEditorFile
)) {
1364 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1371 private static List
<IMarkerEvent
> refreshBookmarks(final IFile editorFile
) {
1372 List
<IMarkerEvent
> bookmarks
= new ArrayList
<>();
1373 if (editorFile
== null || !editorFile
.exists()) {
1377 IMarker
[] markers
= editorFile
.findMarkers(IMarker
.BOOKMARK
, false, IResource
.DEPTH_ZERO
);
1378 for (IMarker marker
: markers
) {
1379 String label
= marker
.getAttribute(IMarker
.MESSAGE
, (String
) null);
1380 String time
= marker
.getAttribute(ITmfMarker
.MARKER_TIME
, (String
) null);
1381 String duration
= marker
.getAttribute(ITmfMarker
.MARKER_DURATION
, Long
.toString(0));
1382 String rgba
= marker
.getAttribute(ITmfMarker
.MARKER_COLOR
, (String
) null);
1383 if (label
!= null && time
!= null && rgba
!= null) {
1384 Matcher matcher
= RGBA_PATTERN
.matcher(rgba
);
1385 if (matcher
.matches()) {
1387 int red
= Integer
.valueOf(matcher
.group(1));
1388 int green
= Integer
.valueOf(matcher
.group(2));
1389 int blue
= Integer
.valueOf(matcher
.group(3));
1390 int alpha
= Integer
.valueOf(matcher
.group(4));
1391 RGBA color
= new RGBA(red
, green
, blue
, alpha
);
1392 bookmarks
.add(new MarkerEvent(null, Long
.valueOf(time
), Long
.valueOf(duration
), IMarkerEvent
.BOOKMARKS
, color
, label
, true));
1393 } catch (NumberFormatException e
) {
1394 Activator
.getDefault().logError(e
.getMessage());
1399 } catch (CoreException e
) {
1400 Activator
.getDefault().logError(e
.getMessage());
1407 // ------------------------------------------------------------------------
1409 // ------------------------------------------------------------------------
1412 * Handler for the trace opened signal.
1415 * The incoming signal
1418 public void traceOpened(TmfTraceOpenedSignal signal
) {
1419 loadTrace(signal
.getTrace());
1423 * Handler for the trace selected signal
1426 * The incoming signal
1429 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1430 if (signal
.getTrace() == fTrace
) {
1433 loadTrace(signal
.getTrace());
1437 * Trace is closed: clear the data structures and the view
1440 * the signal received
1443 public void traceClosed(final TmfTraceClosedSignal signal
) {
1444 synchronized (fBuildThreadMap
) {
1445 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
1446 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
1447 if (buildThread
!= null) {
1448 buildThread
.cancel();
1452 fMarkerEventSourcesMap
.remove(signal
.getTrace());
1453 synchronized (fEntryListMap
) {
1454 fEntryListMap
.remove(signal
.getTrace());
1456 fFiltersMap
.remove(signal
.getTrace());
1457 fViewContext
.remove(signal
.getTrace());
1458 if (signal
.getTrace() == fTrace
) {
1461 fStartTime
= SWT
.DEFAULT
;
1462 fEndTime
= SWT
.DEFAULT
;
1463 if (fZoomThread
!= null) {
1464 fZoomThread
.cancel();
1472 * Handler for the selection range signal.
1475 * The signal that's received
1479 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1480 if (signal
.getSource() == this || fTrace
== null) {
1483 final long beginTime
= signal
.getBeginTime().toNanos();
1484 final long endTime
= signal
.getEndTime().toNanos();
1486 Display
.getDefault().asyncExec(new Runnable() {
1489 if (fTimeGraphWrapper
.isDisposed()) {
1492 if (beginTime
== endTime
) {
1493 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1495 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
, true);
1497 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getSelectionBegin());
1503 * Handler for the window range signal.
1506 * The signal that's received
1510 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1511 if (signal
.getSource() == this || fTrace
== null) {
1514 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1517 final long startTime
= signal
.getCurrentRange().getStartTime().toNanos();
1518 final long endTime
= signal
.getCurrentRange().getEndTime().toNanos();
1519 Display
.getDefault().asyncExec(new Runnable() {
1522 if (fTimeGraphWrapper
.isDisposed()) {
1525 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1526 startZoomThread(startTime
, endTime
);
1532 * @param signal the format of the timestamps was updated.
1535 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1536 fTimeGraphWrapper
.refresh();
1539 // ------------------------------------------------------------------------
1541 // ------------------------------------------------------------------------
1543 private void loadTrace(final ITmfTrace trace
) {
1544 if (fZoomThread
!= null) {
1545 fZoomThread
.cancel();
1548 if (fTrace
!= null) {
1549 /* save the filters of the previous trace */
1550 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1551 fViewContext
.put(fTrace
, new ViewContext(fCurrentSortColumn
, fSortDirection
, fTimeGraphWrapper
.getSelection()));
1554 restoreViewContext();
1555 fEditorFile
= TmfTraceManager
.getInstance().getTraceEditorFile(trace
);
1556 synchronized (fEntryListMap
) {
1557 fEntryList
= fEntryListMap
.get(fTrace
);
1558 if (fEntryList
== null) {
1561 fStartTime
= fTrace
.getStartTime().toNanos();
1562 fEndTime
= fTrace
.getEndTime().toNanos();
1569 * Forces a rebuild of the entries list, even if entries already exist for this trace
1571 protected void rebuild() {
1572 setStartTime(Long
.MAX_VALUE
);
1573 setEndTime(Long
.MIN_VALUE
);
1575 ITmfTrace viewTrace
= fTrace
;
1576 if (viewTrace
== null) {
1579 List
<IMarkerEventSource
> markerEventSources
= new ArrayList
<>();
1580 synchronized (fBuildThreadMap
) {
1581 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1582 if (trace
== null) {
1585 markerEventSources
.addAll(TmfTraceAdapterManager
.getAdapters(trace
, IMarkerEventSource
.class));
1586 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1587 fBuildThreadMap
.put(trace
, buildThread
);
1588 buildThread
.start();
1591 fMarkerEventSourcesMap
.put(viewTrace
, markerEventSources
);
1595 * Method called when synching to a given timestamp. Inheriting classes can
1596 * perform actions here to update the view at the given timestamp.
1599 * The currently selected time
1601 protected void synchingToTime(long time
) {
1606 * Return the list of traces whose data or analysis results will be used to
1607 * populate the view. By default, if the trace is an experiment, the traces
1608 * under it will be returned, otherwise, the trace itself is returned.
1610 * A build thread will be started for each trace returned by this method,
1611 * some of which may receive events in live streaming mode.
1614 * The trace associated with this view
1615 * @return List of traces with data to display
1617 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1618 return TmfTraceManager
.getTraceSet(trace
);
1622 * Build the entries list to show in this time graph
1624 * Called from the BuildThread
1627 * The trace being built
1628 * @param parentTrace
1629 * The parent of the trace set, or the trace itself
1631 * The progress monitor object
1633 protected abstract void buildEventList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1636 * Gets the list of event for an entry in a given timerange
1639 * The entry to get events for
1641 * Start of the time range
1643 * End of the time range
1647 * The progress monitor object
1648 * @return The list of events for the entry
1650 protected abstract @Nullable List
<@NonNull ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1651 long startTime
, long endTime
, long resolution
,
1652 @NonNull IProgressMonitor monitor
);
1655 * Gets the list of links (displayed as arrows) for a trace in a given
1656 * timerange. Default implementation returns an empty list.
1659 * Start of the time range
1661 * End of the time range
1665 * The progress monitor object
1666 * @return The list of link events
1668 protected @Nullable List
<@NonNull ILinkEvent
> getLinkList(long startTime
, long endTime
,
1669 long resolution
, @NonNull IProgressMonitor monitor
) {
1670 return new ArrayList
<>();
1674 * Gets the list of view-specific marker categories. Default implementation
1675 * returns an empty list.
1677 * @return The list of marker categories
1680 protected @NonNull List
<String
> getViewMarkerCategories() {
1681 return new ArrayList
<>();
1685 * Gets the list of view-specific markers for a trace in a given time range.
1686 * Default implementation returns an empty list.
1689 * Start of the time range
1691 * End of the time range
1695 * The progress monitor object
1696 * @return The list of marker events
1699 protected @NonNull List
<IMarkerEvent
> getViewMarkerList(long startTime
, long endTime
,
1700 long resolution
, @NonNull IProgressMonitor monitor
) {
1701 return new ArrayList
<>();
1705 * Gets the list of trace-specific markers for a trace in a given time range.
1708 * Start of the time range
1710 * End of the time range
1714 * The progress monitor object
1715 * @return The list of marker events
1718 protected @NonNull List
<IMarkerEvent
> getTraceMarkerList(long startTime
, long endTime
,
1719 long resolution
, @NonNull IProgressMonitor monitor
) {
1720 List
<IMarkerEvent
> markers
= new ArrayList
<>();
1721 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1722 for (String category
: markerEventSource
.getMarkerCategories()) {
1723 if (monitor
.isCanceled()) {
1726 markers
.addAll(markerEventSource
.getMarkerList(category
, startTime
, endTime
, resolution
, monitor
));
1733 * Get the list of current marker categories.
1735 * @return The list of marker categories
1738 private @NonNull List
<String
> getMarkerCategories() {
1739 Set
<String
> categories
= new LinkedHashSet
<>(getViewMarkerCategories());
1740 for (IMarkerEventSource markerEventSource
: getMarkerEventSources(fTrace
)) {
1741 categories
.addAll(markerEventSource
.getMarkerCategories());
1743 return new ArrayList
<>(categories
);
1747 * Gets the list of marker event sources for a given trace.
1751 * @return The list of marker event sources
1754 private @NonNull List
<IMarkerEventSource
> getMarkerEventSources(ITmfTrace trace
) {
1755 List
<IMarkerEventSource
> markerEventSources
= fMarkerEventSourcesMap
.get(trace
);
1756 if (markerEventSources
== null) {
1757 markerEventSources
= Collections
.emptyList();
1759 return markerEventSources
;
1763 * Refresh the display
1765 protected void refresh() {
1766 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1767 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1770 if (fTimeGraphWrapper
.isDisposed()) {
1773 fDirty
.incrementAndGet();
1775 boolean hasEntries
= false;
1776 synchronized (fEntryListMap
) {
1777 fEntryList
= fEntryListMap
.get(fTrace
);
1778 if (fEntryList
== null) {
1779 fEntryList
= new CopyOnWriteArrayList
<>();
1780 } else if (fEntryComparator
!= null) {
1781 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1782 Collections
.sort(list
, fEntryComparator
);
1783 for (ITimeGraphEntry entry
: list
) {
1784 sortChildren(entry
, fEntryComparator
);
1787 fEntryList
.addAll(list
);
1789 hasEntries
= !fEntryList
.isEmpty();
1791 boolean inputChanged
= fEntryList
!= fTimeGraphWrapper
.getInput();
1792 TimeGraphCombo combo
= getTimeGraphCombo();
1794 // Set redraw to false to only draw once
1795 if (combo
!= null) {
1796 combo
.getTreeViewer().getTree().setRedraw(false);
1798 getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
1800 fTimeGraphWrapper
.setInput(fEntryList
);
1801 /* restore the previously saved filters, if any */
1802 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1803 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1804 fTimeGraphWrapper
.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile
));
1805 fTimeGraphWrapper
.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1806 fTimeGraphWrapper
.getTimeGraphViewer().setMarkers(null);
1809 fTimeGraphWrapper
.refresh();
1812 if (fIsRevealSelection
) {
1813 fIsRevealSelection
= false;
1814 ITimeGraphEntry entry1
= fTimeGraphWrapper
.getSelection();
1815 fTimeGraphWrapper
.setSelection(entry1
);
1818 if (combo
!= null) {
1819 combo
.getTreeViewer().getTree().setRedraw(true);
1821 getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
1823 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1824 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1825 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1827 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1828 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().toNanos();
1829 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().toNanos();
1830 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().toNanos();
1831 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().toNanos();
1832 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1833 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1834 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
, false);
1835 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1837 if (inputChanged
&& selectionBeginTime
!= SWT
.DEFAULT
) {
1838 synchingToTime(selectionBeginTime
);
1841 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1842 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1851 startZoomThread(startTime
, endTime
);
1853 fDirty
.decrementAndGet();
1861 protected void redraw() {
1862 synchronized (fSyncObj
) {
1863 if (fRedrawState
== State
.IDLE
) {
1864 fRedrawState
= State
.BUSY
;
1866 fRedrawState
= State
.PENDING
;
1870 Display
.getDefault().asyncExec(new Runnable() {
1873 if (fTimeGraphWrapper
.isDisposed()) {
1876 fTimeGraphWrapper
.redraw();
1877 fTimeGraphWrapper
.update();
1878 synchronized (fSyncObj
) {
1879 if (fRedrawState
== State
.PENDING
) {
1880 fRedrawState
= State
.IDLE
;
1883 fRedrawState
= State
.IDLE
;
1890 private void sortChildren(ITimeGraphEntry entry
, Comparator
<ITimeGraphEntry
> comparator
) {
1891 if (entry
instanceof TimeGraphEntry
) {
1892 ((TimeGraphEntry
) entry
).sortChildren(comparator
);
1894 for (ITimeGraphEntry child
: entry
.getChildren()) {
1895 sortChildren(child
, comparator
);
1900 * Start or restart the zoom thread.
1903 * the zoom start time
1908 protected final void startZoomThread(long startTime
, long endTime
) {
1909 long clampedStartTime
= Math
.min(Math
.max(startTime
, fStartTime
), fEndTime
);
1910 long clampedEndTime
= Math
.max(Math
.min(endTime
, fEndTime
), fStartTime
);
1911 fDirty
.incrementAndGet();
1912 boolean restart
= false;
1913 if (fZoomThread
!= null) {
1914 fZoomThread
.cancel();
1915 if (fZoomThread
.fZoomStartTime
== clampedStartTime
&& fZoomThread
.fZoomEndTime
== clampedEndTime
) {
1919 long resolution
= Math
.max(1, (clampedEndTime
- clampedStartTime
) / fDisplayWidth
);
1920 fZoomThread
= createZoomThread(clampedStartTime
, clampedEndTime
, resolution
, restart
);
1921 if (fZoomThread
!= null) {
1922 fZoomThread
.start();
1924 fDirty
.decrementAndGet();
1929 * Create a zoom thread.
1932 * the zoom start time
1938 * true if restarting zoom for the same time range
1939 * @return a zoom thread
1942 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1943 final List
<TimeGraphEntry
> entryList
= fEntryList
;
1944 if (entryList
== null) {
1947 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
1950 private void makeActions() {
1951 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1952 fPreviousResourceAction
.setText(getPrevText());
1953 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1954 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1955 fNextResourceAction
.setText(getNextText());
1956 fNextResourceAction
.setToolTipText(getNextTooltip());
1959 private void contributeToActionBars() {
1960 IActionBars bars
= getViewSite().getActionBars();
1961 fillLocalToolBar(bars
.getToolBarManager());
1962 fillLocalMenu(bars
.getMenuManager());
1966 * Add actions to local tool bar manager
1968 * @param manager the tool bar manager
1970 protected void fillLocalToolBar(IToolBarManager manager
) {
1971 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1972 manager
.add(fTimeGraphWrapper
.getShowFilterDialogAction());
1974 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1975 manager
.add(new Separator());
1976 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1977 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1978 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1979 manager
.add(new Separator());
1980 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getToggleBookmarkAction());
1981 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousMarkerAction());
1982 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextMarkerAction());
1983 manager
.add(new Separator());
1984 manager
.add(fPreviousResourceAction
);
1985 manager
.add(fNextResourceAction
);
1986 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1987 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1988 manager
.add(new Separator());
1992 * Add actions to local menu manager
1994 * @param manager the tool bar manager
1997 protected void fillLocalMenu(IMenuManager manager
) {
1998 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getMarkersMenu());
2005 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
2006 if (fTimeGraphWrapper
== null) {
2009 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
2016 public int getAvailableWidth(int requestedOffset
) {
2017 if (fTimeGraphWrapper
== null) {
2020 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
2027 public void performAlign(int offset
, int width
) {
2028 if (fTimeGraphWrapper
!= null) {
2029 fTimeGraphWrapper
.performAlign(offset
, width
);
2034 * Returns whether or not the time graph view is dirty. The time graph view
2035 * is considered dirty if it has yet to completely update its model.
2037 * This method is meant to be used by tests in order to know when it is safe
2040 * Note: If a trace is smaller than the initial window range (see
2041 * {@link ITmfTrace#getInitialRangeOffset}) this method will return true
2044 * @return true if the time graph view has yet to completely update its
2045 * model, false otherwise
2048 public boolean isDirty() {
2049 if (fTrace
== null) {
2053 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
2054 long startTime
= ctx
.getWindowRange().getStartTime().toNanos();
2055 long endTime
= ctx
.getWindowRange().getEndTime().toNanos();
2057 // If the time graph control hasn't updated all the way to the end of
2058 // the window range then it's dirty. A refresh should happen later.
2059 if (fTimeGraphWrapper
.getTimeGraphViewer().getTime0() != startTime
|| fTimeGraphWrapper
.getTimeGraphViewer().getTime1() != endTime
) {
2063 if (fZoomThread
== null) {
2064 // The zoom thread is null but we might be just about to create it (refresh called).
2065 return fDirty
.get() != 0;
2067 // Dirty if the zoom thread is not done or if it hasn't zoomed all the
2068 // way to the end of the window range. In the latter case, there should be
2069 // a subsequent zoom thread that will be triggered.
2070 return fDirty
.get() != 0 || fZoomThread
.getZoomStartTime() != startTime
|| fZoomThread
.getZoomEndTime() != endTime
;
2073 private void createColumnSelectionListener(TreeViewer treeViewer
) {
2074 for (int i
= 0; i
< fColumnComparators
.length
; i
++) {
2075 final int index
= i
;
2076 final Comparator
<ITimeGraphEntry
> comp
= fColumnComparators
[index
];
2077 final Tree tree
= treeViewer
.getTree();
2078 final TreeColumn column
= tree
.getColumn(i
);
2081 column
.addSelectionListener(new SelectionAdapter() {
2083 public void widgetSelected(SelectionEvent e
) {
2084 TreeColumn prevSortcolumn
= tree
.getSortColumn();
2085 int direction
= tree
.getSortDirection();
2086 if (prevSortcolumn
== column
) {
2087 direction
= (direction
== SWT
.DOWN
) ? SWT
.UP
: SWT
.DOWN
;
2089 direction
= SWT
.DOWN
;
2091 tree
.setSortColumn(column
);
2092 tree
.setSortDirection(direction
);
2093 fSortDirection
= direction
;
2094 fCurrentSortColumn
= index
;
2095 Comparator
<ITimeGraphEntry
> comparator
= comp
;
2097 if (comparator
instanceof ITimeGraphEntryComparator
) {
2098 ((ITimeGraphEntryComparator
) comparator
).setDirection(direction
);
2100 if (direction
!= SWT
.DOWN
) {
2101 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2103 setEntryComparator(comparator
);
2104 fIsRevealSelection
= true;
2105 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
2106 ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getControl().setFocus();
2115 private void createDoubleClickListener(TreeViewer treeViewer
) {
2116 treeViewer
.addDoubleClickListener(event
-> {
2117 if (event
.getSelection() instanceof TreeSelection
) {
2118 TreeSelection selection
= (TreeSelection
) event
.getSelection();
2119 if (selection
.getFirstElement() instanceof ITimeGraphEntry
) {
2120 ITimeGraphEntry entry
= (ITimeGraphEntry
) selection
.getFirstElement();
2121 if (entry
.hasChildren()) {
2122 fTimeGraphWrapper
.setExpandedState(entry
, !fTimeGraphWrapper
.getExpandedState(entry
));
2130 private void restoreViewContext() {
2131 TimeGraphCombo combo
= getTimeGraphCombo();
2132 ViewContext viewContext
= fViewContext
.get(fTrace
);
2133 if (combo
!= null) {
2134 if (fColumnComparators
!= null) {
2135 // restore sort settings
2136 fSortDirection
= SWT
.DOWN
;
2137 fCurrentSortColumn
= fInitialSortColumn
;
2138 if (viewContext
!= null) {
2139 fSortDirection
= viewContext
.getSortDirection();
2140 fCurrentSortColumn
= viewContext
.getSortColumn();
2142 if ((fCurrentSortColumn
< fColumnComparators
.length
) && (fColumnComparators
[fCurrentSortColumn
] != null)) {
2143 Comparator
<ITimeGraphEntry
> comparator
= fColumnComparators
[fCurrentSortColumn
];
2144 if (comparator
instanceof ITimeGraphEntryComparator
) {
2145 ((ITimeGraphEntryComparator
) comparator
).setDirection(fSortDirection
);
2147 if (fSortDirection
!= SWT
.DOWN
) {
2148 comparator
= checkNotNull(Collections
.reverseOrder(comparator
));
2150 setEntryComparator(comparator
);
2156 private void applyViewContext() {
2157 TimeGraphCombo combo
= getTimeGraphCombo();
2158 ViewContext viewContext
= fViewContext
.get(fTrace
);
2159 if (combo
!= null) {
2160 TreeViewer treeViewer
= combo
.getTreeViewer();
2161 final Tree tree
= treeViewer
.getTree();
2162 final TreeColumn column
= tree
.getColumn(fCurrentSortColumn
);
2163 tree
.setSortDirection(fSortDirection
);
2164 tree
.setSortColumn(column
);
2165 combo
.getTreeViewer().getControl().setFocus();
2167 // restore and reveal selection
2168 if ((viewContext
!= null) && (viewContext
.getSelection() != null)) {
2169 fTimeGraphWrapper
.setSelection(viewContext
.getSelection());
2171 fViewContext
.remove(fTrace
);
2174 private static class ViewContext
{
2175 private int fSortColumnIndex
;
2176 private int fSortDirection
;
2177 private @Nullable ITimeGraphEntry fSelection
;
2179 ViewContext(int sortColunm
, int sortDirection
, ITimeGraphEntry selection
) {
2180 fSortColumnIndex
= sortColunm
;
2181 fSortDirection
= sortDirection
;
2182 fSelection
= selection
;
2185 * @return the sortColumn
2187 public int getSortColumn() {
2188 return fSortColumnIndex
;
2191 * @return the sortDirection
2193 public int getSortDirection() {
2194 return fSortDirection
;
2197 * @return the selection
2199 public ITimeGraphEntry
getSelection() {
2204 private void createContextMenu() {
2205 TimeGraphCombo combo
= getTimeGraphCombo();
2206 fEntryMenuManager
.setRemoveAllWhenShown(true);
2207 if (combo
!= null) {
2208 TreeViewer treeViewer
= combo
.getTreeViewer();
2209 Tree tree
= treeViewer
.getTree();
2210 Menu menu
= fEntryMenuManager
.createContextMenu(tree
);
2213 TimeGraphControl timeGraphControl
= getTimeGraphViewer().getTimeGraphControl();
2214 final Menu entryMenu
= fEntryMenuManager
.createContextMenu(timeGraphControl
);
2215 timeGraphControl
.addTimeGraphEntryMenuListener(new MenuDetectListener() {
2217 public void menuDetected(MenuDetectEvent event
) {
2218 Point p
= timeGraphControl
.toControl(event
.x
, event
.y
);
2220 * The TimeGraphControl will call the TimeGraphEntryMenuListener
2221 * before the TimeEventMenuListener. If the event is
2222 * triggered on the namespace then show the menu else
2225 if (p
.x
< getTimeGraphViewer().getNameSpace()) {
2226 timeGraphControl
.setMenu(entryMenu
);
2228 timeGraphControl
.setMenu(null);
2234 fEntryMenuManager
.addMenuListener(new IMenuListener() {
2236 public void menuAboutToShow(IMenuManager manager
) {
2237 fillTimeGraphEntryContextMenu(fEntryMenuManager
);
2238 fEntryMenuManager
.add(new GroupMarker(IWorkbenchActionConstants
.MB_ADDITIONS
));
2241 getSite().registerContextMenu(fEntryMenuManager
, fTimeGraphWrapper
.getSelectionProvider());
2247 * @param menuManager
2248 * a menuManager to fill
2251 protected void fillTimeGraphEntryContextMenu (@NonNull IMenuManager menuManager
) {
2255 * Inner classes used for searching
2258 public ITimeGraphEntry
getSelection() {
2259 return fTimeGraphWrapper
.getSelection();
2262 public void selectAndReveal(@NonNull ITimeGraphEntry entry
) {
2263 fTimeGraphWrapper
.selectAndReveal(entry
);
2266 public ITimeGraphEntry
[] getEntries() {
2267 TimeGraphViewer viewer
= getTimeGraphViewer();
2268 return viewer
.getTimeGraphContentProvider().getElements(viewer
.getInput());
2271 public Shell
getShell() {
2272 return getSite().getShell();
2276 class TimeGraphPartListener
implements IPartListener
{
2278 public void partActivated(IWorkbenchPart part
) {
2279 if (part
== AbstractTimeGraphView
.this) {
2280 synchronized (FIND_ACTION
) {
2281 if (fFindActionHandler
== null) {
2282 fFindActionHandler
= new ActionHandler(FIND_ACTION
);
2284 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2285 fFindHandlerActivation
= ((IHandlerService
) service
).activateHandler(ActionFactory
.FIND
.getCommandId(), fFindActionHandler
);
2288 // Notify action for all parts
2289 FIND_ACTION
.partActivated(part
);
2292 public void partDeactivated(IWorkbenchPart part
) {
2293 if ((part
== AbstractTimeGraphView
.this) && (fFindHandlerActivation
!= null)) {
2294 final Object service
= PlatformUI
.getWorkbench().getService(IHandlerService
.class);
2295 ((IHandlerService
) service
).deactivateHandler(fFindHandlerActivation
);
2299 public void partBroughtToTop(IWorkbenchPart part
) {
2302 public void partClosed(IWorkbenchPart part
) {
2305 public void partOpened(IWorkbenchPart part
) {