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