1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 * Geneviève Bastien - Move code to provide base classes for time graph view
13 * Marc-Andre Laperle - Add time zone preference
14 * Geneviève Bastien - Add event links between entries
15 *******************************************************************************/
17 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
;
19 import java
.util
.ArrayList
;
20 import java
.util
.Collections
;
21 import java
.util
.Comparator
;
22 import java
.util
.HashMap
;
23 import java
.util
.List
;
25 import java
.util
.concurrent
.CopyOnWriteArrayList
;
27 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
28 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
29 import org
.eclipse
.jdt
.annotation
.NonNull
;
30 import org
.eclipse
.jdt
.annotation
.Nullable
;
31 import org
.eclipse
.jface
.action
.Action
;
32 import org
.eclipse
.jface
.action
.IAction
;
33 import org
.eclipse
.jface
.action
.IStatusLineManager
;
34 import org
.eclipse
.jface
.action
.IToolBarManager
;
35 import org
.eclipse
.jface
.action
.Separator
;
36 import org
.eclipse
.jface
.viewers
.AbstractTreeViewer
;
37 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
38 import org
.eclipse
.jface
.viewers
.ILabelProviderListener
;
39 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
40 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
41 import org
.eclipse
.jface
.viewers
.TreeViewer
;
42 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
43 import org
.eclipse
.swt
.SWT
;
44 import org
.eclipse
.swt
.graphics
.Image
;
45 import org
.eclipse
.swt
.widgets
.Composite
;
46 import org
.eclipse
.swt
.widgets
.Display
;
47 import org
.eclipse
.swt
.widgets
.TreeColumn
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
55 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
56 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
57 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
58 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
60 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
61 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
62 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
63 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
64 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
65 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
66 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
67 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
68 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
69 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
70 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
75 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
76 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
77 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
78 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
79 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
80 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
81 import org
.eclipse
.ui
.IActionBars
;
84 * An abstract view all time graph views can inherit
86 * This view contains either a time graph viewer, or a time graph combo which is
87 * divided between a tree viewer on the left and a time graph viewer on the right.
89 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
{
91 /** Constant indicating that all levels of the time graph should be expanded */
92 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
101 // ------------------------------------------------------------------------
103 // ------------------------------------------------------------------------
105 /** The timegraph wrapper */
106 private ITimeGraphWrapper fTimeGraphWrapper
;
108 /** The selected trace */
109 private ITmfTrace fTrace
;
111 /** The timegraph entry list */
112 private List
<TimeGraphEntry
> fEntryList
;
114 /** The trace to entry list hash map */
115 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
117 /** The trace to filters hash map */
118 private final Map
<ITmfTrace
, ViewerFilter
[]> fFiltersMap
= new HashMap
<>();
120 /** The trace to build thread hash map */
121 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
123 /** The start time */
124 private long fStartTime
= SWT
.DEFAULT
;
127 private long fEndTime
= SWT
.DEFAULT
;
129 /** The display width */
130 private final int fDisplayWidth
;
132 /** The zoom thread */
133 private ZoomThread fZoomThread
;
135 /** The next resource action */
136 private Action fNextResourceAction
;
138 /** The previous resource action */
139 private Action fPreviousResourceAction
;
141 /** A comparator class */
142 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
144 /** The redraw state used to prevent unnecessary queuing of display runnables */
145 private State fRedrawState
= State
.IDLE
;
147 /** The redraw synchronization object */
148 private final Object fSyncObj
= new Object();
150 /** The presentation provider for this view */
151 private final TimeGraphPresentationProvider fPresentation
;
153 /** The tree column label array, or null if combo is not used */
154 private String
[] fColumns
;
156 /** The tree label provider, or null if combo is not used */
157 private TreeLabelProvider fLabelProvider
= null;
159 /** The time graph content provider */
160 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
162 /** The relative weight of the sash, ignored if combo is not used */
163 private int[] fWeight
= { 1, 3 };
165 /** The filter column label array, or null if filter is not used */
166 private String
[] fFilterColumns
;
168 /** The pack done flag */
169 private boolean fPackDone
= false;
171 /** The filter label provider, or null if filter is not used */
172 private TreeLabelProvider fFilterLabelProvider
;
174 private int fAutoExpandLevel
= ALL_LEVELS
;
176 // ------------------------------------------------------------------------
178 // ------------------------------------------------------------------------
180 private interface ITimeGraphWrapper
{
182 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation
);
184 TimeGraphViewer
getTimeGraphViewer();
186 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener
);
188 ISelectionProvider
getSelectionProvider();
192 boolean isDisposed();
196 void setInput(Object input
);
200 void setFilters(ViewerFilter
[] filters
);
202 ViewerFilter
[] getFilters();
208 void setAutoExpandLevel(int level
);
210 void performAlign(int offset
, int width
);
212 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
214 int getAvailableWidth(int requestedOffset
);
217 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
218 private TimeGraphViewer viewer
;
220 private TimeGraphViewerWrapper(Composite parent
, int style
) {
221 viewer
= new TimeGraphViewer(parent
, style
);
225 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
226 viewer
.setTimeGraphProvider(timeGraphProvider
);
230 public TimeGraphViewer
getTimeGraphViewer() {
235 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
236 viewer
.addSelectionListener(listener
);
240 public ISelectionProvider
getSelectionProvider() {
241 return viewer
.getSelectionProvider();
245 public void setFocus() {
250 public boolean isDisposed() {
251 return viewer
.getControl().isDisposed();
255 public void setInput(Object input
) {
256 viewer
.setInput(input
);
260 public Object
getInput() {
261 return viewer
.getInput();
265 public void setFilters(ViewerFilter
[] filters
) {
266 viewer
.setFilters(filters
);
270 public ViewerFilter
[] getFilters() {
271 return viewer
.getFilters();
275 public void refresh() {
280 public void redraw() {
281 viewer
.getControl().redraw();
285 public void update() {
286 viewer
.getControl().update();
290 public void setAutoExpandLevel(int level
) {
291 viewer
.setAutoExpandLevel(level
);
295 public void performAlign(int offset
, int width
) {
296 viewer
.performAlign(offset
, width
);
300 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
301 return viewer
.getTimeViewAlignmentInfo();
305 public int getAvailableWidth(int requestedOffset
) {
306 return viewer
.getAvailableWidth(requestedOffset
);
310 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
311 private TimeGraphCombo combo
;
313 private TimeGraphComboWrapper(Composite parent
, int style
) {
314 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
318 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
319 combo
.setTimeGraphProvider(timeGraphProvider
);
323 public TimeGraphViewer
getTimeGraphViewer() {
324 return combo
.getTimeGraphViewer();
328 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
329 combo
.addSelectionListener(listener
);
333 public ISelectionProvider
getSelectionProvider() {
334 return combo
.getTreeViewer();
338 public void setFocus() {
343 public boolean isDisposed() {
344 return combo
.isDisposed();
348 public void setInput(Object input
) {
349 combo
.setInput(input
);
353 public Object
getInput() {
354 return combo
.getInput();
358 public void setFilters(ViewerFilter
[] filters
) {
359 combo
.setFilters(filters
);
363 public ViewerFilter
[] getFilters() {
364 return combo
.getFilters();
368 public void refresh() {
373 public void redraw() {
378 public void update() {
383 public void setAutoExpandLevel(int level
) {
384 combo
.setAutoExpandLevel(level
);
387 TimeGraphCombo
getTimeGraphCombo() {
391 TreeViewer
getTreeViewer() {
392 return combo
.getTreeViewer();
395 IAction
getShowFilterAction() {
396 return combo
.getShowFilterAction();
400 public void performAlign(int offset
, int width
) {
401 combo
.performAlign(offset
, width
);
405 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
406 return combo
.getTimeViewAlignmentInfo();
410 public int getAvailableWidth(int requestedOffset
) {
411 return combo
.getAvailableWidth(requestedOffset
);
416 * Base class to provide the labels for the tree viewer. Views extending
417 * this class typically need to override the getColumnText method if they
418 * have more than one column to display
420 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
423 public void addListener(ILabelProviderListener listener
) {
427 public void dispose() {
431 public boolean isLabelProperty(Object element
, String property
) {
436 public void removeListener(ILabelProviderListener listener
) {
440 public Image
getColumnImage(Object element
, int columnIndex
) {
445 public String
getColumnText(Object element
, int columnIndex
) {
446 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
447 if (columnIndex
== 0) {
448 return entry
.getName();
454 public Image
getImage(Object element
) {
459 public String
getText(Object element
) {
460 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
461 return entry
.getName();
466 private class BuildThread
extends Thread
{
467 private final @NonNull ITmfTrace fBuildTrace
;
468 private final @NonNull ITmfTrace fParentTrace
;
469 private final @NonNull IProgressMonitor fMonitor
;
471 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
472 super(name
+ " build"); //$NON-NLS-1$
474 fParentTrace
= parentTrace
;
475 fMonitor
= new NullProgressMonitor();
480 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
481 synchronized (fBuildThreadMap
) {
482 fBuildThreadMap
.remove(fBuildTrace
);
486 public void cancel() {
487 fMonitor
.setCanceled(true);
495 protected abstract class ZoomThread
extends Thread
{
496 private final long fZoomStartTime
;
497 private final long fZoomEndTime
;
498 private final long fResolution
;
499 private final @NonNull IProgressMonitor fMonitor
;
511 public ZoomThread(long startTime
, long endTime
, long resolution
) {
512 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
513 fZoomStartTime
= startTime
;
514 fZoomEndTime
= endTime
;
515 fResolution
= resolution
;
516 fMonitor
= new NullProgressMonitor();
520 * @return the zoom start time
522 public long getZoomStartTime() {
523 return fZoomStartTime
;
527 * @return the zoom end time
529 public long getZoomEndTime() {
534 * @return the resolution
536 public long getResolution() {
541 * @return the monitor
543 public @NonNull IProgressMonitor
getMonitor() {
548 * Cancel the zoom thread
550 public void cancel() {
551 fMonitor
.setCanceled(true);
555 private class ZoomThreadByEntry
extends ZoomThread
{
556 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
558 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
559 super(startTime
, endTime
, resolution
);
560 fZoomEntryList
= entryList
;
565 for (TimeGraphEntry entry
: fZoomEntryList
) {
566 if (getMonitor().isCanceled()) {
572 zoom(entry
, getMonitor());
574 /* Refresh the arrows when zooming */
575 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
576 if (events
!= null) {
577 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
582 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
583 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
584 entry
.setZoomedEventList(null);
586 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
587 if (zoomedEventList
!= null) {
588 entry
.setZoomedEventList(zoomedEventList
);
592 for (ITimeGraphEntry child
: entry
.getChildren()) {
593 if (monitor
.isCanceled()) {
596 if (child
instanceof TimeGraphEntry
) {
597 zoom((TimeGraphEntry
) child
, monitor
);
604 // ------------------------------------------------------------------------
606 // ------------------------------------------------------------------------
609 * Constructs a time graph view that contains either a time graph viewer or
610 * a time graph combo.
612 * By default, the view uses a time graph viewer. To use a time graph combo,
613 * the subclass constructor must call {@link #setTreeColumns(String[])} and
614 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
619 * The presentation provider
621 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
623 fPresentation
= pres
;
624 fDisplayWidth
= Display
.getDefault().getBounds().width
;
627 // ------------------------------------------------------------------------
628 // Getters and setters
629 // ------------------------------------------------------------------------
632 * Getter for the time graph combo
634 * @return The time graph combo, or null if combo is not used
636 protected TimeGraphCombo
getTimeGraphCombo() {
637 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
638 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
644 * Getter for the time graph viewer
646 * @return The time graph viewer
648 protected TimeGraphViewer
getTimeGraphViewer() {
649 return fTimeGraphWrapper
.getTimeGraphViewer();
653 * Getter for the presentation provider
655 * @return The time graph presentation provider
657 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
658 return fPresentation
;
662 * Sets the tree column labels.
663 * This should be called from the constructor.
666 * The array of tree column labels
668 protected void setTreeColumns(final String
[] columns
) {
673 * Sets the tree label provider.
674 * This should be called from the constructor.
677 * The tree label provider
679 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
680 fLabelProvider
= tlp
;
684 * Sets the time graph content provider. This should be called from the
688 * The time graph content provider
691 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
692 fTimeGraphContentProvider
= tgcp
;
696 * Sets the relative weight of each part of the time graph combo.
697 * This should be called from the constructor.
700 * The array (length 2) of relative weights of each part of the combo
702 protected void setWeight(final int[] weights
) {
707 * Sets the filter column labels.
708 * This should be called from the constructor.
710 * @param filterColumns
711 * The array of filter column labels
713 protected void setFilterColumns(final String
[] filterColumns
) {
714 fFilterColumns
= filterColumns
;
718 * Sets the filter label provider.
719 * This should be called from the constructor.
721 * @param labelProvider
722 * The filter label provider
724 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
725 fFilterLabelProvider
= labelProvider
;
729 * Gets the display width
731 * @return the display width
733 protected int getDisplayWidth() {
734 return fDisplayWidth
;
738 * Gets the comparator for the entries
740 * @return The entry comparator
742 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
743 return fEntryComparator
;
747 * Sets the comparator class for the entries
750 * A comparator object
752 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
753 fEntryComparator
= comparator
;
757 * Gets the trace displayed in the view
761 protected ITmfTrace
getTrace() {
766 * Gets the start time
768 * @return The start time
770 protected long getStartTime() {
775 * Sets the start time
780 protected void setStartTime(long time
) {
787 * @return The end time
789 protected long getEndTime() {
799 protected void setEndTime(long time
) {
804 * Sets the auto-expand level to be used for the input of the view. The
805 * value 0 means that there is no auto-expand; 1 means that top-level
806 * elements are expanded, but not their children; 2 means that top-level
807 * elements are expanded, and their children, but not grand-children; and so
810 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
814 * non-negative level, or <code>ALL_LEVELS</code> to expand all
817 protected void setAutoExpandLevel(int level
) {
818 fAutoExpandLevel
= level
;
819 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
820 if (tgWrapper
!= null) {
821 tgWrapper
.setAutoExpandLevel(level
);
826 * Gets the entry list for a trace
831 * @return the entry list map
833 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
834 synchronized (fEntryListMap
) {
835 return fEntryListMap
.get(trace
);
840 * Adds a trace entry list to the entry list map
845 * the list of time graph entries
847 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
848 synchronized (fEntryListMap
) {
849 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
854 * Adds a list of entries to a trace's entry list
859 * the list of time graph entries to add
861 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
862 synchronized (fEntryListMap
) {
863 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
864 if (entryList
== null) {
865 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
867 entryList
.addAll(list
);
873 * Removes a list of entries from a trace's entry list
878 * the list of time graph entries to remove
880 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
881 synchronized (fEntryListMap
) {
882 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
883 if (entryList
!= null) {
884 entryList
.removeAll(list
);
890 * Text for the "next" button
892 * @return The "next" button text
894 protected String
getNextText() {
895 return Messages
.AbstractTimeGraphtView_NextText
;
899 * Tooltip for the "next" button
901 * @return Tooltip for the "next" button
903 protected String
getNextTooltip() {
904 return Messages
.AbstractTimeGraphView_NextTooltip
;
908 * Text for the "Previous" button
910 * @return The "Previous" button text
912 protected String
getPrevText() {
913 return Messages
.AbstractTimeGraphView_PreviousText
;
917 * Tooltip for the "previous" button
919 * @return Tooltip for the "previous" button
921 protected String
getPrevTooltip() {
922 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
925 // ------------------------------------------------------------------------
927 // ------------------------------------------------------------------------
930 public void createPartControl(Composite parent
) {
931 super.createPartControl(parent
);
932 if (fColumns
== null || fLabelProvider
== null) {
933 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
934 TimeGraphViewer viewer
= fTimeGraphWrapper
.getTimeGraphViewer();
935 viewer
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
937 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
938 fTimeGraphWrapper
= wrapper
;
939 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
940 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
941 combo
.setTreeLabelProvider(fLabelProvider
);
942 combo
.setTreeColumns(fColumns
);
943 combo
.setFilterContentProvider(fTimeGraphContentProvider
);
944 combo
.setFilterLabelProvider(fFilterLabelProvider
);
945 combo
.setFilterColumns(fFilterColumns
);
946 combo
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
949 fTimeGraphWrapper
.setTimeGraphProvider(fPresentation
);
950 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
952 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
954 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
955 final long startTime
= event
.getStartTime();
956 final long endTime
= event
.getEndTime();
957 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
958 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
959 startZoomThread(startTime
, endTime
);
963 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
965 public void timeSelected(TimeGraphTimeEvent event
) {
966 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
967 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
968 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
972 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
974 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
975 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
977 // View Action Handling
979 contributeToActionBars();
981 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
983 traceSelected(new TmfTraceSelectedSignal(this, trace
));
986 // make selection available to other views
987 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
991 public void setFocus() {
992 fTimeGraphWrapper
.setFocus();
995 // ------------------------------------------------------------------------
997 // ------------------------------------------------------------------------
1000 * Handler for the trace opened signal.
1003 * The incoming signal
1006 public void traceOpened(TmfTraceOpenedSignal signal
) {
1007 loadTrace(signal
.getTrace());
1011 * Handler for the trace selected signal
1014 * The incoming signal
1017 public void traceSelected(final TmfTraceSelectedSignal signal
) {
1018 if (signal
.getTrace() == fTrace
) {
1021 loadTrace(signal
.getTrace());
1025 * Trace is closed: clear the data structures and the view
1028 * the signal received
1031 public void traceClosed(final TmfTraceClosedSignal signal
) {
1032 synchronized (fBuildThreadMap
) {
1033 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
1034 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
1035 if (buildThread
!= null) {
1036 buildThread
.cancel();
1040 synchronized (fEntryListMap
) {
1041 fEntryListMap
.remove(signal
.getTrace());
1043 fFiltersMap
.remove(signal
.getTrace());
1044 if (signal
.getTrace() == fTrace
) {
1046 fStartTime
= SWT
.DEFAULT
;
1047 fEndTime
= SWT
.DEFAULT
;
1048 if (fZoomThread
!= null) {
1049 fZoomThread
.cancel();
1057 * Handler for the selection range signal.
1060 * The signal that's received
1064 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1065 if (signal
.getSource() == this || fTrace
== null) {
1068 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1069 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1071 Display
.getDefault().asyncExec(new Runnable() {
1074 if (fTimeGraphWrapper
.isDisposed()) {
1077 if (beginTime
== endTime
) {
1078 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1080 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
1082 synchingToTime(fTimeGraphWrapper
.getTimeGraphViewer().getTime0());
1088 * Handler for the window range signal.
1091 * The signal that's received
1095 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1096 if (signal
.getSource() == this || fTrace
== null) {
1099 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1102 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1103 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1104 Display
.getDefault().asyncExec(new Runnable() {
1107 if (fTimeGraphWrapper
.isDisposed()) {
1110 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1111 startZoomThread(startTime
, endTime
);
1117 * @param signal the format of the timestamps was updated.
1120 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1121 fTimeGraphWrapper
.refresh();
1124 // ------------------------------------------------------------------------
1126 // ------------------------------------------------------------------------
1128 private void loadTrace(final ITmfTrace trace
) {
1129 if (fZoomThread
!= null) {
1130 fZoomThread
.cancel();
1133 if (fTrace
!= null) {
1134 /* save the filters of the previous trace */
1135 fFiltersMap
.put(fTrace
, fTimeGraphWrapper
.getFilters());
1138 synchronized (fEntryListMap
) {
1139 fEntryList
= fEntryListMap
.get(fTrace
);
1140 if (fEntryList
== null) {
1143 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1144 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1151 * Forces a rebuild of the entries list, even if entries already exist for this trace
1153 protected void rebuild() {
1154 setStartTime(Long
.MAX_VALUE
);
1155 setEndTime(Long
.MIN_VALUE
);
1157 ITmfTrace viewTrace
= fTrace
;
1158 if (viewTrace
== null) {
1161 synchronized (fBuildThreadMap
) {
1162 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1163 if (trace
== null) {
1166 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1167 fBuildThreadMap
.put(trace
, buildThread
);
1168 buildThread
.start();
1174 * Method called when synching to a given timestamp. Inheriting classes can
1175 * perform actions here to update the view at the given timestamp.
1178 * The currently selected time
1180 protected void synchingToTime(long time
) {
1185 * Return the list of traces whose data or analysis results will be used to
1186 * populate the view. By default, if the trace is an experiment, the traces
1187 * under it will be returned, otherwise, the trace itself is returned.
1189 * A build thread will be started for each trace returned by this method,
1190 * some of which may receive events in live streaming mode.
1193 * The trace associated with this view
1194 * @return List of traces with data to display
1196 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1197 return TmfTraceManager
.getTraceSet(trace
);
1201 * Build the entries list to show in this time graph
1203 * Called from the BuildThread
1206 * The trace being built
1207 * @param parentTrace
1208 * The parent of the trace set, or the trace itself
1210 * The progress monitor object
1212 protected abstract void buildEventList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1215 * Gets the list of event for an entry in a given timerange
1218 * The entry to get events for
1220 * Start of the time range
1222 * End of the time range
1226 * The progress monitor object
1227 * @return The list of events for the entry
1229 protected abstract @Nullable List
<ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1230 long startTime
, long endTime
, long resolution
,
1231 @NonNull IProgressMonitor monitor
);
1234 * Gets the list of links (displayed as arrows) for a trace in a given
1235 * timerange. Default implementation returns an empty list.
1238 * Start of the time range
1240 * End of the time range
1244 * The progress monitor object
1245 * @return The list of link events
1247 protected @Nullable List
<ILinkEvent
> getLinkList(long startTime
, long endTime
,
1248 long resolution
, @NonNull IProgressMonitor monitor
) {
1249 return new ArrayList
<>();
1254 * Refresh the display
1256 protected void refresh() {
1257 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1258 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1261 if (fTimeGraphWrapper
.isDisposed()) {
1264 boolean hasEntries
= false;
1265 synchronized (fEntryListMap
) {
1266 fEntryList
= fEntryListMap
.get(fTrace
);
1267 if (fEntryList
== null) {
1268 fEntryList
= new CopyOnWriteArrayList
<>();
1269 } else if (fEntryComparator
!= null) {
1270 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1271 Collections
.sort(list
, fEntryComparator
);
1273 fEntryList
.addAll(list
);
1275 hasEntries
= fEntryList
.size() != 0;
1277 if (fEntryList
!= fTimeGraphWrapper
.getInput()) {
1278 fTimeGraphWrapper
.setInput(fEntryList
);
1279 /* restore the previously saved filters, if any */
1280 fTimeGraphWrapper
.setFilters(fFiltersMap
.get(fTrace
));
1281 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1283 fTimeGraphWrapper
.refresh();
1285 long startBound
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: fStartTime
);
1286 long endBound
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: fEndTime
);
1287 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(startBound
, endBound
);
1289 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1290 long selectionBeginTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1291 long selectionEndTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1292 long startTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1293 long endTime
= fTrace
== null ? SWT
.DEFAULT
: ctx
.getWindowRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1294 startTime
= (fStartTime
== Long
.MAX_VALUE ? SWT
.DEFAULT
: Math
.max(startTime
, fStartTime
));
1295 endTime
= (fEndTime
== Long
.MIN_VALUE ? SWT
.DEFAULT
: Math
.min(endTime
, fEndTime
));
1296 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1297 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1299 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1300 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1309 startZoomThread(startTime
, endTime
);
1318 protected void redraw() {
1319 synchronized (fSyncObj
) {
1320 if (fRedrawState
== State
.IDLE
) {
1321 fRedrawState
= State
.BUSY
;
1323 fRedrawState
= State
.PENDING
;
1327 Display
.getDefault().asyncExec(new Runnable() {
1330 if (fTimeGraphWrapper
.isDisposed()) {
1333 fTimeGraphWrapper
.redraw();
1334 fTimeGraphWrapper
.update();
1335 synchronized (fSyncObj
) {
1336 if (fRedrawState
== State
.PENDING
) {
1337 fRedrawState
= State
.IDLE
;
1340 fRedrawState
= State
.IDLE
;
1347 private void startZoomThread(long startTime
, long endTime
) {
1348 boolean restart
= false;
1349 if (fZoomThread
!= null) {
1350 fZoomThread
.cancel();
1351 if (fZoomThread
.fZoomStartTime
== startTime
&& fZoomThread
.fZoomEndTime
== endTime
) {
1355 long resolution
= Math
.max(1, (endTime
- startTime
) / fDisplayWidth
);
1356 fZoomThread
= createZoomThread(startTime
, endTime
, resolution
, restart
);
1357 if (fZoomThread
!= null) {
1358 fZoomThread
.start();
1363 * Create a zoom thread.
1366 * the zoom start time
1372 * true if restarting zoom for the same time range
1373 * @return a zoom thread
1376 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1377 final List
<TimeGraphEntry
> entryList
= fEntryList
;
1378 if (entryList
== null) {
1381 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
1384 private void makeActions() {
1385 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1386 fPreviousResourceAction
.setText(getPrevText());
1387 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1388 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1389 fNextResourceAction
.setText(getNextText());
1390 fNextResourceAction
.setToolTipText(getNextTooltip());
1393 private void contributeToActionBars() {
1394 IActionBars bars
= getViewSite().getActionBars();
1395 fillLocalToolBar(bars
.getToolBarManager());
1399 * Add actions to local tool bar manager
1401 * @param manager the tool bar manager
1403 protected void fillLocalToolBar(IToolBarManager manager
) {
1404 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
1405 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1406 manager
.add(((TimeGraphComboWrapper
) fTimeGraphWrapper
).getShowFilterAction());
1409 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1410 manager
.add(new Separator());
1411 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1412 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1413 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1414 manager
.add(fPreviousResourceAction
);
1415 manager
.add(fNextResourceAction
);
1416 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1417 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1418 manager
.add(new Separator());
1425 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
1426 if (fTimeGraphWrapper
== null) {
1429 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
1436 public int getAvailableWidth(int requestedOffset
) {
1437 if (fTimeGraphWrapper
== null) {
1440 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
1447 public void performAlign(int offset
, int width
) {
1448 if (fTimeGraphWrapper
!= null) {
1449 fTimeGraphWrapper
.performAlign(offset
, width
);