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