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