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