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