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
.views
.TmfView
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphContentProvider
;
56 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphPresentationProvider2
;
57 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphRangeListener
;
58 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphSelectionListener
;
59 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
60 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphCombo
;
61 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
62 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
63 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphSelectionEvent
;
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 (TimeGraphEntry child
: entry
.getChildren()) {
498 if (fMonitor
.isCanceled()) {
501 zoom(child
, monitor
);
505 public void cancel() {
506 fMonitor
.setCanceled(true);
510 // ------------------------------------------------------------------------
512 // ------------------------------------------------------------------------
515 * Constructs a time graph view that contains either a time graph viewer or
516 * a time graph combo.
518 * By default, the view uses a time graph viewer. To use a time graph combo,
519 * the subclass constructor must call {@link #setTreeColumns(String[])} and
520 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
525 * The presentation provider
527 public AbstractTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
529 fPresentation
= pres
;
530 fDisplayWidth
= Display
.getDefault().getBounds().width
;
533 // ------------------------------------------------------------------------
534 // Getters and setters
535 // ------------------------------------------------------------------------
538 * Getter for the time graph combo
540 * @return The time graph combo, or null if combo is not used
542 protected TimeGraphCombo
getTimeGraphCombo() {
543 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
544 return ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTimeGraphCombo();
550 * Getter for the time graph viewer
552 * @return The time graph viewer
554 protected TimeGraphViewer
getTimeGraphViewer() {
555 return fTimeGraphWrapper
.getTimeGraphViewer();
559 * Getter for the presentation provider
561 * @return The time graph presentation provider
564 protected ITimeGraphPresentationProvider2
getPresentationProvider() {
565 return fPresentation
;
569 * Sets the tree column labels.
570 * This should be called from the constructor.
573 * The array of tree column labels
575 protected void setTreeColumns(final String
[] columns
) {
580 * Sets the tree label provider.
581 * This should be called from the constructor.
584 * The tree label provider
586 protected void setTreeLabelProvider(final TreeLabelProvider tlp
) {
587 fLabelProvider
= tlp
;
591 * Sets the relative weight of each part of the time graph combo.
592 * This should be called from the constructor.
595 * The array (length 2) of relative weights of each part of the combo
597 protected void setWeight(final int[] weights
) {
602 * Sets the filter column labels.
603 * This should be called from the constructor.
605 * @param filterColumns
606 * The array of filter column labels
608 protected void setFilterColumns(final String
[] filterColumns
) {
609 fFilterColumns
= filterColumns
;
613 * Sets the filter label provider.
614 * This should be called from the constructor.
616 * @param labelProvider
617 * The filter label provider
621 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider
) {
622 fFilterLabelProvider
= labelProvider
;
626 * Gets the display width
628 * @return the display width
630 protected int getDisplayWidth() {
631 return fDisplayWidth
;
635 * Gets the comparator for the entries
637 * @return The entry comparator
639 protected Comparator
<ITimeGraphEntry
> getEntryComparator() {
640 return fEntryComparator
;
644 * Sets the comparator class for the entries
647 * A comparator object
649 protected void setEntryComparator(final Comparator
<ITimeGraphEntry
> comparator
) {
650 fEntryComparator
= comparator
;
654 * Gets the trace displayed in the view
658 protected ITmfTrace
getTrace() {
663 * Gets the start time
665 * @return The start time
667 protected long getStartTime() {
672 * Sets the start time
677 protected void setStartTime(long time
) {
684 * @return The end time
686 protected long getEndTime() {
696 protected void setEndTime(long time
) {
701 * Gets the entry list for a trace
706 * @return the entry list map
709 protected List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
710 synchronized (fEntryListMap
) {
711 return fEntryListMap
.get(trace
);
716 * Adds a trace entry list to the entry list map
721 * the list of time graph entries
723 protected void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
724 synchronized (fEntryListMap
) {
725 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
730 * Adds a list of entries to a trace's entry list
735 * the list of time graph entries to add
738 protected void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
739 synchronized (fEntryListMap
) {
740 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
741 if (entryList
== null) {
742 fEntryListMap
.put(trace
, new CopyOnWriteArrayList
<>(list
));
744 entryList
.addAll(list
);
750 * Removes a list of entries from a trace's entry list
755 * the list of time graph entries to remove
758 protected void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
759 synchronized (fEntryListMap
) {
760 List
<TimeGraphEntry
> entryList
= fEntryListMap
.get(trace
);
761 if (entryList
!= null) {
762 entryList
.removeAll(list
);
768 * Text for the "next" button
770 * @return The "next" button text
772 protected String
getNextText() {
773 return Messages
.AbstractTimeGraphtView_NextText
;
777 * Tooltip for the "next" button
779 * @return Tooltip for the "next" button
781 protected String
getNextTooltip() {
782 return Messages
.AbstractTimeGraphView_NextTooltip
;
786 * Text for the "Previous" button
788 * @return The "Previous" button text
790 protected String
getPrevText() {
791 return Messages
.AbstractTimeGraphView_PreviousText
;
795 * Tooltip for the "previous" button
797 * @return Tooltip for the "previous" button
799 protected String
getPrevTooltip() {
800 return Messages
.AbstractTimeGraphView_PreviousTooltip
;
803 // ------------------------------------------------------------------------
805 // ------------------------------------------------------------------------
808 public void createPartControl(Composite parent
) {
809 if (fColumns
== null || fLabelProvider
== null) {
810 fTimeGraphWrapper
= new TimeGraphViewerWrapper(parent
, SWT
.NONE
);
811 TimeGraphViewer viewer
= fTimeGraphWrapper
.getTimeGraphViewer();
812 viewer
.setTimeGraphContentProvider(new TimeGraphContentProvider());
814 TimeGraphComboWrapper wrapper
= new TimeGraphComboWrapper(parent
, SWT
.NONE
);
815 fTimeGraphWrapper
= wrapper
;
816 TimeGraphCombo combo
= wrapper
.getTimeGraphCombo();
817 combo
.setTreeContentProvider(new TreeContentProvider());
818 combo
.setTreeLabelProvider(fLabelProvider
);
819 combo
.setTreeColumns(fColumns
);
820 combo
.setFilterContentProvider(new TreeContentProvider());
821 combo
.setFilterLabelProvider(fFilterLabelProvider
);
822 combo
.setFilterColumns(fFilterColumns
);
823 combo
.setTimeGraphContentProvider(new TimeGraphContentProvider());
826 fTimeGraphWrapper
.setTimeGraphProvider(fPresentation
);
828 fTimeGraphWrapper
.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
830 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
831 final long startTime
= event
.getStartTime();
832 final long endTime
= event
.getEndTime();
833 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
834 broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView
.this, range
));
835 if (fZoomThread
!= null) {
836 fZoomThread
.cancel();
838 startZoomThread(startTime
, endTime
);
842 fTimeGraphWrapper
.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
844 public void timeSelected(TimeGraphTimeEvent event
) {
845 TmfNanoTimestamp startTime
= new TmfNanoTimestamp(event
.getBeginTime());
846 TmfNanoTimestamp endTime
= new TmfNanoTimestamp(event
.getEndTime());
847 broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView
.this, startTime
, endTime
));
851 fTimeGraphWrapper
.addSelectionListener(new ITimeGraphSelectionListener() {
853 public void selectionChanged(TimeGraphSelectionEvent event
) {
854 // ITimeGraphEntry selection = event.getSelection();
858 fTimeGraphWrapper
.getTimeGraphViewer().setTimeFormat(TimeFormat
.CALENDAR
);
860 IStatusLineManager statusLineManager
= getViewSite().getActionBars().getStatusLineManager();
861 fTimeGraphWrapper
.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager
);
863 // View Action Handling
865 contributeToActionBars();
867 ITmfTrace trace
= getActiveTrace();
869 traceSelected(new TmfTraceSelectedSignal(this, trace
));
872 // make selection available to other views
873 getSite().setSelectionProvider(fTimeGraphWrapper
.getSelectionProvider());
877 public void setFocus() {
878 fTimeGraphWrapper
.setFocus();
881 // ------------------------------------------------------------------------
883 // ------------------------------------------------------------------------
886 * Handler for the trace opened signal.
889 * The incoming signal
893 public void traceOpened(TmfTraceOpenedSignal signal
) {
894 fTrace
= signal
.getTrace();
899 * Handler for the trace selected signal
902 * The incoming signal
905 public void traceSelected(final TmfTraceSelectedSignal signal
) {
906 if (signal
.getTrace() == fTrace
) {
909 fTrace
= signal
.getTrace();
915 * Trace is closed: clear the data structures and the view
918 * the signal received
921 public void traceClosed(final TmfTraceClosedSignal signal
) {
922 synchronized (fBuildThreadMap
) {
923 for (ITmfTrace trace
: getTracesToBuild(signal
.getTrace())) {
924 BuildThread buildThread
= fBuildThreadMap
.remove(trace
);
925 if (buildThread
!= null) {
926 buildThread
.cancel();
930 synchronized (fEntryListMap
) {
931 fEntryListMap
.remove(signal
.getTrace());
933 if (signal
.getTrace() == fTrace
) {
937 if (fZoomThread
!= null) {
938 fZoomThread
.cancel();
945 * Handler for the time synch signal
948 * The signal that's received
951 public void synchToTime(final TmfTimeSynchSignal signal
) {
952 if (signal
.getSource() == this || fTrace
== null) {
955 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
956 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
958 Display
.getDefault().asyncExec(new Runnable() {
961 if (fTimeGraphWrapper
.isDisposed()) {
964 if (beginTime
== endTime
) {
965 fTimeGraphWrapper
.getTimeGraphViewer().setSelectedTime(beginTime
, true);
967 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(beginTime
, endTime
);
969 startZoomThread(fTimeGraphWrapper
.getTimeGraphViewer().getTime0(), fTimeGraphWrapper
.getTimeGraphViewer().getTime1());
971 synchingToTime(beginTime
);
977 * Handler for the range synch signal
980 * The signal that's received
983 public void synchToRange(final TmfRangeSynchSignal signal
) {
984 if (signal
.getSource() == this || fTrace
== null) {
987 if (signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange()) == null) {
990 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
991 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
992 Display
.getDefault().asyncExec(new Runnable() {
995 if (fTimeGraphWrapper
.isDisposed()) {
998 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
999 startZoomThread(startTime
, endTime
);
1005 * @param signal the format of the timestamps was updated.
1009 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal
){
1010 fTimeGraphWrapper
.refresh();
1013 // ------------------------------------------------------------------------
1015 // ------------------------------------------------------------------------
1017 private void loadTrace() {
1018 synchronized (fEntryListMap
) {
1019 fEntryList
= fEntryListMap
.get(fTrace
);
1020 if (fEntryList
== null) {
1023 fStartTime
= fTrace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1024 fEndTime
= fTrace
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1031 * Forces a rebuild of the entries list, even if entries already exist for this trace
1034 protected void rebuild() {
1035 setStartTime(Long
.MAX_VALUE
);
1036 setEndTime(Long
.MIN_VALUE
);
1037 synchronized (fBuildThreadMap
) {
1038 for (ITmfTrace trace
: getTracesToBuild(fTrace
)) {
1039 BuildThread buildThread
= new BuildThread(trace
, fTrace
, getName());
1040 fBuildThreadMap
.put(trace
, buildThread
);
1041 buildThread
.start();
1047 * Method called when synching to a given timestamp. Inheriting classes can
1048 * perform actions here to update the view at the given timestamp.
1051 * The currently selected time
1053 protected void synchingToTime(long time
) {
1058 * Return the list of traces whose data or analysis results will be used to
1059 * populate the view. By default, if the trace is an experiment, the traces
1060 * under it will be returned, otherwise, the trace itself is returned.
1062 * A build thread will be started for each trace returned by this method,
1063 * some of which may receive events in live streaming mode.
1066 * The trace associated with this view
1067 * @return List of traces with data to display
1070 protected Iterable
<ITmfTrace
> getTracesToBuild(ITmfTrace trace
) {
1071 return Arrays
.asList(TmfTraceManager
.getTraceSet(trace
));
1075 * Build the entries list to show in this time graph
1077 * Called from the BuildThread
1080 * The trace being built
1081 * @param parentTrace
1082 * The parent of the trace set, or the trace itself
1084 * The progress monitor object
1087 protected abstract void buildEventList(ITmfTrace trace
, ITmfTrace parentTrace
, IProgressMonitor monitor
);
1090 * Gets the list of event for an entry in a given timerange
1093 * The entry to get events for
1095 * Start of the time range
1097 * End of the time range
1101 * The progress monitor object
1102 * @return The list of events for the entry
1104 protected abstract @Nullable List
<ITimeEvent
> getEventList(TimeGraphEntry entry
,
1105 long startTime
, long endTime
, long resolution
,
1106 IProgressMonitor monitor
);
1109 * Gets the list of links (displayed as arrows) for a trace in a given
1110 * timerange. Default implementation returns an empty list.
1113 * Start of the time range
1115 * End of the time range
1119 * The progress monitor object
1120 * @return The list of link events
1123 protected List
<ILinkEvent
> getLinkList(long startTime
, long endTime
,
1124 long resolution
, IProgressMonitor monitor
) {
1125 return new ArrayList
<>();
1130 * Refresh the display
1132 protected void refresh() {
1133 Display
.getDefault().asyncExec(new Runnable() {
1136 if (fTimeGraphWrapper
.isDisposed()) {
1139 boolean hasEntries
= false;
1140 synchronized (fEntryListMap
) {
1141 fEntryList
= fEntryListMap
.get(fTrace
);
1142 if (fEntryList
== null) {
1143 fEntryList
= new CopyOnWriteArrayList
<>();
1144 } else if (fEntryComparator
!= null) {
1145 List
<TimeGraphEntry
> list
= new ArrayList
<>(fEntryList
);
1146 Collections
.sort(list
, fEntryComparator
);
1148 fEntryList
.addAll(list
);
1150 hasEntries
= fEntryList
.size() != 0;
1152 if (fEntryList
!= fTimeGraphWrapper
.getInput()) {
1153 fTimeGraphWrapper
.setInput(fEntryList
);
1155 fTimeGraphWrapper
.refresh();
1157 fTimeGraphWrapper
.getTimeGraphViewer().setTimeBounds(fStartTime
, fEndTime
);
1159 long selectionBeginTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1160 long selectionEndTime
= fTrace
== null ?
0 : fTraceManager
.getSelectionEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1161 long startTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1162 long endTime
= fTrace
== null ?
0 : fTraceManager
.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
1163 startTime
= Math
.max(startTime
, fStartTime
);
1164 endTime
= Math
.min(endTime
, fEndTime
);
1165 fTimeGraphWrapper
.getTimeGraphViewer().setSelectionRange(selectionBeginTime
, selectionEndTime
);
1166 fTimeGraphWrapper
.getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
1168 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
&& !fPackDone
) {
1169 for (TreeColumn column
: ((TimeGraphComboWrapper
) fTimeGraphWrapper
).getTreeViewer().getTree().getColumns()) {
1177 startZoomThread(startTime
, endTime
);
1185 protected void redraw() {
1186 synchronized (fSyncObj
) {
1187 if (fRedrawState
== State
.IDLE
) {
1188 fRedrawState
= State
.BUSY
;
1190 fRedrawState
= State
.PENDING
;
1194 Display
.getDefault().asyncExec(new Runnable() {
1197 if (fTimeGraphWrapper
.isDisposed()) {
1200 fTimeGraphWrapper
.redraw();
1201 fTimeGraphWrapper
.update();
1202 synchronized (fSyncObj
) {
1203 if (fRedrawState
== State
.PENDING
) {
1204 fRedrawState
= State
.IDLE
;
1207 fRedrawState
= State
.IDLE
;
1214 private void startZoomThread(long startTime
, long endTime
) {
1215 if (fZoomThread
!= null) {
1216 fZoomThread
.cancel();
1218 fZoomThread
= new ZoomThread(fEntryList
, startTime
, endTime
, getName());
1219 fZoomThread
.start();
1222 private void makeActions() {
1223 fPreviousResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getPreviousItemAction();
1224 fPreviousResourceAction
.setText(getPrevText());
1225 fPreviousResourceAction
.setToolTipText(getPrevTooltip());
1226 fNextResourceAction
= fTimeGraphWrapper
.getTimeGraphViewer().getNextItemAction();
1227 fNextResourceAction
.setText(getNextText());
1228 fNextResourceAction
.setToolTipText(getNextTooltip());
1231 private void contributeToActionBars() {
1232 IActionBars bars
= getViewSite().getActionBars();
1233 fillLocalToolBar(bars
.getToolBarManager());
1237 * Add actions to local tool bar manager
1239 * @param manager the tool bar manager
1241 protected void fillLocalToolBar(IToolBarManager manager
) {
1242 if (fTimeGraphWrapper
instanceof TimeGraphComboWrapper
) {
1243 if (fFilterColumns
!= null && fFilterLabelProvider
!= null && fFilterColumns
.length
> 0) {
1244 manager
.add(((TimeGraphComboWrapper
) fTimeGraphWrapper
).getShowFilterAction());
1247 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getShowLegendAction());
1248 manager
.add(new Separator());
1249 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getResetScaleAction());
1250 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getPreviousEventAction());
1251 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getNextEventAction());
1252 manager
.add(fPreviousResourceAction
);
1253 manager
.add(fNextResourceAction
);
1254 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomInAction());
1255 manager
.add(fTimeGraphWrapper
.getTimeGraphViewer().getZoomOutAction());
1256 manager
.add(new Separator());