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