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