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