tmf: TmfTraceManager improvements
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractTimeGraphView.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
3 *
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
8 *
9 * Contributors:
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 *******************************************************************************/
16
17 package org.eclipse.tracecompass.tmf.ui.views.timegraph;
18
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;
24 import java.util.Map;
25 import java.util.concurrent.CopyOnWriteArrayList;
26
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.ITreeContentProvider;
42 import org.eclipse.jface.viewers.TreeViewer;
43 import org.eclipse.jface.viewers.Viewer;
44 import org.eclipse.swt.SWT;
45 import org.eclipse.swt.graphics.Image;
46 import org.eclipse.swt.widgets.Composite;
47 import org.eclipse.swt.widgets.Display;
48 import org.eclipse.swt.widgets.TreeColumn;
49 import org.eclipse.tracecompass.tmf.core.signal.TmfRangeSynchSignal;
50 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
51 import org.eclipse.tracecompass.tmf.core.signal.TmfTimeSynchSignal;
52 import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
53 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
54 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
55 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
56 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
57 import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
58 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
59 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
60 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
61 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
62 import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
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.TimeGraphPresentationProvider;
71 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
72 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
73 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
74 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
75 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
76 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
77 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
78 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
79 import org.eclipse.ui.IActionBars;
80
81 /**
82 * An abstract view all time graph views can inherit
83 *
84 * This view contains either a time graph viewer, or a time graph combo which is
85 * divided between a tree viewer on the left and a time graph viewer on the right.
86 */
87 public abstract class AbstractTimeGraphView extends TmfView {
88
89 /** Constant indicating that all levels of the time graph should be expanded */
90 protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
91
92 /**
93 * Redraw state enum
94 */
95 private enum State {
96 IDLE, BUSY, PENDING
97 }
98
99 // ------------------------------------------------------------------------
100 // Fields
101 // ------------------------------------------------------------------------
102
103 /** The timegraph wrapper */
104 private ITimeGraphWrapper fTimeGraphWrapper;
105
106 /** The selected trace */
107 private ITmfTrace fTrace;
108
109 /** The timegraph entry list */
110 private List<TimeGraphEntry> fEntryList;
111
112 /** The trace to entry list hash map */
113 private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
114
115 /** The trace to build thread hash map */
116 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
117
118 /** The start time */
119 private long fStartTime;
120
121 /** The end time */
122 private long fEndTime;
123
124 /** The display width */
125 private final int fDisplayWidth;
126
127 /** The zoom thread */
128 private ZoomThread fZoomThread;
129
130 /** The next resource action */
131 private Action fNextResourceAction;
132
133 /** The previous resource action */
134 private Action fPreviousResourceAction;
135
136 /** A comparator class */
137 private Comparator<ITimeGraphEntry> fEntryComparator = null;
138
139 /** The redraw state used to prevent unnecessary queuing of display runnables */
140 private State fRedrawState = State.IDLE;
141
142 /** The redraw synchronization object */
143 private final Object fSyncObj = new Object();
144
145 /** The presentation provider for this view */
146 private final TimeGraphPresentationProvider fPresentation;
147
148 /** The tree column label array, or null if combo is not used */
149 private String[] fColumns;
150
151 /** The tree label provider, or null if combo is not used */
152 private TreeLabelProvider fLabelProvider = null;
153
154 /** The relative weight of the sash, ignored if combo is not used */
155 private int[] fWeight = { 1, 1 };
156
157 /** The filter column label array, or null if filter is not used */
158 private String[] fFilterColumns;
159
160 /** The pack done flag */
161 private boolean fPackDone = false;
162
163 /** The filter label provider, or null if filter is not used */
164 private TreeLabelProvider fFilterLabelProvider;
165
166 private int fAutoExpandLevel = ALL_LEVELS;
167
168 // ------------------------------------------------------------------------
169 // Classes
170 // ------------------------------------------------------------------------
171
172 private interface ITimeGraphWrapper {
173
174 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation);
175
176 TimeGraphViewer getTimeGraphViewer();
177
178 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener);
179
180 ISelectionProvider getSelectionProvider();
181
182 void setFocus();
183
184 boolean isDisposed();
185
186 void refresh();
187
188 void setInput(Object input);
189
190 Object getInput();
191
192 void redraw();
193
194 void update();
195
196 void setAutoExpandLevel(int level);
197
198 }
199
200 private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
201 private TimeGraphViewer viewer;
202
203 private TimeGraphViewerWrapper(Composite parent, int style) {
204 viewer = new TimeGraphViewer(parent, style);
205 }
206
207 @Override
208 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
209 viewer.setTimeGraphProvider(timeGraphProvider);
210 }
211
212 @Override
213 public TimeGraphViewer getTimeGraphViewer() {
214 return viewer;
215 }
216
217 @Override
218 public void addSelectionListener(ITimeGraphSelectionListener listener) {
219 viewer.addSelectionListener(listener);
220 }
221
222 @Override
223 public ISelectionProvider getSelectionProvider() {
224 return viewer.getSelectionProvider();
225 }
226
227 @Override
228 public void setFocus() {
229 viewer.setFocus();
230 }
231
232 @Override
233 public boolean isDisposed() {
234 return viewer.getControl().isDisposed();
235 }
236
237 @Override
238 public void setInput(Object input) {
239 viewer.setInput(input);
240 }
241
242 @Override
243 public Object getInput() {
244 return viewer.getInput();
245 }
246
247 @Override
248 public void refresh() {
249 viewer.refresh();
250 }
251
252 @Override
253 public void redraw() {
254 viewer.getControl().redraw();
255 }
256
257 @Override
258 public void update() {
259 viewer.getControl().update();
260 }
261
262 @Override
263 public void setAutoExpandLevel(int level) {
264 viewer.setAutoExpandLevel(level);
265 }
266 }
267
268 private class TimeGraphComboWrapper implements ITimeGraphWrapper {
269 private TimeGraphCombo combo;
270
271 private TimeGraphComboWrapper(Composite parent, int style) {
272 combo = new TimeGraphCombo(parent, style, fWeight);
273 }
274
275 @Override
276 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
277 combo.setTimeGraphProvider(timeGraphProvider);
278 }
279
280 @Override
281 public TimeGraphViewer getTimeGraphViewer() {
282 return combo.getTimeGraphViewer();
283 }
284
285 @Override
286 public void addSelectionListener(ITimeGraphSelectionListener listener) {
287 combo.addSelectionListener(listener);
288 }
289
290 @Override
291 public ISelectionProvider getSelectionProvider() {
292 return combo.getTreeViewer();
293 }
294
295 @Override
296 public void setFocus() {
297 combo.setFocus();
298 }
299
300 @Override
301 public boolean isDisposed() {
302 return combo.isDisposed();
303 }
304
305 @Override
306 public void setInput(Object input) {
307 combo.setInput(input);
308 }
309
310 @Override
311 public Object getInput() {
312 return combo.getInput();
313 }
314
315 @Override
316 public void refresh() {
317 combo.refresh();
318 }
319
320 @Override
321 public void redraw() {
322 combo.redraw();
323 }
324
325 @Override
326 public void update() {
327 combo.update();
328 }
329
330 @Override
331 public void setAutoExpandLevel(int level) {
332 combo.setAutoExpandLevel(level);
333 }
334
335 TimeGraphCombo getTimeGraphCombo() {
336 return combo;
337 }
338
339 TreeViewer getTreeViewer() {
340 return combo.getTreeViewer();
341 }
342
343 IAction getShowFilterAction() {
344 return combo.getShowFilterAction();
345 }
346 }
347
348 private class TreeContentProvider implements ITreeContentProvider {
349
350 @Override
351 public void dispose() {
352 }
353
354 @Override
355 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
356 }
357
358 @Override
359 public ITimeGraphEntry[] getElements(Object inputElement) {
360 if (inputElement != null) {
361 try {
362 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
363 } catch (ClassCastException e) {
364 }
365 }
366 return new ITimeGraphEntry[0];
367 }
368
369 @Override
370 public Object[] getChildren(Object parentElement) {
371 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
372 List<? extends ITimeGraphEntry> children = entry.getChildren();
373 return children.toArray(new ITimeGraphEntry[children.size()]);
374 }
375
376 @Override
377 public Object getParent(Object element) {
378 ITimeGraphEntry entry = (ITimeGraphEntry) element;
379 return entry.getParent();
380 }
381
382 @Override
383 public boolean hasChildren(Object element) {
384 ITimeGraphEntry entry = (ITimeGraphEntry) element;
385 return entry.hasChildren();
386 }
387
388 }
389
390 private class TimeGraphContentProvider implements ITimeGraphContentProvider {
391
392 @Override
393 public ITimeGraphEntry[] getElements(Object inputElement) {
394 if (inputElement != null) {
395 try {
396 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
397 } catch (ClassCastException e) {
398 }
399 }
400 return new ITimeGraphEntry[0];
401 }
402
403 }
404
405 /**
406 * Base class to provide the labels for the tree viewer. Views extending
407 * this class typically need to override the getColumnText method if they
408 * have more than one column to display
409 */
410 protected static class TreeLabelProvider implements ITableLabelProvider, ILabelProvider {
411
412 @Override
413 public void addListener(ILabelProviderListener listener) {
414 }
415
416 @Override
417 public void dispose() {
418 }
419
420 @Override
421 public boolean isLabelProperty(Object element, String property) {
422 return false;
423 }
424
425 @Override
426 public void removeListener(ILabelProviderListener listener) {
427 }
428
429 @Override
430 public Image getColumnImage(Object element, int columnIndex) {
431 return null;
432 }
433
434 @Override
435 public String getColumnText(Object element, int columnIndex) {
436 TimeGraphEntry entry = (TimeGraphEntry) element;
437 if (columnIndex == 0) {
438 return entry.getName();
439 }
440 return new String();
441 }
442
443 @Override
444 public Image getImage(Object element) {
445 return null;
446 }
447
448 @Override
449 public String getText(Object element) {
450 TimeGraphEntry entry = (TimeGraphEntry) element;
451 return entry.getName();
452 }
453
454 }
455
456 private class BuildThread extends Thread {
457 private final @NonNull ITmfTrace fBuildTrace;
458 private final @NonNull ITmfTrace fParentTrace;
459 private final @NonNull IProgressMonitor fMonitor;
460
461 public BuildThread(final @NonNull ITmfTrace trace, final @NonNull ITmfTrace parentTrace, final String name) {
462 super(name + " build"); //$NON-NLS-1$
463 fBuildTrace = trace;
464 fParentTrace = parentTrace;
465 fMonitor = new NullProgressMonitor();
466 }
467
468 @Override
469 public void run() {
470 buildEventList(fBuildTrace, fParentTrace, fMonitor);
471 synchronized (fBuildThreadMap) {
472 fBuildThreadMap.remove(fBuildTrace);
473 }
474 }
475
476 public void cancel() {
477 fMonitor.setCanceled(true);
478 }
479 }
480
481 private class ZoomThread extends Thread {
482 private final @NonNull List<TimeGraphEntry> fZoomEntryList;
483 private final long fZoomStartTime;
484 private final long fZoomEndTime;
485 private final long fResolution;
486 private final @NonNull IProgressMonitor fMonitor;
487
488 public ZoomThread(@NonNull List<TimeGraphEntry> entryList, long startTime, long endTime, String name) {
489 super(name + " zoom"); //$NON-NLS-1$
490 fZoomEntryList = entryList;
491 fZoomStartTime = startTime;
492 fZoomEndTime = endTime;
493 fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
494 fMonitor = new NullProgressMonitor();
495 }
496
497 @Override
498 public void run() {
499 for (TimeGraphEntry entry : fZoomEntryList) {
500 if (fMonitor.isCanceled()) {
501 return;
502 }
503 if (entry == null) {
504 break;
505 }
506 zoom(entry, fMonitor);
507 }
508 /* Refresh the arrows when zooming */
509 List<ILinkEvent> events = getLinkList(fZoomStartTime, fZoomEndTime, fResolution, fMonitor);
510 if (events != null) {
511 fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
512 redraw();
513 }
514 }
515
516 private void zoom(@NonNull TimeGraphEntry entry, @NonNull IProgressMonitor monitor) {
517 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
518 entry.setZoomedEventList(null);
519 } else {
520 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor);
521 if (zoomedEventList != null) {
522 entry.setZoomedEventList(zoomedEventList);
523 }
524 }
525 redraw();
526 for (ITimeGraphEntry child : entry.getChildren()) {
527 if (fMonitor.isCanceled()) {
528 return;
529 }
530 if (child instanceof TimeGraphEntry) {
531 zoom((TimeGraphEntry) child, monitor);
532 }
533 }
534 }
535
536 public void cancel() {
537 fMonitor.setCanceled(true);
538 }
539 }
540
541 // ------------------------------------------------------------------------
542 // Constructors
543 // ------------------------------------------------------------------------
544
545 /**
546 * Constructs a time graph view that contains either a time graph viewer or
547 * a time graph combo.
548 *
549 * By default, the view uses a time graph viewer. To use a time graph combo,
550 * the subclass constructor must call {@link #setTreeColumns(String[])} and
551 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
552 *
553 * @param id
554 * The id of the view
555 * @param pres
556 * The presentation provider
557 */
558 public AbstractTimeGraphView(String id, TimeGraphPresentationProvider pres) {
559 super(id);
560 fPresentation = pres;
561 fDisplayWidth = Display.getDefault().getBounds().width;
562 }
563
564 // ------------------------------------------------------------------------
565 // Getters and setters
566 // ------------------------------------------------------------------------
567
568 /**
569 * Getter for the time graph combo
570 *
571 * @return The time graph combo, or null if combo is not used
572 */
573 protected TimeGraphCombo getTimeGraphCombo() {
574 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
575 return ((TimeGraphComboWrapper) fTimeGraphWrapper).getTimeGraphCombo();
576 }
577 return null;
578 }
579
580 /**
581 * Getter for the time graph viewer
582 *
583 * @return The time graph viewer
584 */
585 protected TimeGraphViewer getTimeGraphViewer() {
586 return fTimeGraphWrapper.getTimeGraphViewer();
587 }
588
589 /**
590 * Getter for the presentation provider
591 *
592 * @return The time graph presentation provider
593 */
594 protected ITimeGraphPresentationProvider2 getPresentationProvider() {
595 return fPresentation;
596 }
597
598 /**
599 * Sets the tree column labels.
600 * This should be called from the constructor.
601 *
602 * @param columns
603 * The array of tree column labels
604 */
605 protected void setTreeColumns(final String[] columns) {
606 fColumns = columns;
607 }
608
609 /**
610 * Sets the tree label provider.
611 * This should be called from the constructor.
612 *
613 * @param tlp
614 * The tree label provider
615 */
616 protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
617 fLabelProvider = tlp;
618 }
619
620 /**
621 * Sets the relative weight of each part of the time graph combo.
622 * This should be called from the constructor.
623 *
624 * @param weights
625 * The array (length 2) of relative weights of each part of the combo
626 */
627 protected void setWeight(final int[] weights) {
628 fWeight = weights;
629 }
630
631 /**
632 * Sets the filter column labels.
633 * This should be called from the constructor.
634 *
635 * @param filterColumns
636 * The array of filter column labels
637 */
638 protected void setFilterColumns(final String[] filterColumns) {
639 fFilterColumns = filterColumns;
640 }
641
642 /**
643 * Sets the filter label provider.
644 * This should be called from the constructor.
645 *
646 * @param labelProvider
647 * The filter label provider
648 */
649 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
650 fFilterLabelProvider = labelProvider;
651 }
652
653 /**
654 * Gets the display width
655 *
656 * @return the display width
657 */
658 protected int getDisplayWidth() {
659 return fDisplayWidth;
660 }
661
662 /**
663 * Gets the comparator for the entries
664 *
665 * @return The entry comparator
666 */
667 protected Comparator<ITimeGraphEntry> getEntryComparator() {
668 return fEntryComparator;
669 }
670
671 /**
672 * Sets the comparator class for the entries
673 *
674 * @param comparator
675 * A comparator object
676 */
677 protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) {
678 fEntryComparator = comparator;
679 }
680
681 /**
682 * Gets the trace displayed in the view
683 *
684 * @return The trace
685 */
686 protected ITmfTrace getTrace() {
687 return fTrace;
688 }
689
690 /**
691 * Gets the start time
692 *
693 * @return The start time
694 */
695 protected long getStartTime() {
696 return fStartTime;
697 }
698
699 /**
700 * Sets the start time
701 *
702 * @param time
703 * The start time
704 */
705 protected void setStartTime(long time) {
706 fStartTime = time;
707 }
708
709 /**
710 * Gets the end time
711 *
712 * @return The end time
713 */
714 protected long getEndTime() {
715 return fEndTime;
716 }
717
718 /**
719 * Sets the end time
720 *
721 * @param time
722 * The end time
723 */
724 protected void setEndTime(long time) {
725 fEndTime = time;
726 }
727
728 /**
729 * Sets the auto-expand level to be used for the input of the view. The
730 * value 0 means that there is no auto-expand; 1 means that top-level
731 * elements are expanded, but not their children; 2 means that top-level
732 * elements are expanded, and their children, but not grand-children; and so
733 * on.
734 * <p>
735 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
736 * </p>
737 *
738 * @param level
739 * non-negative level, or <code>ALL_LEVELS</code> to expand all
740 * levels of the tree
741 */
742 protected void setAutoExpandLevel(int level) {
743 fAutoExpandLevel = level;
744 ITimeGraphWrapper tgWrapper = fTimeGraphWrapper;
745 if (tgWrapper != null) {
746 tgWrapper.setAutoExpandLevel(level);
747 }
748 }
749
750 /**
751 * Gets the entry list for a trace
752 *
753 * @param trace
754 * the trace
755 *
756 * @return the entry list map
757 */
758 protected List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
759 synchronized (fEntryListMap) {
760 return fEntryListMap.get(trace);
761 }
762 }
763
764 /**
765 * Adds a trace entry list to the entry list map
766 *
767 * @param trace
768 * the trace to add
769 * @param list
770 * the list of time graph entries
771 */
772 protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
773 synchronized (fEntryListMap) {
774 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
775 }
776 }
777
778 /**
779 * Adds a list of entries to a trace's entry list
780 *
781 * @param trace
782 * the trace
783 * @param list
784 * the list of time graph entries to add
785 */
786 protected void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
787 synchronized (fEntryListMap) {
788 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
789 if (entryList == null) {
790 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
791 } else {
792 entryList.addAll(list);
793 }
794 }
795 }
796
797 /**
798 * Removes a list of entries from a trace's entry list
799 *
800 * @param trace
801 * the trace
802 * @param list
803 * the list of time graph entries to remove
804 */
805 protected void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
806 synchronized (fEntryListMap) {
807 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
808 if (entryList != null) {
809 entryList.removeAll(list);
810 }
811 }
812 }
813
814 /**
815 * Text for the "next" button
816 *
817 * @return The "next" button text
818 */
819 protected String getNextText() {
820 return Messages.AbstractTimeGraphtView_NextText;
821 }
822
823 /**
824 * Tooltip for the "next" button
825 *
826 * @return Tooltip for the "next" button
827 */
828 protected String getNextTooltip() {
829 return Messages.AbstractTimeGraphView_NextTooltip;
830 }
831
832 /**
833 * Text for the "Previous" button
834 *
835 * @return The "Previous" button text
836 */
837 protected String getPrevText() {
838 return Messages.AbstractTimeGraphView_PreviousText;
839 }
840
841 /**
842 * Tooltip for the "previous" button
843 *
844 * @return Tooltip for the "previous" button
845 */
846 protected String getPrevTooltip() {
847 return Messages.AbstractTimeGraphView_PreviousTooltip;
848 }
849
850 // ------------------------------------------------------------------------
851 // ViewPart
852 // ------------------------------------------------------------------------
853
854 @Override
855 public void createPartControl(Composite parent) {
856 if (fColumns == null || fLabelProvider == null) {
857 fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
858 TimeGraphViewer viewer = fTimeGraphWrapper.getTimeGraphViewer();
859 viewer.setTimeGraphContentProvider(new TimeGraphContentProvider());
860 } else {
861 TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
862 fTimeGraphWrapper = wrapper;
863 TimeGraphCombo combo = wrapper.getTimeGraphCombo();
864 combo.setTreeContentProvider(new TreeContentProvider());
865 combo.setTreeLabelProvider(fLabelProvider);
866 combo.setTreeColumns(fColumns);
867 combo.setFilterContentProvider(new TreeContentProvider());
868 combo.setFilterLabelProvider(fFilterLabelProvider);
869 combo.setFilterColumns(fFilterColumns);
870 combo.setTimeGraphContentProvider(new TimeGraphContentProvider());
871 }
872
873 fTimeGraphWrapper.setTimeGraphProvider(fPresentation);
874 fTimeGraphWrapper.setAutoExpandLevel(fAutoExpandLevel);
875
876 fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
877 @Override
878 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
879 final long startTime = event.getStartTime();
880 final long endTime = event.getEndTime();
881 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
882 broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView.this, range));
883 startZoomThread(startTime, endTime);
884 }
885 });
886
887 fTimeGraphWrapper.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
888 @Override
889 public void timeSelected(TimeGraphTimeEvent event) {
890 TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime());
891 TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime());
892 broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView.this, startTime, endTime));
893 }
894 });
895
896 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
897
898 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
899 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
900
901 // View Action Handling
902 makeActions();
903 contributeToActionBars();
904
905 ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
906 if (trace != null) {
907 traceSelected(new TmfTraceSelectedSignal(this, trace));
908 }
909
910 // make selection available to other views
911 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
912 }
913
914 @Override
915 public void setFocus() {
916 fTimeGraphWrapper.setFocus();
917 }
918
919 // ------------------------------------------------------------------------
920 // Signal handlers
921 // ------------------------------------------------------------------------
922
923 /**
924 * Handler for the trace opened signal.
925 *
926 * @param signal
927 * The incoming signal
928 */
929 @TmfSignalHandler
930 public void traceOpened(TmfTraceOpenedSignal signal) {
931 fTrace = signal.getTrace();
932 loadTrace();
933 }
934
935 /**
936 * Handler for the trace selected signal
937 *
938 * @param signal
939 * The incoming signal
940 */
941 @TmfSignalHandler
942 public void traceSelected(final TmfTraceSelectedSignal signal) {
943 if (signal.getTrace() == fTrace) {
944 return;
945 }
946 fTrace = signal.getTrace();
947
948 loadTrace();
949 }
950
951 /**
952 * Trace is closed: clear the data structures and the view
953 *
954 * @param signal
955 * the signal received
956 */
957 @TmfSignalHandler
958 public void traceClosed(final TmfTraceClosedSignal signal) {
959 synchronized (fBuildThreadMap) {
960 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
961 BuildThread buildThread = fBuildThreadMap.remove(trace);
962 if (buildThread != null) {
963 buildThread.cancel();
964 }
965 }
966 }
967 synchronized (fEntryListMap) {
968 fEntryListMap.remove(signal.getTrace());
969 }
970 if (signal.getTrace() == fTrace) {
971 fTrace = null;
972 fStartTime = 0;
973 fEndTime = 0;
974 if (fZoomThread != null) {
975 fZoomThread.cancel();
976 }
977 refresh();
978 }
979 }
980
981 /**
982 * Handler for the time synch signal
983 *
984 * @param signal
985 * The signal that's received
986 */
987 @TmfSignalHandler
988 public void synchToTime(final TmfTimeSynchSignal signal) {
989 if (signal.getSource() == this || fTrace == null) {
990 return;
991 }
992 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
993 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
994
995 Display.getDefault().asyncExec(new Runnable() {
996 @Override
997 public void run() {
998 if (fTimeGraphWrapper.isDisposed()) {
999 return;
1000 }
1001 if (beginTime == endTime) {
1002 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
1003 } else {
1004 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
1005 }
1006 startZoomThread(fTimeGraphWrapper.getTimeGraphViewer().getTime0(), fTimeGraphWrapper.getTimeGraphViewer().getTime1());
1007
1008 synchingToTime(beginTime);
1009 }
1010 });
1011 }
1012
1013 /**
1014 * Handler for the range synch signal
1015 *
1016 * @param signal
1017 * The signal that's received
1018 */
1019 @TmfSignalHandler
1020 public void synchToRange(final TmfRangeSynchSignal signal) {
1021 if (signal.getSource() == this || fTrace == null) {
1022 return;
1023 }
1024 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1025 return;
1026 }
1027 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1028 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1029 Display.getDefault().asyncExec(new Runnable() {
1030 @Override
1031 public void run() {
1032 if (fTimeGraphWrapper.isDisposed()) {
1033 return;
1034 }
1035 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1036 startZoomThread(startTime, endTime);
1037 }
1038 });
1039 }
1040
1041 /**
1042 * @param signal the format of the timestamps was updated.
1043 */
1044 @TmfSignalHandler
1045 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
1046 fTimeGraphWrapper.refresh();
1047 }
1048
1049 // ------------------------------------------------------------------------
1050 // Internal
1051 // ------------------------------------------------------------------------
1052
1053 private void loadTrace() {
1054 synchronized (fEntryListMap) {
1055 fEntryList = fEntryListMap.get(fTrace);
1056 if (fEntryList == null) {
1057 rebuild();
1058 } else {
1059 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1060 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1061 refresh();
1062 }
1063 }
1064 }
1065
1066 /**
1067 * Forces a rebuild of the entries list, even if entries already exist for this trace
1068 */
1069 protected void rebuild() {
1070 setStartTime(Long.MAX_VALUE);
1071 setEndTime(Long.MIN_VALUE);
1072 refresh();
1073 ITmfTrace viewTrace = fTrace;
1074 if (viewTrace == null) {
1075 return;
1076 }
1077 synchronized (fBuildThreadMap) {
1078 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1079 if (trace == null) {
1080 break;
1081 }
1082 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
1083 fBuildThreadMap.put(trace, buildThread);
1084 buildThread.start();
1085 }
1086 }
1087 }
1088
1089 /**
1090 * Method called when synching to a given timestamp. Inheriting classes can
1091 * perform actions here to update the view at the given timestamp.
1092 *
1093 * @param time
1094 * The currently selected time
1095 */
1096 protected void synchingToTime(long time) {
1097
1098 }
1099
1100 /**
1101 * Return the list of traces whose data or analysis results will be used to
1102 * populate the view. By default, if the trace is an experiment, the traces
1103 * under it will be returned, otherwise, the trace itself is returned.
1104 *
1105 * A build thread will be started for each trace returned by this method,
1106 * some of which may receive events in live streaming mode.
1107 *
1108 * @param trace
1109 * The trace associated with this view
1110 * @return List of traces with data to display
1111 */
1112 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
1113 return TmfTraceManager.getTraceSet(trace);
1114 }
1115
1116 /**
1117 * Build the entries list to show in this time graph
1118 *
1119 * Called from the BuildThread
1120 *
1121 * @param trace
1122 * The trace being built
1123 * @param parentTrace
1124 * The parent of the trace set, or the trace itself
1125 * @param monitor
1126 * The progress monitor object
1127 */
1128 protected abstract void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
1129
1130 /**
1131 * Gets the list of event for an entry in a given timerange
1132 *
1133 * @param entry
1134 * The entry to get events for
1135 * @param startTime
1136 * Start of the time range
1137 * @param endTime
1138 * End of the time range
1139 * @param resolution
1140 * The resolution
1141 * @param monitor
1142 * The progress monitor object
1143 * @return The list of events for the entry
1144 */
1145 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
1146 long startTime, long endTime, long resolution,
1147 @NonNull IProgressMonitor monitor);
1148
1149 /**
1150 * Gets the list of links (displayed as arrows) for a trace in a given
1151 * timerange. Default implementation returns an empty list.
1152 *
1153 * @param startTime
1154 * Start of the time range
1155 * @param endTime
1156 * End of the time range
1157 * @param resolution
1158 * The resolution
1159 * @param monitor
1160 * The progress monitor object
1161 * @return The list of link events
1162 */
1163 protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime,
1164 long resolution, @NonNull IProgressMonitor monitor) {
1165 return new ArrayList<>();
1166 }
1167
1168
1169 /**
1170 * Refresh the display
1171 */
1172 protected void refresh() {
1173 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
1174 @Override
1175 public void run() {
1176 if (fTimeGraphWrapper.isDisposed()) {
1177 return;
1178 }
1179 boolean hasEntries = false;
1180 synchronized (fEntryListMap) {
1181 fEntryList = fEntryListMap.get(fTrace);
1182 if (fEntryList == null) {
1183 fEntryList = new CopyOnWriteArrayList<>();
1184 } else if (fEntryComparator != null) {
1185 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1186 Collections.sort(list, fEntryComparator);
1187 fEntryList.clear();
1188 fEntryList.addAll(list);
1189 }
1190 hasEntries = fEntryList.size() != 0;
1191 }
1192 if (fEntryList != fTimeGraphWrapper.getInput()) {
1193 fTimeGraphWrapper.setInput(fEntryList);
1194 } else {
1195 fTimeGraphWrapper.refresh();
1196 }
1197 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
1198
1199 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
1200 long selectionBeginTime = fTrace == null ? 0 : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1201 long selectionEndTime = fTrace == null ? 0 : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1202 long startTime = fTrace == null ? 0 : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1203 long endTime = fTrace == null ? 0 : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1204 startTime = Math.max(startTime, fStartTime);
1205 endTime = Math.min(endTime, fEndTime);
1206 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1207 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1208
1209 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
1210 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1211 column.pack();
1212 }
1213 if (hasEntries) {
1214 fPackDone = true;
1215 }
1216 }
1217
1218 startZoomThread(startTime, endTime);
1219 }
1220 });
1221 }
1222
1223 /**
1224 * Redraw the canvas
1225 */
1226 protected void redraw() {
1227 synchronized (fSyncObj) {
1228 if (fRedrawState == State.IDLE) {
1229 fRedrawState = State.BUSY;
1230 } else {
1231 fRedrawState = State.PENDING;
1232 return;
1233 }
1234 }
1235 Display.getDefault().asyncExec(new Runnable() {
1236 @Override
1237 public void run() {
1238 if (fTimeGraphWrapper.isDisposed()) {
1239 return;
1240 }
1241 fTimeGraphWrapper.redraw();
1242 fTimeGraphWrapper.update();
1243 synchronized (fSyncObj) {
1244 if (fRedrawState == State.PENDING) {
1245 fRedrawState = State.IDLE;
1246 redraw();
1247 } else {
1248 fRedrawState = State.IDLE;
1249 }
1250 }
1251 }
1252 });
1253 }
1254
1255 private void startZoomThread(long startTime, long endTime) {
1256 if (fZoomThread != null) {
1257 fZoomThread.cancel();
1258 }
1259 final List<TimeGraphEntry> entryList = fEntryList;
1260 if (entryList == null) {
1261 return;
1262 }
1263 fZoomThread = new ZoomThread(entryList, startTime, endTime, getName());
1264 fZoomThread.start();
1265 }
1266
1267 private void makeActions() {
1268 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
1269 fPreviousResourceAction.setText(getPrevText());
1270 fPreviousResourceAction.setToolTipText(getPrevTooltip());
1271 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
1272 fNextResourceAction.setText(getNextText());
1273 fNextResourceAction.setToolTipText(getNextTooltip());
1274 }
1275
1276 private void contributeToActionBars() {
1277 IActionBars bars = getViewSite().getActionBars();
1278 fillLocalToolBar(bars.getToolBarManager());
1279 }
1280
1281 /**
1282 * Add actions to local tool bar manager
1283 *
1284 * @param manager the tool bar manager
1285 */
1286 protected void fillLocalToolBar(IToolBarManager manager) {
1287 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
1288 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
1289 manager.add(((TimeGraphComboWrapper) fTimeGraphWrapper).getShowFilterAction());
1290 }
1291 }
1292 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
1293 manager.add(new Separator());
1294 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1295 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1296 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
1297 manager.add(fPreviousResourceAction);
1298 manager.add(fNextResourceAction);
1299 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1300 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
1301 manager.add(new Separator());
1302 }
1303 }
This page took 0.087228 seconds and 5 git commands to generate.