79b67cfa9762fd9843ee32e88f47cba6f0d42fc1
[deliverable/tracecompass.git] / tmf / 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 static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.concurrent.CopyOnWriteArrayList;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 import org.eclipse.core.resources.IFile;
34 import org.eclipse.core.resources.IMarker;
35 import org.eclipse.core.resources.IMarkerDelta;
36 import org.eclipse.core.resources.IResource;
37 import org.eclipse.core.resources.IResourceChangeEvent;
38 import org.eclipse.core.resources.IResourceChangeListener;
39 import org.eclipse.core.resources.IWorkspaceRunnable;
40 import org.eclipse.core.resources.ResourcesPlugin;
41 import org.eclipse.core.runtime.CoreException;
42 import org.eclipse.core.runtime.IProgressMonitor;
43 import org.eclipse.core.runtime.NullProgressMonitor;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.eclipse.jdt.annotation.Nullable;
46 import org.eclipse.jface.action.Action;
47 import org.eclipse.jface.action.IAction;
48 import org.eclipse.jface.action.IMenuManager;
49 import org.eclipse.jface.action.IStatusLineManager;
50 import org.eclipse.jface.action.IToolBarManager;
51 import org.eclipse.jface.action.Separator;
52 import org.eclipse.jface.viewers.AbstractTreeViewer;
53 import org.eclipse.jface.viewers.ILabelProvider;
54 import org.eclipse.jface.viewers.ILabelProviderListener;
55 import org.eclipse.jface.viewers.ISelectionProvider;
56 import org.eclipse.jface.viewers.ITableLabelProvider;
57 import org.eclipse.jface.viewers.ITreeContentProvider;
58 import org.eclipse.jface.viewers.TreeViewer;
59 import org.eclipse.jface.viewers.ViewerFilter;
60 import org.eclipse.osgi.util.NLS;
61 import org.eclipse.swt.SWT;
62 import org.eclipse.swt.graphics.Color;
63 import org.eclipse.swt.graphics.Image;
64 import org.eclipse.swt.widgets.Composite;
65 import org.eclipse.swt.widgets.Display;
66 import org.eclipse.swt.widgets.TreeColumn;
67 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
68 import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker;
69 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
70 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
71 import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
72 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
73 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
74 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
75 import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
76 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
77 import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
78 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
79 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
80 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceAdapterManager;
81 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
82 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
83 import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
84 import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
85 import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
86 import org.eclipse.tracecompass.tmf.ui.views.TmfView;
87 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphBookmarkListener;
88 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
89 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
90 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
91 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
92 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
93 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphBookmarkEvent;
94 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
95 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
96 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
97 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
98 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
99 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
100 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
101 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
102 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEventSource;
103 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
104 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
105 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
106 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
107 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
108 import org.eclipse.ui.IActionBars;
109
110 /**
111 * An abstract view all time graph views can inherit
112 *
113 * This view contains either a time graph viewer, or a time graph combo which is
114 * divided between a tree viewer on the left and a time graph viewer on the right.
115 */
116 public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeAligned, IResourceChangeListener {
117
118 /** Constant indicating that all levels of the time graph should be expanded */
119 protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
120
121 private static final Pattern RGBA_PATTERN = Pattern.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
122
123 /**
124 * Redraw state enum
125 */
126 private enum State {
127 IDLE, BUSY, PENDING
128 }
129
130 // ------------------------------------------------------------------------
131 // Fields
132 // ------------------------------------------------------------------------
133
134 /** The timegraph wrapper */
135 private ITimeGraphWrapper fTimeGraphWrapper;
136
137 /** The selected trace */
138 private ITmfTrace fTrace;
139
140 /** The selected trace editor file*/
141 private IFile fEditorFile;
142
143 /** The timegraph entry list */
144 private List<TimeGraphEntry> fEntryList;
145
146 /** The trace to entry list hash map */
147 private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
148
149 /** The trace to filters hash map */
150 private final Map<ITmfTrace, ViewerFilter[]> fFiltersMap = new HashMap<>();
151
152 /** The trace to marker event sources hash map */
153 private final Map<ITmfTrace, List<IMarkerEventSource>> fMarkerEventSourcesMap = new HashMap<>();
154
155 /** The trace to build thread hash map */
156 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
157
158 /** The start time */
159 private long fStartTime = SWT.DEFAULT;
160
161 /** The end time */
162 private long fEndTime = SWT.DEFAULT;
163
164 /** The display width */
165 private final int fDisplayWidth;
166
167 /** The zoom thread */
168 private ZoomThread fZoomThread;
169
170 /** The next resource action */
171 private Action fNextResourceAction;
172
173 /** The previous resource action */
174 private Action fPreviousResourceAction;
175
176 /** A comparator class */
177 private Comparator<ITimeGraphEntry> fEntryComparator = null;
178
179 /** The redraw state used to prevent unnecessary queuing of display runnables */
180 private State fRedrawState = State.IDLE;
181
182 /** The redraw synchronization object */
183 private final Object fSyncObj = new Object();
184
185 /** The presentation provider for this view */
186 private final TimeGraphPresentationProvider fPresentation;
187
188 /** The tree column label array, or null if combo is not used */
189 private String[] fColumns;
190
191 /** The tree label provider, or null if combo is not used */
192 private TreeLabelProvider fLabelProvider = null;
193
194 /** The time graph content provider */
195 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider = new TimeGraphContentProvider();
196
197 /** The relative weight of the sash, ignored if combo is not used */
198 private int[] fWeight = { 1, 3 };
199
200 /** The filter column label array, or null if filter is not used */
201 private String[] fFilterColumns;
202
203 /** The pack done flag */
204 private boolean fPackDone = false;
205
206 /** The filter label provider, or null if filter is not used */
207 private TreeLabelProvider fFilterLabelProvider;
208
209 private int fAutoExpandLevel = ALL_LEVELS;
210
211 /** The list of color resources created by this view */
212 private final List<Color> fColors = new ArrayList<>();
213
214 // ------------------------------------------------------------------------
215 // Classes
216 // ------------------------------------------------------------------------
217
218 private interface ITimeGraphWrapper {
219
220 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider);
221
222 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider);
223
224 TimeGraphViewer getTimeGraphViewer();
225
226 void addSelectionListener(ITimeGraphSelectionListener listener);
227
228 ISelectionProvider getSelectionProvider();
229
230 void setFocus();
231
232 boolean isDisposed();
233
234 void refresh();
235
236 void setInput(Object input);
237
238 Object getInput();
239
240 void setFilters(ViewerFilter[] filters);
241
242 ViewerFilter[] getFilters();
243
244 void redraw();
245
246 void update();
247
248 void setAutoExpandLevel(int level);
249
250 void setFilterColumns(String[] columnNames);
251
252 void setFilterContentProvider(ITreeContentProvider contentProvider);
253
254 void setFilterLabelProvider(ITableLabelProvider labelProvider);
255
256 IAction getShowFilterDialogAction();
257
258 void performAlign(int offset, int width);
259
260 TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo();
261
262 int getAvailableWidth(int requestedOffset);
263 }
264
265 private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
266 private TimeGraphViewer viewer;
267
268 private TimeGraphViewerWrapper(Composite parent, int style) {
269 viewer = new TimeGraphViewer(parent, style);
270 }
271
272 @Override
273 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
274 viewer.setTimeGraphContentProvider(timeGraphContentProvider);
275 }
276
277 @Override
278 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
279 viewer.setTimeGraphProvider(timeGraphPresentationProvider);
280 }
281
282 @Override
283 public TimeGraphViewer getTimeGraphViewer() {
284 return viewer;
285 }
286
287 @Override
288 public void addSelectionListener(ITimeGraphSelectionListener listener) {
289 viewer.addSelectionListener(listener);
290 }
291
292 @Override
293 public ISelectionProvider getSelectionProvider() {
294 return viewer.getSelectionProvider();
295 }
296
297 @Override
298 public void setFocus() {
299 viewer.setFocus();
300 }
301
302 @Override
303 public boolean isDisposed() {
304 return viewer.getControl().isDisposed();
305 }
306
307 @Override
308 public void setInput(Object input) {
309 viewer.setInput(input);
310 }
311
312 @Override
313 public Object getInput() {
314 return viewer.getInput();
315 }
316
317 @Override
318 public void setFilterColumns(String[] columnNames) {
319 viewer.setFilterColumns(columnNames);
320 }
321
322 @Override
323 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
324 viewer.setFilterContentProvider(contentProvider);
325 }
326
327 @Override
328 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
329 viewer.setFilterLabelProvider(labelProvider);
330 }
331
332 @Override
333 public void setFilters(ViewerFilter[] filters) {
334 viewer.setFilters(filters);
335 }
336
337 @Override
338 public ViewerFilter[] getFilters() {
339 return viewer.getFilters();
340 }
341
342 @Override
343 public IAction getShowFilterDialogAction() {
344 return viewer.getShowFilterDialogAction();
345 }
346
347 @Override
348 public void refresh() {
349 viewer.refresh();
350 }
351
352 @Override
353 public void redraw() {
354 viewer.getControl().redraw();
355 }
356
357 @Override
358 public void update() {
359 viewer.getControl().update();
360 }
361
362 @Override
363 public void setAutoExpandLevel(int level) {
364 viewer.setAutoExpandLevel(level);
365 }
366
367 @Override
368 public void performAlign(int offset, int width) {
369 viewer.performAlign(offset, width);
370 }
371
372 @Override
373 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
374 return viewer.getTimeViewAlignmentInfo();
375 }
376
377 @Override
378 public int getAvailableWidth(int requestedOffset) {
379 return viewer.getAvailableWidth(requestedOffset);
380 }
381 }
382
383 private class TimeGraphComboWrapper implements ITimeGraphWrapper {
384 private TimeGraphCombo combo;
385
386 private TimeGraphComboWrapper(Composite parent, int style) {
387 combo = new TimeGraphCombo(parent, style, fWeight);
388 }
389
390 @Override
391 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
392 combo.setTimeGraphContentProvider(timeGraphContentProvider);
393 }
394
395 @Override
396 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
397 combo.setTimeGraphProvider(timeGraphPresentationProvider);
398 }
399
400 @Override
401 public TimeGraphViewer getTimeGraphViewer() {
402 return combo.getTimeGraphViewer();
403 }
404
405 @Override
406 public void addSelectionListener(ITimeGraphSelectionListener listener) {
407 combo.addSelectionListener(listener);
408 }
409
410 @Override
411 public ISelectionProvider getSelectionProvider() {
412 return combo.getTreeViewer();
413 }
414
415 @Override
416 public void setFocus() {
417 combo.setFocus();
418 }
419
420 @Override
421 public boolean isDisposed() {
422 return combo.isDisposed();
423 }
424
425 @Override
426 public void setInput(Object input) {
427 combo.setInput(input);
428 }
429
430 @Override
431 public Object getInput() {
432 return combo.getInput();
433 }
434
435 @Override
436 public void setFilterColumns(String[] columnNames) {
437 combo.setFilterColumns(columnNames);
438 }
439
440 @Override
441 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
442 combo.setFilterContentProvider(contentProvider);
443 }
444
445 @Override
446 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
447 combo.setFilterLabelProvider(labelProvider);
448 }
449
450 @Override
451 public void setFilters(ViewerFilter[] filters) {
452 combo.setFilters(filters);
453 }
454
455 @Override
456 public ViewerFilter[] getFilters() {
457 return combo.getFilters();
458 }
459
460 @Override
461 public IAction getShowFilterDialogAction() {
462 return combo.getShowFilterDialogAction();
463 }
464
465 @Override
466 public void refresh() {
467 combo.refresh();
468 }
469
470 @Override
471 public void redraw() {
472 combo.redraw();
473 }
474
475 @Override
476 public void update() {
477 combo.update();
478 }
479
480 @Override
481 public void setAutoExpandLevel(int level) {
482 combo.setAutoExpandLevel(level);
483 }
484
485 TimeGraphCombo getTimeGraphCombo() {
486 return combo;
487 }
488
489 TreeViewer getTreeViewer() {
490 return combo.getTreeViewer();
491 }
492
493 @Override
494 public void performAlign(int offset, int width) {
495 combo.performAlign(offset, width);
496 }
497
498 @Override
499 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
500 return combo.getTimeViewAlignmentInfo();
501 }
502
503 @Override
504 public int getAvailableWidth(int requestedOffset) {
505 return combo.getAvailableWidth(requestedOffset);
506 }
507 }
508
509 /**
510 * Base class to provide the labels for the tree viewer. Views extending
511 * this class typically need to override the getColumnText method if they
512 * have more than one column to display
513 */
514 protected static class TreeLabelProvider implements ITableLabelProvider, ILabelProvider {
515
516 @Override
517 public void addListener(ILabelProviderListener listener) {
518 }
519
520 @Override
521 public void dispose() {
522 }
523
524 @Override
525 public boolean isLabelProperty(Object element, String property) {
526 return false;
527 }
528
529 @Override
530 public void removeListener(ILabelProviderListener listener) {
531 }
532
533 @Override
534 public Image getColumnImage(Object element, int columnIndex) {
535 return null;
536 }
537
538 @Override
539 public String getColumnText(Object element, int columnIndex) {
540 TimeGraphEntry entry = (TimeGraphEntry) element;
541 if (columnIndex == 0) {
542 return entry.getName();
543 }
544 return new String();
545 }
546
547 @Override
548 public Image getImage(Object element) {
549 return null;
550 }
551
552 @Override
553 public String getText(Object element) {
554 TimeGraphEntry entry = (TimeGraphEntry) element;
555 return entry.getName();
556 }
557
558 }
559
560 private class BuildThread extends Thread {
561 private final @NonNull ITmfTrace fBuildTrace;
562 private final @NonNull ITmfTrace fParentTrace;
563 private final @NonNull IProgressMonitor fMonitor;
564
565 public BuildThread(final @NonNull ITmfTrace trace, final @NonNull ITmfTrace parentTrace, final String name) {
566 super(name + " build"); //$NON-NLS-1$
567 fBuildTrace = trace;
568 fParentTrace = parentTrace;
569 fMonitor = new NullProgressMonitor();
570 }
571
572 @Override
573 public void run() {
574 buildEventList(fBuildTrace, fParentTrace, fMonitor);
575 synchronized (fBuildThreadMap) {
576 fBuildThreadMap.remove(fBuildTrace);
577 }
578 }
579
580 public void cancel() {
581 fMonitor.setCanceled(true);
582 }
583 }
584
585 /**
586 * Zoom thread
587 * @since 1.1
588 */
589 protected abstract class ZoomThread extends Thread {
590 private final long fZoomStartTime;
591 private final long fZoomEndTime;
592 private final long fResolution;
593 private final @NonNull IProgressMonitor fMonitor;
594
595 /**
596 * Constructor
597 *
598 * @param startTime
599 * the start time
600 * @param endTime
601 * the end time
602 * @param resolution
603 * the resolution
604 */
605 public ZoomThread(long startTime, long endTime, long resolution) {
606 super(AbstractTimeGraphView.this.getName() + " zoom"); //$NON-NLS-1$
607 fZoomStartTime = startTime;
608 fZoomEndTime = endTime;
609 fResolution = resolution;
610 fMonitor = new NullProgressMonitor();
611 }
612
613 /**
614 * @return the zoom start time
615 */
616 public long getZoomStartTime() {
617 return fZoomStartTime;
618 }
619
620 /**
621 * @return the zoom end time
622 */
623 public long getZoomEndTime() {
624 return fZoomEndTime;
625 }
626
627 /**
628 * @return the resolution
629 */
630 public long getResolution() {
631 return fResolution;
632 }
633
634 /**
635 * @return the monitor
636 */
637 public @NonNull IProgressMonitor getMonitor() {
638 return fMonitor;
639 }
640
641 /**
642 * Cancel the zoom thread
643 */
644 public void cancel() {
645 fMonitor.setCanceled(true);
646 }
647 }
648
649 private class ZoomThreadByEntry extends ZoomThread {
650 private final @NonNull List<TimeGraphEntry> fZoomEntryList;
651
652 public ZoomThreadByEntry(@NonNull List<TimeGraphEntry> entryList, long startTime, long endTime, long resolution) {
653 super(startTime, endTime, resolution);
654 fZoomEntryList = entryList;
655 }
656
657 @Override
658 public void run() {
659 for (TimeGraphEntry entry : fZoomEntryList) {
660 if (getMonitor().isCanceled()) {
661 return;
662 }
663 if (entry == null) {
664 break;
665 }
666 zoom(entry, getMonitor());
667 }
668 /* Refresh the arrows when zooming */
669 List<ILinkEvent> events = getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
670 if (events != null) {
671 fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
672 redraw();
673 }
674 /* Refresh the view-specific markers when zooming */
675 List<IMarkerEvent> markers = new ArrayList<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
676 /* Refresh the trace-specific markers when zooming */
677 markers.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
678 fTimeGraphWrapper.getTimeGraphViewer().setMarkers(markers);
679 redraw();
680 }
681
682 private void zoom(@NonNull TimeGraphEntry entry, @NonNull IProgressMonitor monitor) {
683 if (getZoomStartTime() <= fStartTime && getZoomEndTime() >= fEndTime) {
684 entry.setZoomedEventList(null);
685 } else {
686 List<ITimeEvent> zoomedEventList = getEventList(entry, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor);
687 if (zoomedEventList != null) {
688 entry.setZoomedEventList(zoomedEventList);
689 }
690 }
691 redraw();
692 for (ITimeGraphEntry child : entry.getChildren()) {
693 if (monitor.isCanceled()) {
694 return;
695 }
696 if (child instanceof TimeGraphEntry) {
697 zoom((TimeGraphEntry) child, monitor);
698 }
699 }
700 }
701
702 }
703
704 // ------------------------------------------------------------------------
705 // Constructors
706 // ------------------------------------------------------------------------
707
708 /**
709 * Constructs a time graph view that contains either a time graph viewer or
710 * a time graph combo.
711 *
712 * By default, the view uses a time graph viewer. To use a time graph combo,
713 * the subclass constructor must call {@link #setTreeColumns(String[])} and
714 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
715 *
716 * @param id
717 * The id of the view
718 * @param pres
719 * The presentation provider
720 */
721 public AbstractTimeGraphView(String id, TimeGraphPresentationProvider pres) {
722 super(id);
723 fPresentation = pres;
724 fDisplayWidth = Display.getDefault().getBounds().width;
725 }
726
727 // ------------------------------------------------------------------------
728 // Getters and setters
729 // ------------------------------------------------------------------------
730
731 /**
732 * Getter for the time graph combo
733 *
734 * @return The time graph combo, or null if combo is not used
735 */
736 protected TimeGraphCombo getTimeGraphCombo() {
737 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
738 return ((TimeGraphComboWrapper) fTimeGraphWrapper).getTimeGraphCombo();
739 }
740 return null;
741 }
742
743 /**
744 * Getter for the time graph viewer
745 *
746 * @return The time graph viewer
747 */
748 protected TimeGraphViewer getTimeGraphViewer() {
749 return fTimeGraphWrapper.getTimeGraphViewer();
750 }
751
752 /**
753 * Getter for the presentation provider
754 *
755 * @return The time graph presentation provider
756 */
757 protected ITimeGraphPresentationProvider2 getPresentationProvider() {
758 return fPresentation;
759 }
760
761 /**
762 * Sets the tree column labels.
763 * This should be called from the constructor.
764 *
765 * @param columns
766 * The array of tree column labels
767 */
768 protected void setTreeColumns(final String[] columns) {
769 fColumns = columns;
770 }
771
772 /**
773 * Sets the tree label provider.
774 * This should be called from the constructor.
775 *
776 * @param tlp
777 * The tree label provider
778 */
779 protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
780 fLabelProvider = tlp;
781 }
782
783 /**
784 * Sets the time graph content provider. This should be called from the
785 * constructor.
786 *
787 * @param tgcp
788 * The time graph content provider
789 * @since 1.0
790 */
791 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp) {
792 fTimeGraphContentProvider = tgcp;
793 }
794
795 /**
796 * Sets the relative weight of each part of the time graph combo.
797 * This should be called from the constructor.
798 *
799 * @param weights
800 * The array (length 2) of relative weights of each part of the combo
801 */
802 protected void setWeight(final int[] weights) {
803 fWeight = weights;
804 }
805
806 /**
807 * Sets the filter column labels.
808 * This should be called from the constructor.
809 *
810 * @param filterColumns
811 * The array of filter column labels
812 */
813 protected void setFilterColumns(final String[] filterColumns) {
814 fFilterColumns = filterColumns;
815 }
816
817 /**
818 * Sets the filter label provider.
819 * This should be called from the constructor.
820 *
821 * @param labelProvider
822 * The filter label provider
823 */
824 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
825 fFilterLabelProvider = labelProvider;
826 }
827
828 /**
829 * Gets the display width
830 *
831 * @return the display width
832 */
833 protected int getDisplayWidth() {
834 return fDisplayWidth;
835 }
836
837 /**
838 * Gets the comparator for the entries
839 *
840 * @return The entry comparator
841 */
842 protected Comparator<ITimeGraphEntry> getEntryComparator() {
843 return fEntryComparator;
844 }
845
846 /**
847 * Sets the comparator class for the entries
848 *
849 * @param comparator
850 * A comparator object
851 */
852 protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) {
853 fEntryComparator = comparator;
854 }
855
856 /**
857 * Gets the trace displayed in the view
858 *
859 * @return The trace
860 */
861 protected ITmfTrace getTrace() {
862 return fTrace;
863 }
864
865 /**
866 * Gets the start time
867 *
868 * @return The start time
869 */
870 protected long getStartTime() {
871 return fStartTime;
872 }
873
874 /**
875 * Sets the start time
876 *
877 * @param time
878 * The start time
879 */
880 protected void setStartTime(long time) {
881 fStartTime = time;
882 }
883
884 /**
885 * Gets the end time
886 *
887 * @return The end time
888 */
889 protected long getEndTime() {
890 return fEndTime;
891 }
892
893 /**
894 * Sets the end time
895 *
896 * @param time
897 * The end time
898 */
899 protected void setEndTime(long time) {
900 fEndTime = time;
901 }
902
903 /**
904 * Sets the auto-expand level to be used for the input of the view. The
905 * value 0 means that there is no auto-expand; 1 means that top-level
906 * elements are expanded, but not their children; 2 means that top-level
907 * elements are expanded, and their children, but not grand-children; and so
908 * on.
909 * <p>
910 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
911 * </p>
912 *
913 * @param level
914 * non-negative level, or <code>ALL_LEVELS</code> to expand all
915 * levels of the tree
916 */
917 protected void setAutoExpandLevel(int level) {
918 fAutoExpandLevel = level;
919 ITimeGraphWrapper tgWrapper = fTimeGraphWrapper;
920 if (tgWrapper != null) {
921 tgWrapper.setAutoExpandLevel(level);
922 }
923 }
924
925 /**
926 * Gets the entry list for a trace
927 *
928 * @param trace
929 * the trace
930 *
931 * @return the entry list map
932 */
933 protected List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
934 synchronized (fEntryListMap) {
935 return fEntryListMap.get(trace);
936 }
937 }
938
939 /**
940 * Adds a trace entry list to the entry list map
941 *
942 * @param trace
943 * the trace to add
944 * @param list
945 * the list of time graph entries
946 */
947 protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
948 synchronized (fEntryListMap) {
949 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
950 }
951 }
952
953 /**
954 * Adds a list of entries to a trace's entry list
955 *
956 * @param trace
957 * the trace
958 * @param list
959 * the list of time graph entries to add
960 */
961 protected void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
962 synchronized (fEntryListMap) {
963 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
964 if (entryList == null) {
965 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
966 } else {
967 entryList.addAll(list);
968 }
969 }
970 }
971
972 /**
973 * Removes a list of entries from a trace's entry list
974 *
975 * @param trace
976 * the trace
977 * @param list
978 * the list of time graph entries to remove
979 */
980 protected void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
981 synchronized (fEntryListMap) {
982 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
983 if (entryList != null) {
984 entryList.removeAll(list);
985 }
986 }
987 }
988
989 /**
990 * Text for the "next" button
991 *
992 * @return The "next" button text
993 */
994 protected String getNextText() {
995 return Messages.AbstractTimeGraphtView_NextText;
996 }
997
998 /**
999 * Tooltip for the "next" button
1000 *
1001 * @return Tooltip for the "next" button
1002 */
1003 protected String getNextTooltip() {
1004 return Messages.AbstractTimeGraphView_NextTooltip;
1005 }
1006
1007 /**
1008 * Text for the "Previous" button
1009 *
1010 * @return The "Previous" button text
1011 */
1012 protected String getPrevText() {
1013 return Messages.AbstractTimeGraphView_PreviousText;
1014 }
1015
1016 /**
1017 * Tooltip for the "previous" button
1018 *
1019 * @return Tooltip for the "previous" button
1020 */
1021 protected String getPrevTooltip() {
1022 return Messages.AbstractTimeGraphView_PreviousTooltip;
1023 }
1024
1025 // ------------------------------------------------------------------------
1026 // ViewPart
1027 // ------------------------------------------------------------------------
1028
1029 @Override
1030 public void createPartControl(Composite parent) {
1031 super.createPartControl(parent);
1032 if (fColumns == null || fLabelProvider == null) {
1033 fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
1034 } else {
1035 TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
1036 fTimeGraphWrapper = wrapper;
1037 TimeGraphCombo combo = wrapper.getTimeGraphCombo();
1038 combo.setTreeContentProvider(fTimeGraphContentProvider);
1039 combo.setTreeLabelProvider(fLabelProvider);
1040 combo.setTreeColumns(fColumns);
1041 }
1042 fTimeGraphWrapper.setTimeGraphContentProvider(fTimeGraphContentProvider);
1043 fTimeGraphWrapper.setFilterContentProvider(fTimeGraphContentProvider);
1044 fTimeGraphWrapper.setFilterLabelProvider(fFilterLabelProvider);
1045 fTimeGraphWrapper.setFilterColumns(fFilterColumns);
1046
1047 fTimeGraphWrapper.setTimeGraphPresentationProvider(fPresentation);
1048 fTimeGraphWrapper.setAutoExpandLevel(fAutoExpandLevel);
1049
1050 fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
1051 @Override
1052 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
1053 final long startTime = event.getStartTime();
1054 final long endTime = event.getEndTime();
1055 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
1056 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView.this, range));
1057 startZoomThread(startTime, endTime);
1058 }
1059 });
1060
1061 fTimeGraphWrapper.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
1062 @Override
1063 public void timeSelected(TimeGraphTimeEvent event) {
1064 TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime());
1065 TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime());
1066 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView.this, startTime, endTime));
1067 }
1068 });
1069
1070 fTimeGraphWrapper.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1071 @Override
1072 public void bookmarkAdded(final TimeGraphBookmarkEvent event) {
1073 try {
1074 ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
1075 @Override
1076 public void run(IProgressMonitor monitor) throws CoreException {
1077 IMarkerEvent bookmark = event.getBookmark();
1078 IMarker marker = fEditorFile.createMarker(IMarker.BOOKMARK);
1079 marker.setAttribute(IMarker.MESSAGE, bookmark.getLabel());
1080 marker.setAttribute(ITmfMarker.MARKER_TIME, Long.toString(bookmark.getTime()));
1081 if (bookmark.getDuration() > 0) {
1082 marker.setAttribute(ITmfMarker.MARKER_DURATION, Long.toString(bookmark.getDuration()));
1083 marker.setAttribute(IMarker.LOCATION,
1084 NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTimeRange,
1085 new TmfNanoTimestamp(bookmark.getTime()),
1086 new TmfNanoTimestamp(bookmark.getTime() + bookmark.getDuration())));
1087 } else {
1088 marker.setAttribute(IMarker.LOCATION,
1089 NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTime,
1090 new TmfNanoTimestamp(bookmark.getTime())));
1091 }
1092 marker.setAttribute(ITmfMarker.MARKER_COLOR, bookmark.getColor().getRGBA().toString());
1093 }
1094 }, null);
1095 } catch (CoreException e) {
1096 Activator.getDefault().logError(e.getMessage());
1097 }
1098 }
1099
1100 @Override
1101 public void bookmarkRemoved(TimeGraphBookmarkEvent event) {
1102 try {
1103 IMarkerEvent bookmark = event.getBookmark();
1104 IMarker[] markers = fEditorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1105 for (IMarker marker : markers) {
1106 if (bookmark.getLabel().equals(marker.getAttribute(IMarker.MESSAGE)) &&
1107 Long.toString(bookmark.getTime()).equals(marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null)) &&
1108 Long.toString(bookmark.getDuration()).equals(marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0))) &&
1109 bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(ITmfMarker.MARKER_COLOR))) {
1110 marker.delete();
1111 break;
1112 }
1113 }
1114 } catch (CoreException e) {
1115 Activator.getDefault().logError(e.getMessage());
1116 }
1117 }
1118 });
1119
1120 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
1121
1122 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
1123 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
1124
1125 // View Action Handling
1126 makeActions();
1127 contributeToActionBars();
1128
1129 ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
1130 if (trace != null) {
1131 traceSelected(new TmfTraceSelectedSignal(this, trace));
1132 }
1133
1134 // make selection available to other views
1135 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
1136
1137 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
1138 }
1139
1140 @Override
1141 public void setFocus() {
1142 fTimeGraphWrapper.setFocus();
1143 }
1144
1145 @Override
1146 public void dispose() {
1147 super.dispose();
1148 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
1149 }
1150
1151 /**
1152 * @since 2.0
1153 */
1154 @Override
1155 public void resourceChanged(final IResourceChangeEvent event) {
1156 for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
1157 if (delta.getResource().equals(fEditorFile)) {
1158 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1159 redraw();
1160 return;
1161 }
1162 }
1163 }
1164
1165 private List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
1166 List<IMarkerEvent> bookmarks = new ArrayList<>();
1167 for (Color color : fColors) {
1168 color.dispose();
1169 }
1170 fColors.clear();
1171 if (editorFile == null || !editorFile.exists()) {
1172 return bookmarks;
1173 }
1174 try {
1175 IMarker[] markers = editorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1176 for (IMarker marker : markers) {
1177 String label = marker.getAttribute(IMarker.MESSAGE, (String) null);
1178 String time = marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null);
1179 String duration = marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0));
1180 String rgba = marker.getAttribute(ITmfMarker.MARKER_COLOR, (String) null);
1181 if (label != null && time != null && rgba != null) {
1182 Matcher matcher = RGBA_PATTERN.matcher(rgba);
1183 if (matcher.matches()) {
1184 try {
1185 int red = Integer.valueOf(matcher.group(1));
1186 int green = Integer.valueOf(matcher.group(2));
1187 int blue = Integer.valueOf(matcher.group(3));
1188 int alpha = Integer.valueOf(matcher.group(4));
1189 Color color = new Color(Display.getDefault(), red, green, blue, alpha);
1190 fColors.add(color);
1191 bookmarks.add(new MarkerEvent(null, Long.valueOf(time), Long.valueOf(duration), IMarkerEvent.BOOKMARKS, color, label, true));
1192 } catch (NumberFormatException e) {
1193 Activator.getDefault().logError(e.getMessage());
1194 }
1195 }
1196 }
1197 }
1198 } catch (CoreException e) {
1199 Activator.getDefault().logError(e.getMessage());
1200 }
1201 return bookmarks;
1202 }
1203
1204 // ------------------------------------------------------------------------
1205 // Signal handlers
1206 // ------------------------------------------------------------------------
1207
1208 /**
1209 * Handler for the trace opened signal.
1210 *
1211 * @param signal
1212 * The incoming signal
1213 */
1214 @TmfSignalHandler
1215 public void traceOpened(TmfTraceOpenedSignal signal) {
1216 loadTrace(signal.getTrace());
1217 }
1218
1219 /**
1220 * Handler for the trace selected signal
1221 *
1222 * @param signal
1223 * The incoming signal
1224 */
1225 @TmfSignalHandler
1226 public void traceSelected(final TmfTraceSelectedSignal signal) {
1227 if (signal.getTrace() == fTrace) {
1228 return;
1229 }
1230 loadTrace(signal.getTrace());
1231 }
1232
1233 /**
1234 * Trace is closed: clear the data structures and the view
1235 *
1236 * @param signal
1237 * the signal received
1238 */
1239 @TmfSignalHandler
1240 public void traceClosed(final TmfTraceClosedSignal signal) {
1241 synchronized (fBuildThreadMap) {
1242 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
1243 BuildThread buildThread = fBuildThreadMap.remove(trace);
1244 if (buildThread != null) {
1245 buildThread.cancel();
1246 }
1247 }
1248 }
1249 fMarkerEventSourcesMap.remove(signal.getTrace());
1250 synchronized (fEntryListMap) {
1251 fEntryListMap.remove(signal.getTrace());
1252 }
1253 fFiltersMap.remove(signal.getTrace());
1254 if (signal.getTrace() == fTrace) {
1255 fTrace = null;
1256 fEditorFile = null;
1257 fStartTime = SWT.DEFAULT;
1258 fEndTime = SWT.DEFAULT;
1259 if (fZoomThread != null) {
1260 fZoomThread.cancel();
1261 fZoomThread = null;
1262 }
1263 refresh();
1264 }
1265 }
1266
1267 /**
1268 * Handler for the selection range signal.
1269 *
1270 * @param signal
1271 * The signal that's received
1272 * @since 1.0
1273 */
1274 @TmfSignalHandler
1275 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
1276 if (signal.getSource() == this || fTrace == null) {
1277 return;
1278 }
1279 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1280 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1281
1282 Display.getDefault().asyncExec(new Runnable() {
1283 @Override
1284 public void run() {
1285 if (fTimeGraphWrapper.isDisposed()) {
1286 return;
1287 }
1288 if (beginTime == endTime) {
1289 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
1290 } else {
1291 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
1292 }
1293 synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getTime0());
1294 }
1295 });
1296 }
1297
1298 /**
1299 * Handler for the window range signal.
1300 *
1301 * @param signal
1302 * The signal that's received
1303 * @since 1.0
1304 */
1305 @TmfSignalHandler
1306 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
1307 if (signal.getSource() == this || fTrace == null) {
1308 return;
1309 }
1310 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1311 return;
1312 }
1313 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1314 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1315 Display.getDefault().asyncExec(new Runnable() {
1316 @Override
1317 public void run() {
1318 if (fTimeGraphWrapper.isDisposed()) {
1319 return;
1320 }
1321 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1322 startZoomThread(startTime, endTime);
1323 }
1324 });
1325 }
1326
1327 /**
1328 * @param signal the format of the timestamps was updated.
1329 */
1330 @TmfSignalHandler
1331 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
1332 fTimeGraphWrapper.refresh();
1333 }
1334
1335 // ------------------------------------------------------------------------
1336 // Internal
1337 // ------------------------------------------------------------------------
1338
1339 private void loadTrace(final ITmfTrace trace) {
1340 if (fZoomThread != null) {
1341 fZoomThread.cancel();
1342 fZoomThread = null;
1343 }
1344 if (fTrace != null) {
1345 /* save the filters of the previous trace */
1346 fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
1347 }
1348 fTrace = trace;
1349 fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
1350 synchronized (fEntryListMap) {
1351 fEntryList = fEntryListMap.get(fTrace);
1352 if (fEntryList == null) {
1353 rebuild();
1354 } else {
1355 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1356 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1357 refresh();
1358 }
1359 }
1360 }
1361
1362 /**
1363 * Forces a rebuild of the entries list, even if entries already exist for this trace
1364 */
1365 protected void rebuild() {
1366 setStartTime(Long.MAX_VALUE);
1367 setEndTime(Long.MIN_VALUE);
1368 refresh();
1369 ITmfTrace viewTrace = fTrace;
1370 if (viewTrace == null) {
1371 return;
1372 }
1373 List<IMarkerEventSource> markerEventSources = new ArrayList<>();
1374 synchronized (fBuildThreadMap) {
1375 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1376 if (trace == null) {
1377 break;
1378 }
1379 markerEventSources.addAll(TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class));
1380 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
1381 fBuildThreadMap.put(trace, buildThread);
1382 buildThread.start();
1383 }
1384 }
1385 fMarkerEventSourcesMap.put(viewTrace, markerEventSources);
1386 }
1387
1388 /**
1389 * Method called when synching to a given timestamp. Inheriting classes can
1390 * perform actions here to update the view at the given timestamp.
1391 *
1392 * @param time
1393 * The currently selected time
1394 */
1395 protected void synchingToTime(long time) {
1396
1397 }
1398
1399 /**
1400 * Return the list of traces whose data or analysis results will be used to
1401 * populate the view. By default, if the trace is an experiment, the traces
1402 * under it will be returned, otherwise, the trace itself is returned.
1403 *
1404 * A build thread will be started for each trace returned by this method,
1405 * some of which may receive events in live streaming mode.
1406 *
1407 * @param trace
1408 * The trace associated with this view
1409 * @return List of traces with data to display
1410 */
1411 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
1412 return TmfTraceManager.getTraceSet(trace);
1413 }
1414
1415 /**
1416 * Build the entries list to show in this time graph
1417 *
1418 * Called from the BuildThread
1419 *
1420 * @param trace
1421 * The trace being built
1422 * @param parentTrace
1423 * The parent of the trace set, or the trace itself
1424 * @param monitor
1425 * The progress monitor object
1426 */
1427 protected abstract void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
1428
1429 /**
1430 * Gets the list of event for an entry in a given timerange
1431 *
1432 * @param entry
1433 * The entry to get events for
1434 * @param startTime
1435 * Start of the time range
1436 * @param endTime
1437 * End of the time range
1438 * @param resolution
1439 * The resolution
1440 * @param monitor
1441 * The progress monitor object
1442 * @return The list of events for the entry
1443 */
1444 protected abstract @Nullable List<@NonNull ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
1445 long startTime, long endTime, long resolution,
1446 @NonNull IProgressMonitor monitor);
1447
1448 /**
1449 * Gets the list of links (displayed as arrows) for a trace in a given
1450 * timerange. Default implementation returns an empty list.
1451 *
1452 * @param startTime
1453 * Start of the time range
1454 * @param endTime
1455 * End of the time range
1456 * @param resolution
1457 * The resolution
1458 * @param monitor
1459 * The progress monitor object
1460 * @return The list of link events
1461 */
1462 protected @Nullable List<@NonNull ILinkEvent> getLinkList(long startTime, long endTime,
1463 long resolution, @NonNull IProgressMonitor monitor) {
1464 return new ArrayList<>();
1465 }
1466
1467 /**
1468 * Gets the list of view-specific marker categories. Default implementation
1469 * returns an empty list.
1470 *
1471 * @return The list of marker categories
1472 * @since 2.0
1473 */
1474 protected @NonNull List<String> getViewMarkerCategories() {
1475 return new ArrayList<>();
1476 }
1477
1478 /**
1479 * Gets the list of view-specific markers for a trace in a given time range.
1480 * Default implementation returns an empty list.
1481 *
1482 * @param startTime
1483 * Start of the time range
1484 * @param endTime
1485 * End of the time range
1486 * @param resolution
1487 * The resolution
1488 * @param monitor
1489 * The progress monitor object
1490 * @return The list of marker events
1491 * @since 2.0
1492 */
1493 protected @NonNull List<IMarkerEvent> getViewMarkerList(long startTime, long endTime,
1494 long resolution, @NonNull IProgressMonitor monitor) {
1495 return new ArrayList<>();
1496 }
1497
1498 /**
1499 * Gets the list of trace-specific markers for a trace in a given time range.
1500 *
1501 * @param startTime
1502 * Start of the time range
1503 * @param endTime
1504 * End of the time range
1505 * @param resolution
1506 * The resolution
1507 * @param monitor
1508 * The progress monitor object
1509 * @return The list of marker events
1510 * @since 2.0
1511 */
1512 protected @NonNull List<IMarkerEvent> getTraceMarkerList(long startTime, long endTime,
1513 long resolution, @NonNull IProgressMonitor monitor) {
1514 List<IMarkerEvent> markers = new ArrayList<>();
1515 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
1516 for (String category : markerEventSource.getMarkerCategories()) {
1517 if (monitor.isCanceled()) {
1518 break;
1519 }
1520 markers.addAll(markerEventSource.getMarkerList(checkNotNull(category), startTime, endTime, resolution, monitor));
1521 }
1522 }
1523 return markers;
1524 }
1525
1526 /**
1527 * Get the list of current marker categories.
1528 *
1529 * @return The list of marker categories
1530 * @since 2.0
1531 */
1532 private @NonNull List<String> getMarkerCategories() {
1533 Set<String> categories = new HashSet<>(getViewMarkerCategories());
1534 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
1535 categories.addAll(markerEventSource.getMarkerCategories());
1536 }
1537 return new ArrayList<>(categories);
1538 }
1539
1540 /**
1541 * Gets the list of marker event sources for a given trace.
1542 *
1543 * @param trace
1544 * The trace
1545 * @return The list of marker event sources
1546 * @since 2.0
1547 */
1548 private @NonNull List<IMarkerEventSource> getMarkerEventSources(ITmfTrace trace) {
1549 List<IMarkerEventSource> markerEventSources = fMarkerEventSourcesMap.get(trace);
1550 if (markerEventSources == null) {
1551 markerEventSources = checkNotNull(Collections.<IMarkerEventSource>emptyList());
1552 }
1553 return markerEventSources;
1554 }
1555
1556 /**
1557 * Refresh the display
1558 */
1559 protected void refresh() {
1560 final boolean zoomThread = Thread.currentThread() instanceof ZoomThread;
1561 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
1562 @Override
1563 public void run() {
1564 if (fTimeGraphWrapper.isDisposed()) {
1565 return;
1566 }
1567 boolean hasEntries = false;
1568 synchronized (fEntryListMap) {
1569 fEntryList = fEntryListMap.get(fTrace);
1570 if (fEntryList == null) {
1571 fEntryList = new CopyOnWriteArrayList<>();
1572 } else if (fEntryComparator != null) {
1573 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1574 Collections.sort(list, fEntryComparator);
1575 fEntryList.clear();
1576 fEntryList.addAll(list);
1577 }
1578 hasEntries = fEntryList.size() != 0;
1579 }
1580 if (fEntryList != fTimeGraphWrapper.getInput()) {
1581 fTimeGraphWrapper.setInput(fEntryList);
1582 /* restore the previously saved filters, if any */
1583 fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
1584 fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
1585 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1586 fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1587 fTimeGraphWrapper.getTimeGraphViewer().setMarkers(null);
1588 } else {
1589 fTimeGraphWrapper.refresh();
1590 }
1591 long startBound = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : fStartTime);
1592 long endBound = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : fEndTime);
1593 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(startBound, endBound);
1594
1595 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
1596 long selectionBeginTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1597 long selectionEndTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1598 long startTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1599 long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1600 startTime = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : Math.max(startTime, fStartTime));
1601 endTime = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : Math.min(endTime, fEndTime));
1602 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime, false);
1603 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1604
1605 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
1606 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1607 column.pack();
1608 }
1609 if (hasEntries) {
1610 fPackDone = true;
1611 }
1612 }
1613
1614 if (!zoomThread) {
1615 startZoomThread(startTime, endTime);
1616 }
1617 }
1618 });
1619 }
1620
1621 /**
1622 * Redraw the canvas
1623 */
1624 protected void redraw() {
1625 synchronized (fSyncObj) {
1626 if (fRedrawState == State.IDLE) {
1627 fRedrawState = State.BUSY;
1628 } else {
1629 fRedrawState = State.PENDING;
1630 return;
1631 }
1632 }
1633 Display.getDefault().asyncExec(new Runnable() {
1634 @Override
1635 public void run() {
1636 if (fTimeGraphWrapper.isDisposed()) {
1637 return;
1638 }
1639 fTimeGraphWrapper.redraw();
1640 fTimeGraphWrapper.update();
1641 synchronized (fSyncObj) {
1642 if (fRedrawState == State.PENDING) {
1643 fRedrawState = State.IDLE;
1644 redraw();
1645 } else {
1646 fRedrawState = State.IDLE;
1647 }
1648 }
1649 }
1650 });
1651 }
1652
1653 private void startZoomThread(long startTime, long endTime) {
1654 boolean restart = false;
1655 if (fZoomThread != null) {
1656 fZoomThread.cancel();
1657 if (fZoomThread.fZoomStartTime == startTime && fZoomThread.fZoomEndTime == endTime) {
1658 restart = true;
1659 }
1660 }
1661 long resolution = Math.max(1, (endTime - startTime) / fDisplayWidth);
1662 fZoomThread = createZoomThread(startTime, endTime, resolution, restart);
1663 if (fZoomThread != null) {
1664 fZoomThread.start();
1665 }
1666 }
1667
1668 /**
1669 * Create a zoom thread.
1670 *
1671 * @param startTime
1672 * the zoom start time
1673 * @param endTime
1674 * the zoom end time
1675 * @param resolution
1676 * the resolution
1677 * @param restart
1678 * true if restarting zoom for the same time range
1679 * @return a zoom thread
1680 * @since 1.1
1681 */
1682 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
1683 final List<TimeGraphEntry> entryList = fEntryList;
1684 if (entryList == null) {
1685 return null;
1686 }
1687 return new ZoomThreadByEntry(entryList, startTime, endTime, resolution);
1688 }
1689
1690 private void makeActions() {
1691 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
1692 fPreviousResourceAction.setText(getPrevText());
1693 fPreviousResourceAction.setToolTipText(getPrevTooltip());
1694 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
1695 fNextResourceAction.setText(getNextText());
1696 fNextResourceAction.setToolTipText(getNextTooltip());
1697 }
1698
1699 private void contributeToActionBars() {
1700 IActionBars bars = getViewSite().getActionBars();
1701 fillLocalToolBar(bars.getToolBarManager());
1702 fillLocalMenu(bars.getMenuManager());
1703 }
1704
1705 /**
1706 * Add actions to local tool bar manager
1707 *
1708 * @param manager the tool bar manager
1709 */
1710 protected void fillLocalToolBar(IToolBarManager manager) {
1711 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
1712 manager.add(fTimeGraphWrapper.getShowFilterDialogAction());
1713 }
1714 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
1715 manager.add(new Separator());
1716 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1717 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1718 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
1719 manager.add(new Separator());
1720 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getToggleBookmarkAction());
1721 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousMarkerAction());
1722 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextMarkerAction());
1723 manager.add(new Separator());
1724 manager.add(fPreviousResourceAction);
1725 manager.add(fNextResourceAction);
1726 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1727 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
1728 manager.add(new Separator());
1729 }
1730
1731 /**
1732 * Add actions to local menu manager
1733 *
1734 * @param manager the tool bar manager
1735 * @since 2.0
1736 */
1737 protected void fillLocalMenu(IMenuManager manager) {
1738 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getMarkersMenu());
1739 }
1740
1741 /**
1742 * @since 1.0
1743 */
1744 @Override
1745 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
1746 if (fTimeGraphWrapper == null) {
1747 return null;
1748 }
1749 return fTimeGraphWrapper.getTimeViewAlignmentInfo();
1750 }
1751
1752 /**
1753 * @since 1.0
1754 */
1755 @Override
1756 public int getAvailableWidth(int requestedOffset) {
1757 if (fTimeGraphWrapper == null) {
1758 return 0;
1759 }
1760 return fTimeGraphWrapper.getAvailableWidth(requestedOffset);
1761 }
1762
1763 /**
1764 * @since 1.0
1765 */
1766 @Override
1767 public void performAlign(int offset, int width) {
1768 if (fTimeGraphWrapper != null) {
1769 fTimeGraphWrapper.performAlign(offset, width);
1770 }
1771 }
1772 }
This page took 0.068222 seconds and 4 git commands to generate.