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