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
.swt
.SWT
;
43 import org
.eclipse
.swt
.graphics
.Image
;
44 import org
.eclipse
.swt
.widgets
.Composite
;
45 import org
.eclipse
.swt
.widgets
.Display
;
46 import org
.eclipse
.swt
.widgets
.TreeColumn
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
55 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
56 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
57 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
58 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
60 import org
.eclipse
.tracecompass
.tmf
.ui
.TmfUiRefreshHandler
;
61 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
62 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
63 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
64 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
65 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
66 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
67 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
68 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
69 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
70 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
75 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
76 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
77 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
78 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
79 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
80 import org
.eclipse
.ui
.IActionBars
;
83 * An abstract view all time graph views can inherit
85 * This view contains either a time graph viewer, or a time graph combo which is
86 * divided between a tree viewer on the left and a time graph viewer on the right.
88 public abstract class AbstractTimeGraphView
extends TmfView
implements ITmfTimeAligned
{
90 /** Constant indicating that all levels of the time graph should be expanded */
91 protected static final int ALL_LEVELS
= AbstractTreeViewer
.ALL_LEVELS
;
100 // ------------------------------------------------------------------------
102 // ------------------------------------------------------------------------
104 /** The timegraph wrapper */
105 private ITimeGraphWrapper fTimeGraphWrapper
;
107 /** The selected trace */
108 private ITmfTrace fTrace
;
110 /** The timegraph entry list */
111 private List
<TimeGraphEntry
> fEntryList
;
113 /** The trace to entry list hash map */
114 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
116 /** The trace to build thread hash map */
117 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
119 /** The start time */
120 private long fStartTime
;
123 private long fEndTime
;
125 /** The display width */
126 private final int fDisplayWidth
;
128 /** The zoom thread */
129 private ZoomThread fZoomThread
;
131 /** The next resource action */
132 private Action fNextResourceAction
;
134 /** The previous resource action */
135 private Action fPreviousResourceAction
;
137 /** A comparator class */
138 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
140 /** The redraw state used to prevent unnecessary queuing of display runnables */
141 private State fRedrawState
= State
.IDLE
;
143 /** The redraw synchronization object */
144 private final Object fSyncObj
= new Object();
146 /** The presentation provider for this view */
147 private final TimeGraphPresentationProvider fPresentation
;
149 /** The tree column label array, or null if combo is not used */
150 private String
[] fColumns
;
152 /** The tree label provider, or null if combo is not used */
153 private TreeLabelProvider fLabelProvider
= null;
155 /** The time graph content provider */
156 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider
= new TimeGraphContentProvider();
158 /** The relative weight of the sash, ignored if combo is not used */
159 private int[] fWeight
= { 1, 3 };
161 /** The filter column label array, or null if filter is not used */
162 private String
[] fFilterColumns
;
164 /** The pack done flag */
165 private boolean fPackDone
= false;
167 /** The filter label provider, or null if filter is not used */
168 private TreeLabelProvider fFilterLabelProvider
;
170 private int fAutoExpandLevel
= ALL_LEVELS
;
172 // ------------------------------------------------------------------------
174 // ------------------------------------------------------------------------
176 private interface ITimeGraphWrapper
{
178 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation
);
180 TimeGraphViewer
getTimeGraphViewer();
182 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener
);
184 ISelectionProvider
getSelectionProvider();
188 boolean isDisposed();
192 void setInput(Object input
);
200 void setAutoExpandLevel(int level
);
202 void performAlign(int offset
, int width
);
204 TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo();
206 int getAvailableWidth(int requestedOffset
);
209 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
210 private TimeGraphViewer viewer
;
212 private TimeGraphViewerWrapper(Composite parent
, int style
) {
213 viewer
= new TimeGraphViewer(parent
, style
);
217 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
218 viewer
.setTimeGraphProvider(timeGraphProvider
);
222 public TimeGraphViewer
getTimeGraphViewer() {
227 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
228 viewer
.addSelectionListener(listener
);
232 public ISelectionProvider
getSelectionProvider() {
233 return viewer
.getSelectionProvider();
237 public void setFocus() {
242 public boolean isDisposed() {
243 return viewer
.getControl().isDisposed();
247 public void setInput(Object input
) {
248 viewer
.setInput(input
);
252 public Object
getInput() {
253 return viewer
.getInput();
257 public void refresh() {
262 public void redraw() {
263 viewer
.getControl().redraw();
267 public void update() {
268 viewer
.getControl().update();
272 public void setAutoExpandLevel(int level
) {
273 viewer
.setAutoExpandLevel(level
);
277 public void performAlign(int offset
, int width
) {
278 viewer
.performAlign(offset
, width
);
282 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
283 return viewer
.getTimeViewAlignmentInfo();
287 public int getAvailableWidth(int requestedOffset
) {
288 return viewer
.getAvailableWidth(requestedOffset
);
292 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
293 private TimeGraphCombo combo
;
295 private TimeGraphComboWrapper(Composite parent
, int style
) {
296 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
300 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
301 combo
.setTimeGraphProvider(timeGraphProvider
);
305 public TimeGraphViewer
getTimeGraphViewer() {
306 return combo
.getTimeGraphViewer();
310 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
311 combo
.addSelectionListener(listener
);
315 public ISelectionProvider
getSelectionProvider() {
316 return combo
.getTreeViewer();
320 public void setFocus() {
325 public boolean isDisposed() {
326 return combo
.isDisposed();
330 public void setInput(Object input
) {
331 combo
.setInput(input
);
335 public Object
getInput() {
336 return combo
.getInput();
340 public void refresh() {
345 public void redraw() {
350 public void update() {
355 public void setAutoExpandLevel(int level
) {
356 combo
.setAutoExpandLevel(level
);
359 TimeGraphCombo
getTimeGraphCombo() {
363 TreeViewer
getTreeViewer() {
364 return combo
.getTreeViewer();
367 IAction
getShowFilterAction() {
368 return combo
.getShowFilterAction();
372 public void performAlign(int offset
, int width
) {
373 combo
.performAlign(offset
, width
);
377 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
378 return combo
.getTimeViewAlignmentInfo();
382 public int getAvailableWidth(int requestedOffset
) {
383 return combo
.getAvailableWidth(requestedOffset
);
388 * Base class to provide the labels for the tree viewer. Views extending
389 * this class typically need to override the getColumnText method if they
390 * have more than one column to display
392 protected static class TreeLabelProvider
implements ITableLabelProvider
, ILabelProvider
{
395 public void addListener(ILabelProviderListener listener
) {
399 public void dispose() {
403 public boolean isLabelProperty(Object element
, String property
) {
408 public void removeListener(ILabelProviderListener listener
) {
412 public Image
getColumnImage(Object element
, int columnIndex
) {
417 public String
getColumnText(Object element
, int columnIndex
) {
418 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
419 if (columnIndex
== 0) {
420 return entry
.getName();
426 public Image
getImage(Object element
) {
431 public String
getText(Object element
) {
432 TimeGraphEntry entry
= (TimeGraphEntry
) element
;
433 return entry
.getName();
438 private class BuildThread
extends Thread
{
439 private final @NonNull ITmfTrace fBuildTrace
;
440 private final @NonNull ITmfTrace fParentTrace
;
441 private final @NonNull IProgressMonitor fMonitor
;
443 public BuildThread(final @NonNull ITmfTrace trace
, final @NonNull ITmfTrace parentTrace
, final String name
) {
444 super(name
+ " build"); //$NON-NLS-1$
446 fParentTrace
= parentTrace
;
447 fMonitor
= new NullProgressMonitor();
452 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
453 synchronized (fBuildThreadMap
) {
454 fBuildThreadMap
.remove(fBuildTrace
);
458 public void cancel() {
459 fMonitor
.setCanceled(true);
467 protected abstract class ZoomThread
extends Thread
{
468 private final long fZoomStartTime
;
469 private final long fZoomEndTime
;
470 private final long fResolution
;
471 private final @NonNull IProgressMonitor fMonitor
;
483 public ZoomThread(long startTime
, long endTime
, long resolution
) {
484 super(AbstractTimeGraphView
.this.getName() + " zoom"); //$NON-NLS-1$
485 fZoomStartTime
= startTime
;
486 fZoomEndTime
= endTime
;
487 fResolution
= resolution
;
488 fMonitor
= new NullProgressMonitor();
492 * @return the zoom start time
494 public long getZoomStartTime() {
495 return fZoomStartTime
;
499 * @return the zoom end time
501 public long getZoomEndTime() {
506 * @return the resolution
508 public long getResolution() {
513 * @return the monitor
515 public @NonNull IProgressMonitor
getMonitor() {
520 * Cancel the zoom thread
522 public void cancel() {
523 fMonitor
.setCanceled(true);
527 private class ZoomThreadByEntry
extends ZoomThread
{
528 private final @NonNull List
<TimeGraphEntry
> fZoomEntryList
;
530 public ZoomThreadByEntry(@NonNull List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, long resolution
) {
531 super(startTime
, endTime
, resolution
);
532 fZoomEntryList
= entryList
;
537 for (TimeGraphEntry entry
: fZoomEntryList
) {
538 if (getMonitor().isCanceled()) {
544 zoom(entry
, getMonitor());
546 /* Refresh the arrows when zooming */
547 List
<ILinkEvent
> events
= getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
548 if (events
!= null) {
549 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
554 private void zoom(@NonNull TimeGraphEntry entry
, @NonNull IProgressMonitor monitor
) {
555 if (getZoomStartTime() <= fStartTime
&& getZoomEndTime() >= fEndTime
) {
556 entry
.setZoomedEventList(null);
558 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor
);
559 if (zoomedEventList
!= null) {
560 entry
.setZoomedEventList(zoomedEventList
);
564 for (ITimeGraphEntry child
: entry
.getChildren()) {
565 if (monitor
.isCanceled()) {
568 if (child
instanceof TimeGraphEntry
) {
569 zoom((TimeGraphEntry
) child
, monitor
);
576 // ------------------------------------------------------------------------
578 // ------------------------------------------------------------------------
581 * Constructs a time graph view that contains either a time graph viewer or
582 * a time graph combo.
584 * By default, the view uses a time graph viewer. To use a time graph combo,
585 * the subclass constructor must call {@link #setTreeColumns(String[])} and
586 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
591 * The presentation provider
593 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
595 fPresentation
= pres
;
596 fDisplayWidth
= Display
.getDefault().getBounds().width
;
599 // ------------------------------------------------------------------------
600 // Getters and setters
601 // ------------------------------------------------------------------------
604 * Getter for the time graph combo
606 * @return The time graph combo, or null if combo is not used
608 protected TimeGraphCombo
getTimeGraphCombo() {
609 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
610 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
616 * Getter for the time graph viewer
618 * @return The time graph viewer
620 protected TimeGraphViewer
getTimeGraphViewer() {
621 return fTimeGraphWrapper
.getTimeGraphViewer();
625 * Getter for the presentation provider
627 * @return The time graph presentation provider
629 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
630 return fPresentation
;
634 * Sets the tree column labels.
635 * This should be called from the constructor.
638 * The array of tree column labels
640 protected void setTreeColumns(final String
[] columns
) {
645 * Sets the tree label provider.
646 * This should be called from the constructor.
649 * The tree label provider
651 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
652 fLabelProvider
= tlp
;
656 * Sets the time graph content provider. This should be called from the
660 * The time graph content provider
663 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp
) {
664 fTimeGraphContentProvider
= tgcp
;
668 * Sets the relative weight of each part of the time graph combo.
669 * This should be called from the constructor.
672 * The array (length 2) of relative weights of each part of the combo
674 protected void setWeight(final int[] weights
) {
679 * Sets the filter column labels.
680 * This should be called from the constructor.
682 * @param filterColumns
683 * The array of filter column labels
685 protected void setFilterColumns(final String
[] filterColumns
) {
686 fFilterColumns
= filterColumns
;
690 * Sets the filter label provider.
691 * This should be called from the constructor.
693 * @param labelProvider
694 * The filter label provider
696 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
697 fFilterLabelProvider
= labelProvider
;
701 * Gets the display width
703 * @return the display width
705 protected int getDisplayWidth() {
706 return fDisplayWidth
;
710 * Gets the comparator for the entries
712 * @return The entry comparator
714 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
715 return fEntryComparator
;
719 * Sets the comparator class for the entries
722 * A comparator object
724 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
725 fEntryComparator
= comparator
;
729 * Gets the trace displayed in the view
733 protected ITmfTrace
getTrace() {
738 * Gets the start time
740 * @return The start time
742 protected long getStartTime() {
747 * Sets the start time
752 protected void setStartTime(long time
) {
759 * @return The end time
761 protected long getEndTime() {
771 protected void setEndTime(long time
) {
776 * Sets the auto-expand level to be used for the input of the view. The
777 * value 0 means that there is no auto-expand; 1 means that top-level
778 * elements are expanded, but not their children; 2 means that top-level
779 * elements are expanded, and their children, but not grand-children; and so
782 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
786 * non-negative level, or <code>ALL_LEVELS</code> to expand all
789 protected void setAutoExpandLevel(int level
) {
790 fAutoExpandLevel
= level
;
791 ITimeGraphWrapper tgWrapper
= fTimeGraphWrapper
;
792 if (tgWrapper
!= null) {
793 tgWrapper
.setAutoExpandLevel(level
);
798 * Gets the entry list for a trace
803 * @return the entry list map
805 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
806 synchronized (fEntryListMap
) {
807 return fEntryListMap
.get(trace
);
812 * Adds a trace entry list to the entry list map
817 * the list of time graph entries
819 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
820 synchronized (fEntryListMap
) {
821 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
826 * Adds a list of entries to a trace's entry list
831 * the list of time graph entries to add
833 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
834 synchronized (fEntryListMap
) {
835 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
836 if (entryList
== null) {
837 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
839 entryList
.addAll(list
);
845 * Removes a list of entries from a trace's entry list
850 * the list of time graph entries to remove
852 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
853 synchronized (fEntryListMap
) {
854 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
855 if (entryList
!= null) {
856 entryList
.removeAll(list
);
862 * Text for the "next" button
864 * @return The "next" button text
866 protected String
getNextText() {
867 return Messages
.AbstractTimeGraphtView_NextText
;
871 * Tooltip for the "next" button
873 * @return Tooltip for the "next" button
875 protected String
getNextTooltip() {
876 return Messages
.AbstractTimeGraphView_NextTooltip
;
880 * Text for the "Previous" button
882 * @return The "Previous" button text
884 protected String
getPrevText() {
885 return Messages
.AbstractTimeGraphView_PreviousText
;
889 * Tooltip for the "previous" button
891 * @return Tooltip for the "previous" button
893 protected String
getPrevTooltip() {
894 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
897 // ------------------------------------------------------------------------
899 // ------------------------------------------------------------------------
902 public void createPartControl(Composite parent
) {
903 super.createPartControl(parent
);
904 if (fColumns
== null || fLabelProvider
== null) {
905 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
906 TimeGraphViewer viewer
= fTimeGraphWrapper
.getTimeGraphViewer();
907 viewer
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
909 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
910 fTimeGraphWrapper
= wrapper
;
911 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
912 combo
.setTreeContentProvider(fTimeGraphContentProvider
);
913 combo
.setTreeLabelProvider(fLabelProvider
);
914 combo
.setTreeColumns(fColumns
);
915 combo
.setFilterContentProvider(fTimeGraphContentProvider
);
916 combo
.setFilterLabelProvider(fFilterLabelProvider
);
917 combo
.setFilterColumns(fFilterColumns
);
918 combo
.setTimeGraphContentProvider(fTimeGraphContentProvider
);
921 fTimeGraphWrapper
.setTimeGraphProvider(fPresentation
);
922 fTimeGraphWrapper
.setAutoExpandLevel(fAutoExpandLevel
);
924 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
926 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
927 final long startTime
= event
.getStartTime();
928 final long endTime
= event
.getEndTime();
929 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
930 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView
.this, range
));
931 startZoomThread(startTime
, endTime
);
935 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
937 public void timeSelected(TimeGraphTimeEvent event
) {
938 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
939 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
940 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
944 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
946 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
947 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
949 // View Action Handling
951 contributeToActionBars();
953 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
955 traceSelected(new TmfTraceSelectedSignal(this, trace
));
958 // make selection available to other views
959 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
963 public void setFocus() {
964 fTimeGraphWrapper
.setFocus();
967 // ------------------------------------------------------------------------
969 // ------------------------------------------------------------------------
972 * Handler for the trace opened signal.
975 * The incoming signal
978 public void traceOpened(TmfTraceOpenedSignal signal
) {
979 fTrace
= signal
.getTrace();
984 * Handler for the trace selected signal
987 * The incoming signal
990 public void traceSelected(final TmfTraceSelectedSignal signal
) {
991 if (signal
.getTrace() == fTrace
) {
994 fTrace
= signal
.getTrace();
999 * Trace is closed: clear the data structures and the view
1002 * the signal received
1005 public void traceClosed(final TmfTraceClosedSignal signal
) {
1006 synchronized (fBuildThreadMap
) {
1007 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
1008 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
1009 if (buildThread
!= null) {
1010 buildThread
.cancel();
1014 synchronized (fEntryListMap
) {
1015 fEntryListMap
.remove(signal
.getTrace());
1017 if (signal
.getTrace() == fTrace
) {
1021 if (fZoomThread
!= null) {
1022 fZoomThread
.cancel();
1030 * Handler for the selection range signal.
1033 * The signal that's received
1037 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
1038 if (signal
.getSource() == this || fTrace
== null) {
1041 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1042 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1044 Display
.getDefault().asyncExec(new Runnable() {
1047 if (fTimeGraphWrapper
.isDisposed()) {
1050 if (beginTime
== endTime
) {
1051 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
1053 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
1055 startZoomThread(fTimeGraphWrapper
.getTimeGraphViewer().getTime0(), fTimeGraphWrapper
.getTimeGraphViewer().getTime1());
1057 synchingToTime(beginTime
);
1063 * Handler for the window range signal.
1066 * The signal that's received
1070 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
1071 if (signal
.getSource() == this || fTrace
== null) {
1074 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
1077 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1078 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1079 Display
.getDefault().asyncExec(new Runnable() {
1082 if (fTimeGraphWrapper
.isDisposed()) {
1085 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1086 startZoomThread(startTime
, endTime
);
1092 * @param signal the format of the timestamps was updated.
1095 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1096 fTimeGraphWrapper
.refresh();
1099 // ------------------------------------------------------------------------
1101 // ------------------------------------------------------------------------
1103 private void loadTrace() {
1104 if (fZoomThread
!= null) {
1105 fZoomThread
.cancel();
1108 synchronized (fEntryListMap
) {
1109 fEntryList
= fEntryListMap
.get(fTrace
);
1110 if (fEntryList
== null) {
1113 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1114 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1121 * Forces a rebuild of the entries list, even if entries already exist for this trace
1123 protected void rebuild() {
1124 setStartTime(Long
.MAX_VALUE
);
1125 setEndTime(Long
.MIN_VALUE
);
1127 ITmfTrace viewTrace
= fTrace
;
1128 if (viewTrace
== null) {
1131 synchronized (fBuildThreadMap
) {
1132 for (ITmfTrace trace
: getTracesToBuild(viewTrace
)) {
1133 if (trace
== null) {
1136 BuildThread buildThread
= new BuildThread(trace
, viewTrace
, getName());
1137 fBuildThreadMap
.put(trace
, buildThread
);
1138 buildThread
.start();
1144 * Method called when synching to a given timestamp. Inheriting classes can
1145 * perform actions here to update the view at the given timestamp.
1148 * The currently selected time
1150 protected void synchingToTime(long time
) {
1155 * Return the list of traces whose data or analysis results will be used to
1156 * populate the view. By default, if the trace is an experiment, the traces
1157 * under it will be returned, otherwise, the trace itself is returned.
1159 * A build thread will be started for each trace returned by this method,
1160 * some of which may receive events in live streaming mode.
1163 * The trace associated with this view
1164 * @return List of traces with data to display
1166 protected @NonNull Iterable
<ITmfTrace
> getTracesToBuild(@NonNull ITmfTrace trace
) {
1167 return TmfTraceManager
.getTraceSet(trace
);
1171 * Build the entries list to show in this time graph
1173 * Called from the BuildThread
1176 * The trace being built
1177 * @param parentTrace
1178 * The parent of the trace set, or the trace itself
1180 * The progress monitor object
1182 protected abstract void buildEventList(@NonNull ITmfTrace trace
, @NonNull ITmfTrace parentTrace
, @NonNull IProgressMonitor monitor
);
1185 * Gets the list of event for an entry in a given timerange
1188 * The entry to get events for
1190 * Start of the time range
1192 * End of the time range
1196 * The progress monitor object
1197 * @return The list of events for the entry
1199 protected abstract @Nullable List
<ITimeEvent
> getEventList(@NonNull TimeGraphEntry entry
,
1200 long startTime
, long endTime
, long resolution
,
1201 @NonNull IProgressMonitor monitor
);
1204 * Gets the list of links (displayed as arrows) for a trace in a given
1205 * timerange. Default implementation returns an empty list.
1208 * Start of the time range
1210 * End of the time range
1214 * The progress monitor object
1215 * @return The list of link events
1217 protected @Nullable List
<ILinkEvent
> getLinkList(long startTime
, long endTime
,
1218 long resolution
, @NonNull IProgressMonitor monitor
) {
1219 return new ArrayList
<>();
1224 * Refresh the display
1226 protected void refresh() {
1227 final boolean zoomThread
= Thread
.currentThread() instanceof ZoomThread
;
1228 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1231 if (fTimeGraphWrapper
.isDisposed()) {
1234 boolean hasEntries
= false;
1235 synchronized (fEntryListMap
) {
1236 fEntryList
= fEntryListMap
.get(fTrace
);
1237 if (fEntryList
== null) {
1238 fEntryList
= new CopyOnWriteArrayList
<>();
1239 } else if (fEntryComparator
!= null) {
1240 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1241 Collections
.sort(list
, fEntryComparator
);
1243 fEntryList
.addAll(list
);
1245 hasEntries
= fEntryList
.size() != 0;
1247 if (fEntryList
!= fTimeGraphWrapper
.getInput()) {
1248 fTimeGraphWrapper
.setInput(fEntryList
);
1249 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(null);
1251 fTimeGraphWrapper
.refresh();
1253 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
1255 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
1256 long selectionBeginTime
= fTrace
== null ?
0 : ctx
.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1257 long selectionEndTime
= fTrace
== null ?
0 : ctx
.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1258 long startTime
= fTrace
== null ?
0 : ctx
.getWindowRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1259 long endTime
= fTrace
== null ?
0 : ctx
.getWindowRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1260 startTime
= Math
.max(startTime
, fStartTime
);
1261 endTime
= Math
.min(endTime
, fEndTime
);
1262 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1263 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1265 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1266 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1275 startZoomThread(startTime
, endTime
);
1284 protected void redraw() {
1285 synchronized (fSyncObj
) {
1286 if (fRedrawState
== State
.IDLE
) {
1287 fRedrawState
= State
.BUSY
;
1289 fRedrawState
= State
.PENDING
;
1293 Display
.getDefault().asyncExec(new Runnable() {
1296 if (fTimeGraphWrapper
.isDisposed()) {
1299 fTimeGraphWrapper
.redraw();
1300 fTimeGraphWrapper
.update();
1301 synchronized (fSyncObj
) {
1302 if (fRedrawState
== State
.PENDING
) {
1303 fRedrawState
= State
.IDLE
;
1306 fRedrawState
= State
.IDLE
;
1313 private void startZoomThread(long startTime
, long endTime
) {
1314 boolean restart
= false;
1315 if (fZoomThread
!= null) {
1316 fZoomThread
.cancel();
1317 if (fZoomThread
.fZoomStartTime
== startTime
&& fZoomThread
.fZoomEndTime
== endTime
) {
1321 long resolution
= Math
.max(1, (endTime
- startTime
) / fDisplayWidth
);
1322 fZoomThread
= createZoomThread(startTime
, endTime
, resolution
, restart
);
1323 if (fZoomThread
!= null) {
1324 fZoomThread
.start();
1329 * Create a zoom thread.
1332 * the zoom start time
1338 * true if restarting zoom for the same time range
1339 * @return a zoom thread
1342 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
1343 final List
<TimeGraphEntry
> entryList
= fEntryList
;
1344 if (entryList
== null) {
1347 return new ZoomThreadByEntry(entryList
, startTime
, endTime
, resolution
);
1350 private void makeActions() {
1351 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1352 fPreviousResourceAction
.setText(getPrevText());
1353 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1354 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1355 fNextResourceAction
.setText(getNextText());
1356 fNextResourceAction
.setToolTipText(getNextTooltip());
1359 private void contributeToActionBars() {
1360 IActionBars bars
= getViewSite().getActionBars();
1361 fillLocalToolBar(bars
.getToolBarManager());
1365 * Add actions to local tool bar manager
1367 * @param manager the tool bar manager
1369 protected void fillLocalToolBar(IToolBarManager manager
) {
1370 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
1371 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1372 manager
.add(((TimeGraphComboWrapper
) fTimeGraphWrapper
).getShowFilterAction());
1375 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1376 manager
.add(new Separator());
1377 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1378 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1379 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1380 manager
.add(fPreviousResourceAction
);
1381 manager
.add(fNextResourceAction
);
1382 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1383 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1384 manager
.add(new Separator());
1391 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
1392 if (fTimeGraphWrapper
== null) {
1395 return fTimeGraphWrapper
.getTimeViewAlignmentInfo();
1402 public int getAvailableWidth(int requestedOffset
) {
1403 if (fTimeGraphWrapper
== null) {
1406 return fTimeGraphWrapper
.getAvailableWidth(requestedOffset
);
1413 public void performAlign(int offset
, int width
) {
1414 if (fTimeGraphWrapper
!= null) {
1415 fTimeGraphWrapper
.performAlign(offset
, width
);