1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 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
.linuxtools
.tmf
.ui
.views
.timegraph
;
19 import java
.util
.ArrayList
;
20 import java
.util
.Arrays
;
21 import java
.util
.Collections
;
22 import java
.util
.Comparator
;
23 import java
.util
.HashMap
;
24 import java
.util
.List
;
26 import java
.util
.concurrent
.CopyOnWriteArrayList
;
28 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
29 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
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
.ILabelProviderListener
;
37 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
38 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
39 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
40 import org
.eclipse
.jface
.viewers
.TreeViewer
;
41 import org
.eclipse
.jface
.viewers
.Viewer
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceClosedSignal
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.ITmfTimestamp
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
51 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimeRange
;
52 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
53 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTraceManager
;
54 import org
.eclipse
.linuxtools
.tmf
.ui
.TmfUiRefreshHandler
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
56 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
57 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
58 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
59 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
64 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
65 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
66 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
67 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
68 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
69 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
70 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
71 import org
.eclipse
.swt
.SWT
;
72 import org
.eclipse
.swt
.graphics
.Image
;
73 import org
.eclipse
.swt
.widgets
.Composite
;
74 import org
.eclipse
.swt
.widgets
.Display
;
75 import org
.eclipse
.swt
.widgets
.TreeColumn
;
76 import org
.eclipse
.ui
.IActionBars
;
79 * An abstract view all time graph views can inherit
81 * This view contains either a time graph viewer, or a time graph combo which is
82 * divided between a tree viewer on the left and a time graph viewer on the right.
86 public abstract class AbstractTimeGraphView
extends TmfView
{
95 // ------------------------------------------------------------------------
97 // ------------------------------------------------------------------------
99 /** The timegraph wrapper */
100 private ITimeGraphWrapper fTimeGraphWrapper
;
102 /** The selected trace */
103 private ITmfTrace fTrace
;
105 /** The timegraph entry list */
106 private List
<TimeGraphEntry
> fEntryList
;
108 /** The trace to entry list hash map */
109 private final Map
<ITmfTrace
, List
<TimeGraphEntry
>> fEntryListMap
= new HashMap
<>();
111 /** The trace to build thread hash map */
112 private final Map
<ITmfTrace
, BuildThread
> fBuildThreadMap
= new HashMap
<>();
114 /** The start time */
115 private long fStartTime
;
118 private long fEndTime
;
120 /** The display width */
121 private final int fDisplayWidth
;
123 /** The zoom thread */
124 private ZoomThread fZoomThread
;
126 /** The next resource action */
127 private Action fNextResourceAction
;
129 /** The previous resource action */
130 private Action fPreviousResourceAction
;
132 /** A comparator class */
133 private Comparator
<ITimeGraphEntry
> fEntryComparator
= null;
135 /** The redraw state used to prevent unnecessary queuing of display runnables */
136 private State fRedrawState
= State
.IDLE
;
138 /** The redraw synchronization object */
139 private final Object fSyncObj
= new Object();
141 /** The presentation provider for this view */
142 private final TimeGraphPresentationProvider fPresentation
;
144 /** The tree column label array, or null if combo is not used */
145 private String
[] fColumns
;
147 /** The tree label provider, or null if combo is not used */
148 private TreeLabelProvider fLabelProvider
= null;
150 /** The relative weight of the sash, ignored if combo is not used */
151 private int[] fWeight
= { 1, 1 };
153 /** The filter column label array, or null if filter is not used */
154 private String
[] fFilterColumns
;
156 /** The pack done flag */
157 private boolean fPackDone
= false;
159 /** The filter label provider, or null if filter is not used */
160 private TreeLabelProvider fFilterLabelProvider
;
162 // ------------------------------------------------------------------------
164 // ------------------------------------------------------------------------
166 private interface ITimeGraphWrapper
{
168 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation
);
170 TimeGraphViewer
getTimeGraphViewer();
172 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener
);
174 ISelectionProvider
getSelectionProvider();
178 boolean isDisposed();
182 void setInput(Object input
);
192 private class TimeGraphViewerWrapper
implements ITimeGraphWrapper
{
193 private TimeGraphViewer viewer
;
195 private TimeGraphViewerWrapper(Composite parent
, int style
) {
196 viewer
= new TimeGraphViewer(parent
, style
);
200 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
201 viewer
.setTimeGraphProvider(timeGraphProvider
);
205 public TimeGraphViewer
getTimeGraphViewer() {
210 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
211 viewer
.addSelectionListener(listener
);
215 public ISelectionProvider
getSelectionProvider() {
216 return viewer
.getSelectionProvider();
220 public void setFocus() {
225 public boolean isDisposed() {
226 return viewer
.getControl().isDisposed();
230 public void setInput(Object input
) {
231 viewer
.setInput(input
);
235 public Object
getInput() {
236 return viewer
.getInput();
240 public void refresh() {
245 public void redraw() {
246 viewer
.getControl().redraw();
250 public void update() {
251 viewer
.getControl().update();
255 private class TimeGraphComboWrapper
implements ITimeGraphWrapper
{
256 private TimeGraphCombo combo
;
258 private TimeGraphComboWrapper(Composite parent
, int style
) {
259 combo
= new TimeGraphCombo(parent
, style
, fWeight
);
263 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider
) {
264 combo
.setTimeGraphProvider(timeGraphProvider
);
268 public TimeGraphViewer
getTimeGraphViewer() {
269 return combo
.getTimeGraphViewer();
273 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
274 combo
.addSelectionListener(listener
);
278 public ISelectionProvider
getSelectionProvider() {
279 return combo
.getTreeViewer();
283 public void setFocus() {
288 public boolean isDisposed() {
289 return combo
.isDisposed();
293 public void setInput(Object input
) {
294 combo
.setInput(input
);
298 public Object
getInput() {
299 return combo
.getInput();
303 public void refresh() {
308 public void redraw() {
313 public void update() {
317 TimeGraphCombo
getTimeGraphCombo() {
321 TreeViewer
getTreeViewer() {
322 return combo
.getTreeViewer();
325 IAction
getShowFilterAction() {
326 return combo
.getShowFilterAction();
330 private class TreeContentProvider
implements ITreeContentProvider
{
333 public void dispose() {
337 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
341 public ITimeGraphEntry
[] getElements(Object inputElement
) {
342 if (inputElement
!= null) {
344 return ((List
<?
>) inputElement
).toArray(new ITimeGraphEntry
[0]);
345 } catch (ClassCastException e
) {
348 return new ITimeGraphEntry
[0];
352 public Object
[] getChildren(Object parentElement
) {
353 ITimeGraphEntry entry
= (ITimeGraphEntry
) parentElement
;
354 List
<?
extends ITimeGraphEntry
> children
= entry
.getChildren();
355 return children
.toArray(new ITimeGraphEntry
[children
.size()]);
359 public Object
getParent(Object element
) {
360 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
361 return entry
.getParent();
365 public boolean hasChildren(Object element
) {
366 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
367 return entry
.hasChildren();
372 private class TimeGraphContentProvider
implements ITimeGraphContentProvider
{
375 public ITimeGraphEntry
[] getElements(Object inputElement
) {
376 if (inputElement
!= null) {
378 return ((List
<?
>) inputElement
).toArray(new ITimeGraphEntry
[0]);
379 } catch (ClassCastException e
) {
382 return new ITimeGraphEntry
[0];
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
{
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();
427 private class BuildThread
extends Thread
{
428 private final ITmfTrace fBuildTrace
;
429 private final ITmfTrace fParentTrace
;
430 private final IProgressMonitor fMonitor
;
432 public BuildThread(final ITmfTrace trace
, final ITmfTrace parentTrace
, final String name
) {
433 super(name
+ " build"); //$NON-NLS-1$
435 fParentTrace
= parentTrace
;
436 fMonitor
= new NullProgressMonitor();
441 buildEventList(fBuildTrace
, fParentTrace
, fMonitor
);
442 synchronized (fBuildThreadMap
) {
443 fBuildThreadMap
.remove(fBuildTrace
);
447 public void cancel() {
448 fMonitor
.setCanceled(true);
452 private class ZoomThread
extends Thread
{
453 private final List
<TimeGraphEntry
> fZoomEntryList
;
454 private final long fZoomStartTime
;
455 private final long fZoomEndTime
;
456 private final long fResolution
;
457 private final IProgressMonitor fMonitor
;
459 public ZoomThread(List
<TimeGraphEntry
> entryList
, long startTime
, long endTime
, String name
) {
460 super(name
+ " zoom"); //$NON-NLS-1$
461 fZoomEntryList
= entryList
;
462 fZoomStartTime
= startTime
;
463 fZoomEndTime
= endTime
;
464 fResolution
= Math
.max(1, (fZoomEndTime
- fZoomStartTime
) / fDisplayWidth
);
465 fMonitor
= new NullProgressMonitor();
470 if (fZoomEntryList
== null) {
473 for (TimeGraphEntry entry
: fZoomEntryList
) {
474 if (fMonitor
.isCanceled()) {
477 zoom(entry
, fMonitor
);
479 /* Refresh the arrows when zooming */
480 List
<ILinkEvent
> events
= getLinkList(fZoomStartTime
, fZoomEndTime
, fResolution
, fMonitor
);
481 if (events
!= null) {
482 fTimeGraphWrapper
.getTimeGraphViewer().setLinks(events
);
487 private void zoom(TimeGraphEntry entry
, IProgressMonitor monitor
) {
488 if (fZoomStartTime
<= fStartTime
&& fZoomEndTime
>= fEndTime
) {
489 entry
.setZoomedEventList(null);
491 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, fResolution
, monitor
);
492 if (zoomedEventList
!= null) {
493 entry
.setZoomedEventList(zoomedEventList
);
497 for (ITimeGraphEntry child
: entry
.getChildren()) {
498 if (fMonitor
.isCanceled()) {
501 if (child
instanceof TimeGraphEntry
) {
502 zoom((TimeGraphEntry
) child
, monitor
);
507 public void cancel() {
508 fMonitor
.setCanceled(true);
512 // ------------------------------------------------------------------------
514 // ------------------------------------------------------------------------
517 * Constructs a time graph view that contains either a time graph viewer or
518 * a time graph combo.
520 * By default, the view uses a time graph viewer. To use a time graph combo,
521 * the subclass constructor must call {@link #setTreeColumns(String[])} and
522 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
527 * The presentation provider
529 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
531 fPresentation
= pres
;
532 fDisplayWidth
= Display
.getDefault().getBounds().width
;
535 // ------------------------------------------------------------------------
536 // Getters and setters
537 // ------------------------------------------------------------------------
540 * Getter for the time graph combo
542 * @return The time graph combo, or null if combo is not used
544 protected TimeGraphCombo
getTimeGraphCombo() {
545 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
546 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
552 * Getter for the time graph viewer
554 * @return The time graph viewer
556 protected TimeGraphViewer
getTimeGraphViewer() {
557 return fTimeGraphWrapper
.getTimeGraphViewer();
561 * Getter for the presentation provider
563 * @return The time graph presentation provider
566 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
567 return fPresentation
;
571 * Sets the tree column labels.
572 * This should be called from the constructor.
575 * The array of tree column labels
577 protected void setTreeColumns(final String
[] columns
) {
582 * Sets the tree label provider.
583 * This should be called from the constructor.
586 * The tree label provider
588 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
589 fLabelProvider
= tlp
;
593 * Sets the relative weight of each part of the time graph combo.
594 * This should be called from the constructor.
597 * The array (length 2) of relative weights of each part of the combo
599 protected void setWeight(final int[] weights
) {
604 * Sets the filter column labels.
605 * This should be called from the constructor.
607 * @param filterColumns
608 * The array of filter column labels
610 protected void setFilterColumns(final String
[] filterColumns
) {
611 fFilterColumns
= filterColumns
;
615 * Sets the filter label provider.
616 * This should be called from the constructor.
618 * @param labelProvider
619 * The filter label provider
623 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
624 fFilterLabelProvider
= labelProvider
;
628 * Gets the display width
630 * @return the display width
632 protected int getDisplayWidth() {
633 return fDisplayWidth
;
637 * Gets the comparator for the entries
639 * @return The entry comparator
641 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
642 return fEntryComparator
;
646 * Sets the comparator class for the entries
649 * A comparator object
651 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
652 fEntryComparator
= comparator
;
656 * Gets the trace displayed in the view
660 protected ITmfTrace
getTrace() {
665 * Gets the start time
667 * @return The start time
669 protected long getStartTime() {
674 * Sets the start time
679 protected void setStartTime(long time
) {
686 * @return The end time
688 protected long getEndTime() {
698 protected void setEndTime(long time
) {
703 * Gets the entry list for a trace
708 * @return the entry list map
711 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
712 synchronized (fEntryListMap
) {
713 return fEntryListMap
.get(trace
);
718 * Adds a trace entry list to the entry list map
723 * the list of time graph entries
725 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
726 synchronized (fEntryListMap
) {
727 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
732 * Adds a list of entries to a trace's entry list
737 * the list of time graph entries to add
740 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
741 synchronized (fEntryListMap
) {
742 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
743 if (entryList
== null) {
744 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
746 entryList
.addAll(list
);
752 * Removes a list of entries from a trace's entry list
757 * the list of time graph entries to remove
760 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
761 synchronized (fEntryListMap
) {
762 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
763 if (entryList
!= null) {
764 entryList
.removeAll(list
);
770 * Text for the "next" button
772 * @return The "next" button text
774 protected String
getNextText() {
775 return Messages
.AbstractTimeGraphtView_NextText
;
779 * Tooltip for the "next" button
781 * @return Tooltip for the "next" button
783 protected String
getNextTooltip() {
784 return Messages
.AbstractTimeGraphView_NextTooltip
;
788 * Text for the "Previous" button
790 * @return The "Previous" button text
792 protected String
getPrevText() {
793 return Messages
.AbstractTimeGraphView_PreviousText
;
797 * Tooltip for the "previous" button
799 * @return Tooltip for the "previous" button
801 protected String
getPrevTooltip() {
802 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
805 // ------------------------------------------------------------------------
807 // ------------------------------------------------------------------------
810 public void createPartControl(Composite parent
) {
811 if (fColumns
== null || fLabelProvider
== null) {
812 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
813 TimeGraphViewer viewer
= fTimeGraphWrapper
.getTimeGraphViewer();
814 viewer
.setTimeGraphContentProvider(new TimeGraphContentProvider());
816 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
817 fTimeGraphWrapper
= wrapper
;
818 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
819 combo
.setTreeContentProvider(new TreeContentProvider());
820 combo
.setTreeLabelProvider(fLabelProvider
);
821 combo
.setTreeColumns(fColumns
);
822 combo
.setFilterContentProvider(new TreeContentProvider());
823 combo
.setFilterLabelProvider(fFilterLabelProvider
);
824 combo
.setFilterColumns(fFilterColumns
);
825 combo
.setTimeGraphContentProvider(new TimeGraphContentProvider());
828 fTimeGraphWrapper
.setTimeGraphProvider(fPresentation
);
830 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
832 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
833 final long startTime
= event
.getStartTime();
834 final long endTime
= event
.getEndTime();
835 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
836 broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView
.this, range
));
837 if (fZoomThread
!= null) {
838 fZoomThread
.cancel();
840 startZoomThread(startTime
, endTime
);
844 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
846 public void timeSelected(TimeGraphTimeEvent event
) {
847 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
848 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
849 broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
853 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
855 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
856 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
858 // View Action Handling
860 contributeToActionBars();
862 ITmfTrace trace
= getActiveTrace();
864 traceSelected(new TmfTraceSelectedSignal(this, trace
));
867 // make selection available to other views
868 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
872 public void setFocus() {
873 fTimeGraphWrapper
.setFocus();
876 // ------------------------------------------------------------------------
878 // ------------------------------------------------------------------------
881 * Handler for the trace opened signal.
884 * The incoming signal
888 public void traceOpened(TmfTraceOpenedSignal signal
) {
889 fTrace
= signal
.getTrace();
894 * Handler for the trace selected signal
897 * The incoming signal
900 public void traceSelected(final TmfTraceSelectedSignal signal
) {
901 if (signal
.getTrace() == fTrace
) {
904 fTrace
= signal
.getTrace();
910 * Trace is closed: clear the data structures and the view
913 * the signal received
916 public void traceClosed(final TmfTraceClosedSignal signal
) {
917 synchronized (fBuildThreadMap
) {
918 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
919 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
920 if (buildThread
!= null) {
921 buildThread
.cancel();
925 synchronized (fEntryListMap
) {
926 fEntryListMap
.remove(signal
.getTrace());
928 if (signal
.getTrace() == fTrace
) {
932 if (fZoomThread
!= null) {
933 fZoomThread
.cancel();
940 * Handler for the time synch signal
943 * The signal that's received
946 public void synchToTime(final TmfTimeSynchSignal signal
) {
947 if (signal
.getSource() == this || fTrace
== null) {
950 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
951 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
953 Display
.getDefault().asyncExec(new Runnable() {
956 if (fTimeGraphWrapper
.isDisposed()) {
959 if (beginTime
== endTime
) {
960 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
962 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
964 startZoomThread(fTimeGraphWrapper
.getTimeGraphViewer().getTime0(), fTimeGraphWrapper
.getTimeGraphViewer().getTime1());
966 synchingToTime(beginTime
);
972 * Handler for the range synch signal
975 * The signal that's received
978 public void synchToRange(final TmfRangeSynchSignal signal
) {
979 if (signal
.getSource() == this || fTrace
== null) {
982 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
985 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
986 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
987 Display
.getDefault().asyncExec(new Runnable() {
990 if (fTimeGraphWrapper
.isDisposed()) {
993 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
994 startZoomThread(startTime
, endTime
);
1000 * @param signal the format of the timestamps was updated.
1004 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1005 fTimeGraphWrapper
.refresh();
1008 // ------------------------------------------------------------------------
1010 // ------------------------------------------------------------------------
1012 private void loadTrace() {
1013 synchronized (fEntryListMap
) {
1014 fEntryList
= fEntryListMap
.get(fTrace
);
1015 if (fEntryList
== null) {
1018 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1019 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1026 * Forces a rebuild of the entries list, even if entries already exist for this trace
1029 protected void rebuild() {
1030 setStartTime(Long
.MAX_VALUE
);
1031 setEndTime(Long
.MIN_VALUE
);
1032 synchronized (fBuildThreadMap
) {
1033 for (ITmfTrace trace
: getTracesToBuild(fTrace
)) {
1034 BuildThread buildThread
= new BuildThread(trace
, fTrace
, getName());
1035 fBuildThreadMap
.put(trace
, buildThread
);
1036 buildThread
.start();
1042 * Method called when synching to a given timestamp. Inheriting classes can
1043 * perform actions here to update the view at the given timestamp.
1046 * The currently selected time
1048 protected void synchingToTime(long time
) {
1053 * Return the list of traces whose data or analysis results will be used to
1054 * populate the view. By default, if the trace is an experiment, the traces
1055 * under it will be returned, otherwise, the trace itself is returned.
1057 * A build thread will be started for each trace returned by this method,
1058 * some of which may receive events in live streaming mode.
1061 * The trace associated with this view
1062 * @return List of traces with data to display
1065 protected Iterable
<ITmfTrace
> getTracesToBuild(ITmfTrace trace
) {
1066 return Arrays
.asList(TmfTraceManager
.getTraceSet(trace
));
1070 * Build the entries list to show in this time graph
1072 * Called from the BuildThread
1075 * The trace being built
1076 * @param parentTrace
1077 * The parent of the trace set, or the trace itself
1079 * The progress monitor object
1082 protected abstract void buildEventList(ITmfTrace trace
, ITmfTrace parentTrace
, IProgressMonitor monitor
);
1085 * Gets the list of event for an entry in a given timerange
1088 * The entry to get events for
1090 * Start of the time range
1092 * End of the time range
1096 * The progress monitor object
1097 * @return The list of events for the entry
1099 protected abstract @Nullable List
<ITimeEvent
> getEventList(TimeGraphEntry entry
,
1100 long startTime
, long endTime
, long resolution
,
1101 IProgressMonitor monitor
);
1104 * Gets the list of links (displayed as arrows) for a trace in a given
1105 * timerange. Default implementation returns an empty list.
1108 * Start of the time range
1110 * End of the time range
1114 * The progress monitor object
1115 * @return The list of link events
1118 protected List
<ILinkEvent
> getLinkList(long startTime
, long endTime
,
1119 long resolution
, IProgressMonitor monitor
) {
1120 return new ArrayList
<>();
1125 * Refresh the display
1127 protected void refresh() {
1128 TmfUiRefreshHandler
.getInstance().queueUpdate(this, new Runnable() {
1131 if (fTimeGraphWrapper
.isDisposed()) {
1134 boolean hasEntries
= false;
1135 synchronized (fEntryListMap
) {
1136 fEntryList
= fEntryListMap
.get(fTrace
);
1137 if (fEntryList
== null) {
1138 fEntryList
= new CopyOnWriteArrayList
<>();
1139 } else if (fEntryComparator
!= null) {
1140 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1141 Collections
.sort(list
, fEntryComparator
);
1143 fEntryList
.addAll(list
);
1145 hasEntries
= fEntryList
.size() != 0;
1147 if (fEntryList
!= fTimeGraphWrapper
.getInput()) {
1148 fTimeGraphWrapper
.setInput(fEntryList
);
1150 fTimeGraphWrapper
.refresh();
1152 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
1154 long selectionBeginTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1155 long selectionEndTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1156 long startTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1157 long endTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1158 startTime
= Math
.max(startTime
, fStartTime
);
1159 endTime
= Math
.min(endTime
, fEndTime
);
1160 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1161 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1163 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1164 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1172 startZoomThread(startTime
, endTime
);
1180 protected void redraw() {
1181 synchronized (fSyncObj
) {
1182 if (fRedrawState
== State
.IDLE
) {
1183 fRedrawState
= State
.BUSY
;
1185 fRedrawState
= State
.PENDING
;
1189 Display
.getDefault().asyncExec(new Runnable() {
1192 if (fTimeGraphWrapper
.isDisposed()) {
1195 fTimeGraphWrapper
.redraw();
1196 fTimeGraphWrapper
.update();
1197 synchronized (fSyncObj
) {
1198 if (fRedrawState
== State
.PENDING
) {
1199 fRedrawState
= State
.IDLE
;
1202 fRedrawState
= State
.IDLE
;
1209 private void startZoomThread(long startTime
, long endTime
) {
1210 if (fZoomThread
!= null) {
1211 fZoomThread
.cancel();
1213 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
, getName());
1214 fZoomThread
.start();
1217 private void makeActions() {
1218 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1219 fPreviousResourceAction
.setText(getPrevText());
1220 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1221 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1222 fNextResourceAction
.setText(getNextText());
1223 fNextResourceAction
.setToolTipText(getNextTooltip());
1226 private void contributeToActionBars() {
1227 IActionBars bars
= getViewSite().getActionBars();
1228 fillLocalToolBar(bars
.getToolBarManager());
1232 * Add actions to local tool bar manager
1234 * @param manager the tool bar manager
1236 protected void fillLocalToolBar(IToolBarManager manager
) {
1237 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
1238 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1239 manager
.add(((TimeGraphComboWrapper
) fTimeGraphWrapper
).getShowFilterAction());
1242 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1243 manager
.add(new Separator());
1244 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1245 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1246 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1247 manager
.add(fPreviousResourceAction
);
1248 manager
.add(fNextResourceAction
);
1249 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1250 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1251 manager
.add(new Separator());