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