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