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