134b3f1a2148ffad96cf54fe13e37f638052ef55
[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 java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.concurrent.CopyOnWriteArrayList;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.resources.IMarker;
31 import org.eclipse.core.resources.IMarkerDelta;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.resources.IResourceChangeEvent;
34 import org.eclipse.core.resources.IResourceChangeListener;
35 import org.eclipse.core.resources.IWorkspaceRunnable;
36 import org.eclipse.core.resources.ResourcesPlugin;
37 import org.eclipse.core.runtime.CoreException;
38 import org.eclipse.core.runtime.IProgressMonitor;
39 import org.eclipse.core.runtime.NullProgressMonitor;
40 import org.eclipse.jdt.annotation.NonNull;
41 import org.eclipse.jdt.annotation.Nullable;
42 import org.eclipse.jface.action.Action;
43 import org.eclipse.jface.action.IAction;
44 import org.eclipse.jface.action.IStatusLineManager;
45 import org.eclipse.jface.action.IToolBarManager;
46 import org.eclipse.jface.action.Separator;
47 import org.eclipse.jface.viewers.AbstractTreeViewer;
48 import org.eclipse.jface.viewers.ILabelProvider;
49 import org.eclipse.jface.viewers.ILabelProviderListener;
50 import org.eclipse.jface.viewers.ISelectionProvider;
51 import org.eclipse.jface.viewers.ITableLabelProvider;
52 import org.eclipse.jface.viewers.ITreeContentProvider;
53 import org.eclipse.jface.viewers.TreeViewer;
54 import org.eclipse.jface.viewers.ViewerFilter;
55 import org.eclipse.swt.SWT;
56 import org.eclipse.swt.graphics.Color;
57 import org.eclipse.swt.graphics.Image;
58 import org.eclipse.swt.widgets.Composite;
59 import org.eclipse.swt.widgets.Display;
60 import org.eclipse.swt.widgets.TreeColumn;
61 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
62 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
63 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
64 import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
65 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
66 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
67 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
68 import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
69 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
70 import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
71 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
72 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
73 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
74 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
75 import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
76 import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
77 import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
78 import org.eclipse.tracecompass.tmf.ui.views.TmfView;
79 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphBookmarkListener;
80 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
81 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
82 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
83 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
84 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
85 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphBookmarkEvent;
86 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
87 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
88 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
89 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
90 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
91 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
92 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
93 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
94 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
95 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
96 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
97 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
98 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
99 import org.eclipse.ui.IActionBars;
100
101 /**
102 * An abstract view all time graph views can inherit
103 *
104 * This view contains either a time graph viewer, or a time graph combo which is
105 * divided between a tree viewer on the left and a time graph viewer on the right.
106 */
107 public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeAligned, IResourceChangeListener {
108
109 /** Constant indicating that all levels of the time graph should be expanded */
110 protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
111
112 /** Color marker attribute. The format is the output of RGBA.toString(). */
113 private static final String MARKER_COLOR = "color"; //$NON-NLS-1$
114
115 /** Time marker attribute. The format is the output of Long.toString(). */
116 private static final String MARKER_TIME = "time"; //$NON-NLS-1$
117
118 /** Duration marker attribute. The format is the output of Long.toString(). */
119 private static final String MARKER_DURATION = "duration"; //$NON-NLS-1$
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 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 2.0
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 markers when zooming */
672 List<IMarkerEvent> markers = getMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
673 if (markers != null) {
674 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setMarkers(markers);
675 redraw();
676 }
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(MARKER_TIME, Long.toString(bookmark.getTime()));
1078 if (bookmark.getDuration() > 0) {
1079 marker.setAttribute(MARKER_DURATION, Long.toString(bookmark.getDuration()));
1080 marker.setAttribute(IMarker.LOCATION,
1081 String.format("[%d, %d]", bookmark.getTime(), bookmark.getTime() + bookmark.getDuration())); //$NON-NLS-1$
1082 } else {
1083 marker.setAttribute(IMarker.LOCATION,
1084 String.format("[%d]", bookmark.getTime())); //$NON-NLS-1$
1085 }
1086 marker.setAttribute(MARKER_COLOR, bookmark.getColor().getRGBA().toString());
1087 }
1088 }, null);
1089 } catch (CoreException e) {
1090 Activator.getDefault().logError(e.getMessage());
1091 }
1092 }
1093
1094 @Override
1095 public void bookmarkRemoved(TimeGraphBookmarkEvent event) {
1096 try {
1097 IMarkerEvent bookmark = event.getBookmark();
1098 IMarker[] markers = fEditorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1099 for (IMarker marker : markers) {
1100 if (bookmark.getLabel().equals(marker.getAttribute(IMarker.MESSAGE)) &&
1101 Long.toString(bookmark.getTime()).equals(marker.getAttribute(MARKER_TIME, (String) null)) &&
1102 Long.toString(bookmark.getDuration()).equals(marker.getAttribute(MARKER_DURATION, Long.toString(0))) &&
1103 bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(MARKER_COLOR))) {
1104 marker.delete();
1105 break;
1106 }
1107 }
1108 } catch (CoreException e) {
1109 Activator.getDefault().logError(e.getMessage());
1110 }
1111 }
1112 });
1113
1114 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
1115
1116 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
1117 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
1118
1119 // View Action Handling
1120 makeActions();
1121 contributeToActionBars();
1122
1123 ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
1124 if (trace != null) {
1125 traceSelected(new TmfTraceSelectedSignal(this, trace));
1126 }
1127
1128 // make selection available to other views
1129 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
1130
1131 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
1132 }
1133
1134 @Override
1135 public void setFocus() {
1136 fTimeGraphWrapper.setFocus();
1137 }
1138
1139 @Override
1140 public void dispose() {
1141 super.dispose();
1142 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
1143 }
1144
1145 /**
1146 * @since 2.0
1147 */
1148 @Override
1149 public void resourceChanged(final IResourceChangeEvent event) {
1150 for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
1151 if (delta.getResource().equals(fEditorFile)) {
1152 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1153 redraw();
1154 return;
1155 }
1156 }
1157 }
1158
1159 private List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
1160 List<IMarkerEvent> bookmarks = new ArrayList<>();
1161 try {
1162 for (Color color : fColors) {
1163 color.dispose();
1164 }
1165 fColors.clear();
1166 IMarker[] markers = editorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1167 for (IMarker marker : markers) {
1168 String label = marker.getAttribute(IMarker.MESSAGE, (String) null);
1169 String time = marker.getAttribute(MARKER_TIME, (String) null);
1170 String duration = marker.getAttribute(MARKER_DURATION, Long.toString(0));
1171 String rgba = marker.getAttribute(MARKER_COLOR, (String) null);
1172 if (label != null && time != null && rgba != null) {
1173 Matcher matcher = RGBA_PATTERN.matcher(rgba);
1174 if (matcher.matches()) {
1175 try {
1176 int red = Integer.valueOf(matcher.group(1));
1177 int green = Integer.valueOf(matcher.group(2));
1178 int blue = Integer.valueOf(matcher.group(3));
1179 int alpha = Integer.valueOf(matcher.group(4));
1180 Color color = new Color(Display.getDefault(), red, green, blue, alpha);
1181 fColors.add(color);
1182 bookmarks.add(new MarkerEvent(null, Long.valueOf(time), Long.valueOf(duration), color, label, true));
1183 } catch (NumberFormatException e) {
1184 Activator.getDefault().logError(e.getMessage());
1185 }
1186 }
1187 }
1188 }
1189 } catch (CoreException e) {
1190 Activator.getDefault().logError(e.getMessage());
1191 }
1192 return bookmarks;
1193 }
1194
1195 // ------------------------------------------------------------------------
1196 // Signal handlers
1197 // ------------------------------------------------------------------------
1198
1199 /**
1200 * Handler for the trace opened signal.
1201 *
1202 * @param signal
1203 * The incoming signal
1204 */
1205 @TmfSignalHandler
1206 public void traceOpened(TmfTraceOpenedSignal signal) {
1207 loadTrace(signal.getTrace());
1208 }
1209
1210 /**
1211 * Handler for the trace selected signal
1212 *
1213 * @param signal
1214 * The incoming signal
1215 */
1216 @TmfSignalHandler
1217 public void traceSelected(final TmfTraceSelectedSignal signal) {
1218 if (signal.getTrace() == fTrace) {
1219 return;
1220 }
1221 loadTrace(signal.getTrace());
1222 }
1223
1224 /**
1225 * Trace is closed: clear the data structures and the view
1226 *
1227 * @param signal
1228 * the signal received
1229 */
1230 @TmfSignalHandler
1231 public void traceClosed(final TmfTraceClosedSignal signal) {
1232 synchronized (fBuildThreadMap) {
1233 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
1234 BuildThread buildThread = fBuildThreadMap.remove(trace);
1235 if (buildThread != null) {
1236 buildThread.cancel();
1237 }
1238 }
1239 }
1240 synchronized (fEntryListMap) {
1241 fEntryListMap.remove(signal.getTrace());
1242 }
1243 fFiltersMap.remove(signal.getTrace());
1244 if (signal.getTrace() == fTrace) {
1245 fTrace = null;
1246 fStartTime = SWT.DEFAULT;
1247 fEndTime = SWT.DEFAULT;
1248 if (fZoomThread != null) {
1249 fZoomThread.cancel();
1250 fZoomThread = null;
1251 }
1252 refresh();
1253 }
1254 }
1255
1256 /**
1257 * Handler for the selection range signal.
1258 *
1259 * @param signal
1260 * The signal that's received
1261 * @since 1.0
1262 */
1263 @TmfSignalHandler
1264 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
1265 if (signal.getSource() == this || fTrace == null) {
1266 return;
1267 }
1268 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1269 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1270
1271 Display.getDefault().asyncExec(new Runnable() {
1272 @Override
1273 public void run() {
1274 if (fTimeGraphWrapper.isDisposed()) {
1275 return;
1276 }
1277 if (beginTime == endTime) {
1278 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
1279 } else {
1280 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
1281 }
1282 synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getTime0());
1283 }
1284 });
1285 }
1286
1287 /**
1288 * Handler for the window range signal.
1289 *
1290 * @param signal
1291 * The signal that's received
1292 * @since 1.0
1293 */
1294 @TmfSignalHandler
1295 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
1296 if (signal.getSource() == this || fTrace == null) {
1297 return;
1298 }
1299 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1300 return;
1301 }
1302 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1303 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1304 Display.getDefault().asyncExec(new Runnable() {
1305 @Override
1306 public void run() {
1307 if (fTimeGraphWrapper.isDisposed()) {
1308 return;
1309 }
1310 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1311 startZoomThread(startTime, endTime);
1312 }
1313 });
1314 }
1315
1316 /**
1317 * @param signal the format of the timestamps was updated.
1318 */
1319 @TmfSignalHandler
1320 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
1321 fTimeGraphWrapper.refresh();
1322 }
1323
1324 // ------------------------------------------------------------------------
1325 // Internal
1326 // ------------------------------------------------------------------------
1327
1328 private void loadTrace(final ITmfTrace trace) {
1329 if (fZoomThread != null) {
1330 fZoomThread.cancel();
1331 fZoomThread = null;
1332 }
1333 if (fTrace != null) {
1334 /* save the filters of the previous trace */
1335 fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
1336 }
1337 fTrace = trace;
1338 fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
1339 synchronized (fEntryListMap) {
1340 fEntryList = fEntryListMap.get(fTrace);
1341 if (fEntryList == null) {
1342 rebuild();
1343 } else {
1344 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1345 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1346 refresh();
1347 }
1348 }
1349 }
1350
1351 /**
1352 * Forces a rebuild of the entries list, even if entries already exist for this trace
1353 */
1354 protected void rebuild() {
1355 setStartTime(Long.MAX_VALUE);
1356 setEndTime(Long.MIN_VALUE);
1357 refresh();
1358 ITmfTrace viewTrace = fTrace;
1359 if (viewTrace == null) {
1360 return;
1361 }
1362 synchronized (fBuildThreadMap) {
1363 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1364 if (trace == null) {
1365 break;
1366 }
1367 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
1368 fBuildThreadMap.put(trace, buildThread);
1369 buildThread.start();
1370 }
1371 }
1372 }
1373
1374 /**
1375 * Method called when synching to a given timestamp. Inheriting classes can
1376 * perform actions here to update the view at the given timestamp.
1377 *
1378 * @param time
1379 * The currently selected time
1380 */
1381 protected void synchingToTime(long time) {
1382
1383 }
1384
1385 /**
1386 * Return the list of traces whose data or analysis results will be used to
1387 * populate the view. By default, if the trace is an experiment, the traces
1388 * under it will be returned, otherwise, the trace itself is returned.
1389 *
1390 * A build thread will be started for each trace returned by this method,
1391 * some of which may receive events in live streaming mode.
1392 *
1393 * @param trace
1394 * The trace associated with this view
1395 * @return List of traces with data to display
1396 */
1397 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
1398 return TmfTraceManager.getTraceSet(trace);
1399 }
1400
1401 /**
1402 * Build the entries list to show in this time graph
1403 *
1404 * Called from the BuildThread
1405 *
1406 * @param trace
1407 * The trace being built
1408 * @param parentTrace
1409 * The parent of the trace set, or the trace itself
1410 * @param monitor
1411 * The progress monitor object
1412 */
1413 protected abstract void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
1414
1415 /**
1416 * Gets the list of event for an entry in a given timerange
1417 *
1418 * @param entry
1419 * The entry to get events for
1420 * @param startTime
1421 * Start of the time range
1422 * @param endTime
1423 * End of the time range
1424 * @param resolution
1425 * The resolution
1426 * @param monitor
1427 * The progress monitor object
1428 * @return The list of events for the entry
1429 */
1430 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
1431 long startTime, long endTime, long resolution,
1432 @NonNull IProgressMonitor monitor);
1433
1434 /**
1435 * Gets the list of links (displayed as arrows) for a trace in a given
1436 * timerange. Default implementation returns an empty list.
1437 *
1438 * @param startTime
1439 * Start of the time range
1440 * @param endTime
1441 * End of the time range
1442 * @param resolution
1443 * The resolution
1444 * @param monitor
1445 * The progress monitor object
1446 * @return The list of link events
1447 */
1448 protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime,
1449 long resolution, @NonNull IProgressMonitor monitor) {
1450 return new ArrayList<>();
1451 }
1452
1453 /**
1454 * Gets the list of markers for a trace in a given time range. Default
1455 * implementation returns an empty list.
1456 *
1457 * @param startTime
1458 * Start of the time range
1459 * @param endTime
1460 * End of the time range
1461 * @param resolution
1462 * The resolution
1463 * @param monitor
1464 * The progress monitor object
1465 * @return The list of marker events
1466 * @since 2.0
1467 */
1468 protected @Nullable List<IMarkerEvent> getMarkerList(long startTime, long endTime,
1469 long resolution, @NonNull IProgressMonitor monitor) {
1470 return new ArrayList<>();
1471 }
1472
1473 /**
1474 * Refresh the display
1475 */
1476 protected void refresh() {
1477 final boolean zoomThread = Thread.currentThread() instanceof ZoomThread;
1478 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
1479 @Override
1480 public void run() {
1481 if (fTimeGraphWrapper.isDisposed()) {
1482 return;
1483 }
1484 boolean hasEntries = false;
1485 synchronized (fEntryListMap) {
1486 fEntryList = fEntryListMap.get(fTrace);
1487 if (fEntryList == null) {
1488 fEntryList = new CopyOnWriteArrayList<>();
1489 } else if (fEntryComparator != null) {
1490 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1491 Collections.sort(list, fEntryComparator);
1492 fEntryList.clear();
1493 fEntryList.addAll(list);
1494 }
1495 hasEntries = fEntryList.size() != 0;
1496 }
1497 if (fEntryList != fTimeGraphWrapper.getInput()) {
1498 fTimeGraphWrapper.setInput(fEntryList);
1499 /* restore the previously saved filters, if any */
1500 fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
1501 fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
1502 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1503 } else {
1504 fTimeGraphWrapper.refresh();
1505 }
1506 long startBound = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : fStartTime);
1507 long endBound = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : fEndTime);
1508 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(startBound, endBound);
1509
1510 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
1511 long selectionBeginTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1512 long selectionEndTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1513 long startTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1514 long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1515 startTime = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : Math.max(startTime, fStartTime));
1516 endTime = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : Math.min(endTime, fEndTime));
1517 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1518 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1519
1520 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
1521 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1522 column.pack();
1523 }
1524 if (hasEntries) {
1525 fPackDone = true;
1526 }
1527 }
1528
1529 if (!zoomThread) {
1530 startZoomThread(startTime, endTime);
1531 }
1532 }
1533 });
1534 }
1535
1536 /**
1537 * Redraw the canvas
1538 */
1539 protected void redraw() {
1540 synchronized (fSyncObj) {
1541 if (fRedrawState == State.IDLE) {
1542 fRedrawState = State.BUSY;
1543 } else {
1544 fRedrawState = State.PENDING;
1545 return;
1546 }
1547 }
1548 Display.getDefault().asyncExec(new Runnable() {
1549 @Override
1550 public void run() {
1551 if (fTimeGraphWrapper.isDisposed()) {
1552 return;
1553 }
1554 fTimeGraphWrapper.redraw();
1555 fTimeGraphWrapper.update();
1556 synchronized (fSyncObj) {
1557 if (fRedrawState == State.PENDING) {
1558 fRedrawState = State.IDLE;
1559 redraw();
1560 } else {
1561 fRedrawState = State.IDLE;
1562 }
1563 }
1564 }
1565 });
1566 }
1567
1568 private void startZoomThread(long startTime, long endTime) {
1569 boolean restart = false;
1570 if (fZoomThread != null) {
1571 fZoomThread.cancel();
1572 if (fZoomThread.fZoomStartTime == startTime && fZoomThread.fZoomEndTime == endTime) {
1573 restart = true;
1574 }
1575 }
1576 long resolution = Math.max(1, (endTime - startTime) / fDisplayWidth);
1577 fZoomThread = createZoomThread(startTime, endTime, resolution, restart);
1578 if (fZoomThread != null) {
1579 fZoomThread.start();
1580 }
1581 }
1582
1583 /**
1584 * Create a zoom thread.
1585 *
1586 * @param startTime
1587 * the zoom start time
1588 * @param endTime
1589 * the zoom end time
1590 * @param resolution
1591 * the resolution
1592 * @param restart
1593 * true if restarting zoom for the same time range
1594 * @return a zoom thread
1595 * @since 2.0
1596 */
1597 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
1598 final List<TimeGraphEntry> entryList = fEntryList;
1599 if (entryList == null) {
1600 return null;
1601 }
1602 return new ZoomThreadByEntry(entryList, startTime, endTime, resolution);
1603 }
1604
1605 private void makeActions() {
1606 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
1607 fPreviousResourceAction.setText(getPrevText());
1608 fPreviousResourceAction.setToolTipText(getPrevTooltip());
1609 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
1610 fNextResourceAction.setText(getNextText());
1611 fNextResourceAction.setToolTipText(getNextTooltip());
1612 }
1613
1614 private void contributeToActionBars() {
1615 IActionBars bars = getViewSite().getActionBars();
1616 fillLocalToolBar(bars.getToolBarManager());
1617 }
1618
1619 /**
1620 * Add actions to local tool bar manager
1621 *
1622 * @param manager the tool bar manager
1623 */
1624 protected void fillLocalToolBar(IToolBarManager manager) {
1625 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
1626 manager.add(fTimeGraphWrapper.getShowFilterDialogAction());
1627 }
1628 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
1629 manager.add(new Separator());
1630 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1631 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1632 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
1633 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getToggleBookmarkAction());
1634 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousBookmarkAction());
1635 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextBookmarkAction());
1636 manager.add(fPreviousResourceAction);
1637 manager.add(fNextResourceAction);
1638 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1639 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
1640 manager.add(new Separator());
1641 }
1642
1643 /**
1644 * @since 1.0
1645 */
1646 @Override
1647 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
1648 if (fTimeGraphWrapper == null) {
1649 return null;
1650 }
1651 return fTimeGraphWrapper.getTimeViewAlignmentInfo();
1652 }
1653
1654 /**
1655 * @since 1.0
1656 */
1657 @Override
1658 public int getAvailableWidth(int requestedOffset) {
1659 if (fTimeGraphWrapper == null) {
1660 return 0;
1661 }
1662 return fTimeGraphWrapper.getAvailableWidth(requestedOffset);
1663 }
1664
1665 /**
1666 * @since 1.0
1667 */
1668 @Override
1669 public void performAlign(int offset, int width) {
1670 if (fTimeGraphWrapper != null) {
1671 fTimeGraphWrapper.performAlign(offset, width);
1672 }
1673 }
1674 }
This page took 0.06598 seconds and 4 git commands to generate.