lttng: Fix filters not shown with LTTng 2.8
[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 */
271 private static ActionHandler fFindActionHandler;
272
273 /** The find handler activation */
274 private static IHandlerActivation fFindHandlerActivation;
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
1014 * @since 2.0
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) {
1468 synchronized (fBuildThreadMap) {
41cc4f90 1469 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
1cf25311
PT
1470 BuildThread buildThread = fBuildThreadMap.remove(trace);
1471 if (buildThread != null) {
1472 buildThread.cancel();
1473 }
4999a196
GB
1474 }
1475 }
4e94ae24 1476 fMarkerEventSourcesMap.remove(signal.getTrace());
4999a196
GB
1477 synchronized (fEntryListMap) {
1478 fEntryListMap.remove(signal.getTrace());
1479 }
4923d7b9 1480 fFiltersMap.remove(signal.getTrace());
1e5c4376 1481 fViewContext.remove(signal.getTrace());
4999a196
GB
1482 if (signal.getTrace() == fTrace) {
1483 fTrace = null;
7697e148 1484 fEditorFile = null;
335b04e6
PT
1485 fStartTime = SWT.DEFAULT;
1486 fEndTime = SWT.DEFAULT;
4999a196
GB
1487 if (fZoomThread != null) {
1488 fZoomThread.cancel();
6ae6c5bd 1489 fZoomThread = null;
4999a196
GB
1490 }
1491 refresh();
1492 }
1493 }
1494
1495 /**
97c71024 1496 * Handler for the selection range signal.
4999a196
GB
1497 *
1498 * @param signal
1499 * The signal that's received
97c71024 1500 * @since 1.0
4999a196
GB
1501 */
1502 @TmfSignalHandler
97c71024 1503 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
4999a196
GB
1504 if (signal.getSource() == this || fTrace == null) {
1505 return;
1506 }
16801c72
MK
1507 final long beginTime = signal.getBeginTime().toNanos();
1508 final long endTime = signal.getEndTime().toNanos();
4999a196
GB
1509
1510 Display.getDefault().asyncExec(new Runnable() {
1511 @Override
1512 public void run() {
747adf5c 1513 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1514 return;
1515 }
0fcf3b09 1516 if (beginTime == endTime) {
747adf5c 1517 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
0fcf3b09 1518 } else {
84c8aef7 1519 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
0fcf3b09 1520 }
64de182d 1521 synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getSelectionBegin());
4999a196
GB
1522 }
1523 });
1524 }
1525
1526 /**
97c71024 1527 * Handler for the window range signal.
4999a196
GB
1528 *
1529 * @param signal
1530 * The signal that's received
97c71024 1531 * @since 1.0
4999a196
GB
1532 */
1533 @TmfSignalHandler
97c71024 1534 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
4999a196
GB
1535 if (signal.getSource() == this || fTrace == null) {
1536 return;
1537 }
1538 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1539 return;
1540 }
16801c72
MK
1541 final long startTime = signal.getCurrentRange().getStartTime().toNanos();
1542 final long endTime = signal.getCurrentRange().getEndTime().toNanos();
4999a196
GB
1543 Display.getDefault().asyncExec(new Runnable() {
1544 @Override
1545 public void run() {
747adf5c 1546 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1547 return;
1548 }
747adf5c 1549 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196
GB
1550 startZoomThread(startTime, endTime);
1551 }
1552 });
1553 }
1554
c1cd9635
MAL
1555 /**
1556 * @param signal the format of the timestamps was updated.
1557 */
1558 @TmfSignalHandler
1559 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
747adf5c 1560 fTimeGraphWrapper.refresh();
c1cd9635
MAL
1561 }
1562
4999a196
GB
1563 // ------------------------------------------------------------------------
1564 // Internal
1565 // ------------------------------------------------------------------------
1566
4923d7b9 1567 private void loadTrace(final ITmfTrace trace) {
6ae6c5bd
PT
1568 if (fZoomThread != null) {
1569 fZoomThread.cancel();
1570 fZoomThread = null;
1571 }
4923d7b9
PT
1572 if (fTrace != null) {
1573 /* save the filters of the previous trace */
1574 fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
1e5c4376 1575 fViewContext.put(fTrace, new ViewContext(fCurrentSortColumn, fSortDirection, fTimeGraphWrapper.getSelection()));
4923d7b9
PT
1576 }
1577 fTrace = trace;
1e5c4376 1578 restoreViewContext();
9c274768 1579 fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
4999a196
GB
1580 synchronized (fEntryListMap) {
1581 fEntryList = fEntryListMap.get(fTrace);
1582 if (fEntryList == null) {
50c2da9e 1583 rebuild();
4999a196 1584 } else {
16801c72
MK
1585 fStartTime = fTrace.getStartTime().toNanos();
1586 fEndTime = fTrace.getEndTime().toNanos();
4999a196
GB
1587 refresh();
1588 }
1589 }
1590 }
1591
50c2da9e
GB
1592 /**
1593 * Forces a rebuild of the entries list, even if entries already exist for this trace
50c2da9e
GB
1594 */
1595 protected void rebuild() {
1596 setStartTime(Long.MAX_VALUE);
1597 setEndTime(Long.MIN_VALUE);
6b8d11bd 1598 refresh();
dfa0ef96
GB
1599 ITmfTrace viewTrace = fTrace;
1600 if (viewTrace == null) {
1601 return;
1602 }
4e94ae24 1603 List<IMarkerEventSource> markerEventSources = new ArrayList<>();
50c2da9e 1604 synchronized (fBuildThreadMap) {
dfa0ef96
GB
1605 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1606 if (trace == null) {
1607 break;
1608 }
4e94ae24 1609 markerEventSources.addAll(TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class));
dfa0ef96 1610 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
50c2da9e
GB
1611 fBuildThreadMap.put(trace, buildThread);
1612 buildThread.start();
1613 }
1614 }
4e94ae24 1615 fMarkerEventSourcesMap.put(viewTrace, markerEventSources);
50c2da9e
GB
1616 }
1617
4999a196
GB
1618 /**
1619 * Method called when synching to a given timestamp. Inheriting classes can
1620 * perform actions here to update the view at the given timestamp.
1621 *
1622 * @param time
1623 * The currently selected time
1624 */
1625 protected void synchingToTime(long time) {
1626
1627 }
1628
41cc4f90
GB
1629 /**
1630 * Return the list of traces whose data or analysis results will be used to
1631 * populate the view. By default, if the trace is an experiment, the traces
1632 * under it will be returned, otherwise, the trace itself is returned.
1633 *
1634 * A build thread will be started for each trace returned by this method,
1635 * some of which may receive events in live streaming mode.
1636 *
1637 * @param trace
1638 * The trace associated with this view
1639 * @return List of traces with data to display
41cc4f90 1640 */
dfa0ef96 1641 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
c14c0757 1642 return TmfTraceManager.getTraceSet(trace);
41cc4f90
GB
1643 }
1644
4999a196 1645 /**
f8f46a52
PT
1646 * Build the entry list to show in this time graph view.
1647 * <p>
1648 * Called from the BuildThread for each trace returned by
1649 * {@link #getTracesToBuild(ITmfTrace)}. The full event list is also
1650 * normally computed for every entry that is created.
4999a196
GB
1651 *
1652 * @param trace
1653 * The trace being built
1cf25311
PT
1654 * @param parentTrace
1655 * The parent of the trace set, or the trace itself
4999a196
GB
1656 * @param monitor
1657 * The progress monitor object
f8f46a52 1658 * @since 2.0
4999a196 1659 */
f8f46a52 1660 protected abstract void buildEntryList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
4999a196
GB
1661
1662 /**
f8f46a52
PT
1663 * Gets the list of event for an entry in a given time range.
1664 * <p>
1665 * Called from the ZoomThread for every entry to update the zoomed event
1666 * list. Can be an empty implementation if the view does not support zoomed
1667 * event lists. Can also be used to compute the full event list.
4999a196
GB
1668 *
1669 * @param entry
1670 * The entry to get events for
1671 * @param startTime
1672 * Start of the time range
1673 * @param endTime
1674 * End of the time range
1675 * @param resolution
1676 * The resolution
1677 * @param monitor
1678 * The progress monitor object
1679 * @return The list of events for the entry
1680 */
4c4e2816 1681 protected abstract @Nullable List<@NonNull ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
4999a196 1682 long startTime, long endTime, long resolution,
dfa0ef96 1683 @NonNull IProgressMonitor monitor);
4999a196 1684
bec1f1ac
GB
1685 /**
1686 * Gets the list of links (displayed as arrows) for a trace in a given
1687 * timerange. Default implementation returns an empty list.
1688 *
1689 * @param startTime
1690 * Start of the time range
1691 * @param endTime
1692 * End of the time range
1693 * @param resolution
1694 * The resolution
1695 * @param monitor
1696 * The progress monitor object
1697 * @return The list of link events
bec1f1ac 1698 */
4c4e2816 1699 protected @Nullable List<@NonNull ILinkEvent> getLinkList(long startTime, long endTime,
dfa0ef96 1700 long resolution, @NonNull IProgressMonitor monitor) {
507b1336 1701 return new ArrayList<>();
bec1f1ac
GB
1702 }
1703
91512088
PT
1704 /**
1705 * Gets the list of view-specific marker categories. Default implementation
1706 * returns an empty list.
1707 *
1708 * @return The list of marker categories
1709 * @since 2.0
1710 */
1711 protected @NonNull List<String> getViewMarkerCategories() {
1712 return new ArrayList<>();
1713 }
1714
e790b877 1715 /**
24333461
PT
1716 * Gets the list of view-specific markers for a trace in a given time range.
1717 * Default implementation returns an empty list.
e790b877
PT
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 marker events
1728 * @since 2.0
1729 */
24333461 1730 protected @NonNull List<IMarkerEvent> getViewMarkerList(long startTime, long endTime,
e790b877
PT
1731 long resolution, @NonNull IProgressMonitor monitor) {
1732 return new ArrayList<>();
1733 }
bec1f1ac 1734
24333461
PT
1735 /**
1736 * Gets the list of trace-specific markers for a trace in a given time range.
1737 *
1738 * @param startTime
1739 * Start of the time range
1740 * @param endTime
1741 * End of the time range
1742 * @param resolution
1743 * The resolution
1744 * @param monitor
1745 * The progress monitor object
1746 * @return The list of marker events
1747 * @since 2.0
1748 */
1749 protected @NonNull List<IMarkerEvent> getTraceMarkerList(long startTime, long endTime,
1750 long resolution, @NonNull IProgressMonitor monitor) {
1751 List<IMarkerEvent> markers = new ArrayList<>();
4e94ae24 1752 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
2f72084f
PT
1753 for (String category : markerEventSource.getMarkerCategories()) {
1754 if (monitor.isCanceled()) {
1755 break;
1756 }
0e4f957e 1757 markers.addAll(markerEventSource.getMarkerList(category, startTime, endTime, resolution, monitor));
24333461 1758 }
24333461
PT
1759 }
1760 return markers;
1761 }
1762
91512088
PT
1763 /**
1764 * Get the list of current marker categories.
1765 *
1766 * @return The list of marker categories
1767 * @since 2.0
1768 */
1769 private @NonNull List<String> getMarkerCategories() {
a924e2ed 1770 Set<String> categories = new LinkedHashSet<>(getViewMarkerCategories());
91512088
PT
1771 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
1772 categories.addAll(markerEventSource.getMarkerCategories());
1773 }
1774 return new ArrayList<>(categories);
1775 }
1776
24333461
PT
1777 /**
1778 * Gets the list of marker event sources for a given trace.
1779 *
1780 * @param trace
1781 * The trace
1782 * @return The list of marker event sources
1783 * @since 2.0
1784 */
91512088 1785 private @NonNull List<IMarkerEventSource> getMarkerEventSources(ITmfTrace trace) {
24333461
PT
1786 List<IMarkerEventSource> markerEventSources = fMarkerEventSourcesMap.get(trace);
1787 if (markerEventSources == null) {
0e4f957e 1788 markerEventSources = Collections.emptyList();
24333461
PT
1789 }
1790 return markerEventSources;
1791 }
1792
4999a196
GB
1793 /**
1794 * Refresh the display
1795 */
1796 protected void refresh() {
6ae6c5bd 1797 final boolean zoomThread = Thread.currentThread() instanceof ZoomThread;
08593856 1798 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
4999a196
GB
1799 @Override
1800 public void run() {
747adf5c 1801 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1802 return;
1803 }
f149d124
MAL
1804 fDirty.incrementAndGet();
1805
1cf25311 1806 boolean hasEntries = false;
4999a196
GB
1807 synchronized (fEntryListMap) {
1808 fEntryList = fEntryListMap.get(fTrace);
1809 if (fEntryList == null) {
1cf25311
PT
1810 fEntryList = new CopyOnWriteArrayList<>();
1811 } else if (fEntryComparator != null) {
1812 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1813 Collections.sort(list, fEntryComparator);
304e446c
PT
1814 for (ITimeGraphEntry entry : list) {
1815 sortChildren(entry, fEntryComparator);
1816 }
1cf25311
PT
1817 fEntryList.clear();
1818 fEntryList.addAll(list);
4999a196 1819 }
f3e09aa6 1820 hasEntries = !fEntryList.isEmpty();
4999a196 1821 }
f3e09aa6 1822 boolean inputChanged = fEntryList != fTimeGraphWrapper.getInput();
0eca62a1
BH
1823 TimeGraphCombo combo = getTimeGraphCombo();
1824 try {
1825 // Set redraw to false to only draw once
1826 if (combo != null) {
1827 combo.getTreeViewer().getTree().setRedraw(false);
1828 }
1829 getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
1830 if (inputChanged) {
1e5c4376
BH
1831 fTimeGraphWrapper.setInput(fEntryList);
1832 /* restore the previously saved filters, if any */
1833 fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
1834 fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
1835 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1836 fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
1837 fTimeGraphWrapper.getTimeGraphViewer().setMarkers(null);
1838 applyViewContext();
0eca62a1
BH
1839 } else {
1840 fTimeGraphWrapper.refresh();
1e5c4376 1841 }
0eca62a1
BH
1842 // reveal selection
1843 if (fIsRevealSelection) {
1844 fIsRevealSelection = false;
1845 ITimeGraphEntry entry1 = fTimeGraphWrapper.getSelection();
1846 fTimeGraphWrapper.setSelection(entry1);
1847 }
1848 } finally {
1849 if (combo != null) {
1850 combo.getTreeViewer().getTree().setRedraw(true);
1851 }
1852 getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
4999a196 1853 }
335b04e6
PT
1854 long startBound = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : fStartTime);
1855 long endBound = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : fEndTime);
1856 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(startBound, endBound);
4999a196 1857
21852dfa 1858 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
16801c72
MK
1859 long selectionBeginTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getStartTime().toNanos();
1860 long selectionEndTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getEndTime().toNanos();
1861 long startTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getStartTime().toNanos();
1862 long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().toNanos();
335b04e6
PT
1863 startTime = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : Math.max(startTime, fStartTime));
1864 endTime = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : Math.min(endTime, fEndTime));
84c8aef7 1865 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime, false);
747adf5c 1866 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196 1867
f3e09aa6
PT
1868 if (inputChanged && selectionBeginTime != SWT.DEFAULT) {
1869 synchingToTime(selectionBeginTime);
1870 }
1871
1cf25311 1872 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
747adf5c
PT
1873 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1874 column.pack();
1875 }
1cf25311
PT
1876 if (hasEntries) {
1877 fPackDone = true;
1878 }
4999a196
GB
1879 }
1880
6ae6c5bd
PT
1881 if (!zoomThread) {
1882 startZoomThread(startTime, endTime);
1883 }
f149d124 1884 fDirty.decrementAndGet();
4999a196
GB
1885 }
1886 });
1887 }
1888
1889 /**
1890 * Redraw the canvas
1891 */
1892 protected void redraw() {
1893 synchronized (fSyncObj) {
1894 if (fRedrawState == State.IDLE) {
1895 fRedrawState = State.BUSY;
1896 } else {
1897 fRedrawState = State.PENDING;
1898 return;
1899 }
1900 }
1901 Display.getDefault().asyncExec(new Runnable() {
1902 @Override
1903 public void run() {
747adf5c 1904 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1905 return;
1906 }
747adf5c
PT
1907 fTimeGraphWrapper.redraw();
1908 fTimeGraphWrapper.update();
4999a196
GB
1909 synchronized (fSyncObj) {
1910 if (fRedrawState == State.PENDING) {
1911 fRedrawState = State.IDLE;
1912 redraw();
1913 } else {
1914 fRedrawState = State.IDLE;
1915 }
1916 }
1917 }
1918 });
1919 }
1920
a4cddcbc 1921 private void sortChildren(ITimeGraphEntry entry, Comparator<ITimeGraphEntry> comparator) {
304e446c
PT
1922 if (entry instanceof TimeGraphEntry) {
1923 ((TimeGraphEntry) entry).sortChildren(comparator);
1924 }
1925 for (ITimeGraphEntry child : entry.getChildren()) {
1926 sortChildren(child, comparator);
1927 }
1928 }
1929
0c283816
PT
1930 /**
1931 * Start or restart the zoom thread.
1932 *
1933 * @param startTime
1934 * the zoom start time
1935 * @param endTime
1936 * the zoom end time
1937 * @since 2.0
1938 */
156e9ead 1939 protected final void startZoomThread(long startTime, long endTime) {
f149d124
MAL
1940 long clampedStartTime = Math.min(Math.max(startTime, fStartTime), fEndTime);
1941 long clampedEndTime = Math.max(Math.min(endTime, fEndTime), fStartTime);
156e9ead 1942 fDirty.incrementAndGet();
6ae6c5bd 1943 boolean restart = false;
4999a196
GB
1944 if (fZoomThread != null) {
1945 fZoomThread.cancel();
f149d124 1946 if (fZoomThread.fZoomStartTime == clampedStartTime && fZoomThread.fZoomEndTime == clampedEndTime) {
6ae6c5bd
PT
1947 restart = true;
1948 }
1949 }
f149d124
MAL
1950 long resolution = Math.max(1, (clampedEndTime - clampedStartTime) / fDisplayWidth);
1951 fZoomThread = createZoomThread(clampedStartTime, clampedEndTime, resolution, restart);
6ae6c5bd 1952 if (fZoomThread != null) {
6d28f3e8
MAL
1953 // Don't start a new thread right away if results are being applied
1954 // from an old ZoomThread. Otherwise, the old results might
1955 // overwrite the new results if it finishes after.
1956 synchronized (fZoomThreadResultLock) {
1957 fZoomThread.start();
1958 }
156e9ead
MAL
1959 } else {
1960 fDirty.decrementAndGet();
4999a196 1961 }
6ae6c5bd
PT
1962 }
1963
1964 /**
1965 * Create a zoom thread.
1966 *
1967 * @param startTime
1968 * the zoom start time
1969 * @param endTime
1970 * the zoom end time
1971 * @param resolution
1972 * the resolution
1973 * @param restart
1974 * true if restarting zoom for the same time range
1975 * @return a zoom thread
0336f981 1976 * @since 1.1
6ae6c5bd
PT
1977 */
1978 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
dfa0ef96
GB
1979 final List<TimeGraphEntry> entryList = fEntryList;
1980 if (entryList == null) {
6ae6c5bd 1981 return null;
dfa0ef96 1982 }
6ae6c5bd 1983 return new ZoomThreadByEntry(entryList, startTime, endTime, resolution);
4999a196
GB
1984 }
1985
1986 private void makeActions() {
747adf5c 1987 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
4999a196
GB
1988 fPreviousResourceAction.setText(getPrevText());
1989 fPreviousResourceAction.setToolTipText(getPrevTooltip());
747adf5c 1990 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
4999a196
GB
1991 fNextResourceAction.setText(getNextText());
1992 fNextResourceAction.setToolTipText(getNextTooltip());
1993 }
1994
1995 private void contributeToActionBars() {
1996 IActionBars bars = getViewSite().getActionBars();
1997 fillLocalToolBar(bars.getToolBarManager());
91512088 1998 fillLocalMenu(bars.getMenuManager());
4999a196
GB
1999 }
2000
79ec0b89
PT
2001 /**
2002 * Add actions to local tool bar manager
2003 *
2004 * @param manager the tool bar manager
2005 */
2006 protected void fillLocalToolBar(IToolBarManager manager) {
cfcfd964
PT
2007 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
2008 manager.add(fTimeGraphWrapper.getShowFilterDialogAction());
4999a196 2009 }
747adf5c 2010 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
4999a196 2011 manager.add(new Separator());
747adf5c
PT
2012 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
2013 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
2014 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
91512088 2015 manager.add(new Separator());
1d012443 2016 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getToggleBookmarkAction());
f72cd563
PT
2017 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousMarkerAction());
2018 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextMarkerAction());
91512088 2019 manager.add(new Separator());
4999a196
GB
2020 manager.add(fPreviousResourceAction);
2021 manager.add(fNextResourceAction);
747adf5c
PT
2022 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
2023 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
4999a196
GB
2024 manager.add(new Separator());
2025 }
d2e4afa7 2026
91512088
PT
2027 /**
2028 * Add actions to local menu manager
2029 *
2030 * @param manager the tool bar manager
2031 * @since 2.0
2032 */
2033 protected void fillLocalMenu(IMenuManager manager) {
2034 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getMarkersMenu());
2035 }
2036
d2e4afa7
MAL
2037 /**
2038 * @since 1.0
2039 */
2040 @Override
2041 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
2042 if (fTimeGraphWrapper == null) {
2043 return null;
2044 }
2045 return fTimeGraphWrapper.getTimeViewAlignmentInfo();
2046 }
2047
2048 /**
2049 * @since 1.0
2050 */
2051 @Override
2052 public int getAvailableWidth(int requestedOffset) {
2053 if (fTimeGraphWrapper == null) {
2054 return 0;
2055 }
2056 return fTimeGraphWrapper.getAvailableWidth(requestedOffset);
2057 }
2058
2059 /**
2060 * @since 1.0
2061 */
2062 @Override
2063 public void performAlign(int offset, int width) {
2064 if (fTimeGraphWrapper != null) {
2065 fTimeGraphWrapper.performAlign(offset, width);
2066 }
2067 }
156e9ead
MAL
2068
2069 /**
2070 * Returns whether or not the time graph view is dirty. The time graph view
2071 * is considered dirty if it has yet to completely update its model.
2072 *
f149d124
MAL
2073 * This method is meant to be used by tests in order to know when it is safe
2074 * to proceed.
2075 *
2076 * Note: If a trace is smaller than the initial window range (see
2077 * {@link ITmfTrace#getInitialRangeOffset}) this method will return true
2078 * forever.
2079 *
156e9ead
MAL
2080 * @return true if the time graph view has yet to completely update its
2081 * model, false otherwise
2082 * @since 2.0
2083 */
2084 public boolean isDirty() {
f149d124 2085 if (fTrace == null) {
156e9ead
MAL
2086 return false;
2087 }
f149d124
MAL
2088
2089 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
2090 long startTime = ctx.getWindowRange().getStartTime().toNanos();
2091 long endTime = ctx.getWindowRange().getEndTime().toNanos();
2092
2093 // If the time graph control hasn't updated all the way to the end of
2094 // the window range then it's dirty. A refresh should happen later.
2095 if (fTimeGraphWrapper.getTimeGraphViewer().getTime0() != startTime || fTimeGraphWrapper.getTimeGraphViewer().getTime1() != endTime) {
2096 return true;
2097 }
2098
2099 if (fZoomThread == null) {
2100 // The zoom thread is null but we might be just about to create it (refresh called).
2101 return fDirty.get() != 0;
2102 }
2103 // Dirty if the zoom thread is not done or if it hasn't zoomed all the
2104 // way to the end of the window range. In the latter case, there should be
2105 // a subsequent zoom thread that will be triggered.
2106 return fDirty.get() != 0 || fZoomThread.getZoomStartTime() != startTime || fZoomThread.getZoomEndTime() != endTime;
156e9ead
MAL
2107 }
2108
a4cddcbc
BH
2109 private void createColumnSelectionListener(TreeViewer treeViewer) {
2110 for (int i = 0; i < fColumnComparators.length; i++) {
1e5c4376
BH
2111 final int index = i;
2112 final Comparator<ITimeGraphEntry> comp = fColumnComparators[index];
a4cddcbc
BH
2113 final Tree tree = treeViewer.getTree();
2114 final TreeColumn column = tree.getColumn(i);
2115
2116 if (comp != null) {
2117 column.addSelectionListener(new SelectionAdapter() {
2118 @Override
2119 public void widgetSelected(SelectionEvent e) {
2120 TreeColumn prevSortcolumn = tree.getSortColumn();
1e5c4376 2121 int direction = tree.getSortDirection();
a4cddcbc 2122 if (prevSortcolumn == column) {
1e5c4376 2123 direction = (direction == SWT.DOWN) ? SWT.UP : SWT.DOWN;
a4cddcbc 2124 } else {
1e5c4376 2125 direction = SWT.DOWN;
a4cddcbc
BH
2126 }
2127 tree.setSortColumn(column);
1e5c4376
BH
2128 tree.setSortDirection(direction);
2129 fSortDirection = direction;
2130 fCurrentSortColumn = index;
a4cddcbc 2131 Comparator<ITimeGraphEntry> comparator = comp;
1e5c4376 2132
a4cddcbc 2133 if (comparator instanceof ITimeGraphEntryComparator) {
1e5c4376 2134 ((ITimeGraphEntryComparator) comparator).setDirection(direction);
a4cddcbc 2135 }
1e5c4376 2136 if (direction != SWT.DOWN) {
a4cddcbc
BH
2137 comparator = checkNotNull(Collections.reverseOrder(comparator));
2138 }
2139 setEntryComparator(comparator);
2140 fIsRevealSelection = true;
2141 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
2142 ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getControl().setFocus();
2143 }
2144 refresh();
2145 }
2146 });
2147 }
2148 }
2149 }
2150
82467e47
BH
2151 private void createDoubleClickListener(TreeViewer treeViewer) {
2152 treeViewer.addDoubleClickListener(event -> {
2153 if (event.getSelection() instanceof TreeSelection) {
2154 TreeSelection selection = (TreeSelection) event.getSelection();
2155 if (selection.getFirstElement() instanceof ITimeGraphEntry) {
2156 ITimeGraphEntry entry = (ITimeGraphEntry) selection.getFirstElement();
2157 if (entry.hasChildren()) {
2158 fTimeGraphWrapper.setExpandedState(entry, !fTimeGraphWrapper.getExpandedState(entry));
2159 }
2160 }
2161 }
2162 });
2163 }
2164
2165
1e5c4376
BH
2166 private void restoreViewContext() {
2167 TimeGraphCombo combo = getTimeGraphCombo();
2168 ViewContext viewContext = fViewContext.get(fTrace);
2169 if (combo != null) {
2170 if (fColumnComparators != null) {
2171 // restore sort settings
2172 fSortDirection = SWT.DOWN;
2173 fCurrentSortColumn = fInitialSortColumn;
2174 if (viewContext != null) {
2175 fSortDirection = viewContext.getSortDirection();
2176 fCurrentSortColumn = viewContext.getSortColumn();
2177 }
2178 if ((fCurrentSortColumn < fColumnComparators.length) && (fColumnComparators[fCurrentSortColumn] != null)) {
2179 Comparator<ITimeGraphEntry> comparator = fColumnComparators[fCurrentSortColumn];
2180 if (comparator instanceof ITimeGraphEntryComparator) {
2181 ((ITimeGraphEntryComparator) comparator).setDirection(fSortDirection);
2182 }
2183 if (fSortDirection != SWT.DOWN) {
2184 comparator = checkNotNull(Collections.reverseOrder(comparator));
2185 }
2186 setEntryComparator(comparator);
2187 }
a4cddcbc 2188 }
1e5c4376
BH
2189 }
2190 }
2191
2192 private void applyViewContext() {
2193 TimeGraphCombo combo = getTimeGraphCombo();
2194 ViewContext viewContext = fViewContext.get(fTrace);
2195 if (combo != null) {
2196 TreeViewer treeViewer = combo.getTreeViewer();
a4cddcbc 2197 final Tree tree = treeViewer.getTree();
1e5c4376
BH
2198 final TreeColumn column = tree.getColumn(fCurrentSortColumn);
2199 tree.setSortDirection(fSortDirection);
a4cddcbc 2200 tree.setSortColumn(column);
1e5c4376
BH
2201 combo.getTreeViewer().getControl().setFocus();
2202 }
2203 // restore and reveal selection
2204 if ((viewContext != null) && (viewContext.getSelection() != null)) {
2205 fTimeGraphWrapper.setSelection(viewContext.getSelection());
2206 }
2207 fViewContext.remove(fTrace);
2208 }
2209
2210 private static class ViewContext {
2211 private int fSortColumnIndex;
2212 private int fSortDirection;
2213 private @Nullable ITimeGraphEntry fSelection;
2214
2215 ViewContext(int sortColunm, int sortDirection, ITimeGraphEntry selection) {
2216 fSortColumnIndex = sortColunm;
2217 fSortDirection = sortDirection;
2218 fSelection = selection;
2219 }
2220 /**
2221 * @return the sortColumn
2222 */
2223 public int getSortColumn() {
2224 return fSortColumnIndex;
2225 }
2226 /**
2227 * @return the sortDirection
2228 */
2229 public int getSortDirection() {
2230 return fSortDirection;
2231 }
2232 /**
2233 * @return the selection
2234 */
2235 public ITimeGraphEntry getSelection() {
2236 return fSelection;
a4cddcbc
BH
2237 }
2238 }
90bb3a0c
BH
2239
2240 private void createContextMenu() {
2241 TimeGraphCombo combo = getTimeGraphCombo();
9bdf1671 2242 fEntryMenuManager.setRemoveAllWhenShown(true);
90bb3a0c 2243 if (combo != null) {
90bb3a0c
BH
2244 TreeViewer treeViewer = combo.getTreeViewer();
2245 Tree tree = treeViewer.getTree();
2246 Menu menu = fEntryMenuManager.createContextMenu(tree);
2247 tree.setMenu(menu);
9bdf1671
BH
2248 } else {
2249 TimeGraphControl timeGraphControl = getTimeGraphViewer().getTimeGraphControl();
2250 final Menu entryMenu = fEntryMenuManager.createContextMenu(timeGraphControl);
2251 timeGraphControl.addTimeGraphEntryMenuListener(new MenuDetectListener() {
90bb3a0c 2252 @Override
9bdf1671
BH
2253 public void menuDetected(MenuDetectEvent event) {
2254 Point p = timeGraphControl.toControl(event.x, event.y);
2255 /*
2256 * The TimeGraphControl will call the TimeGraphEntryMenuListener
2257 * before the TimeEventMenuListener. If the event is
2258 * triggered on the namespace then show the menu else
2259 * clear the menu.
2260 */
2261 if (p.x < getTimeGraphViewer().getNameSpace()) {
2262 timeGraphControl.setMenu(entryMenu);
2263 } else {
2264 timeGraphControl.setMenu(null);
2265 event.doit = false;
2266 }
90bb3a0c
BH
2267 }
2268 });
90bb3a0c 2269 }
9bdf1671
BH
2270 fEntryMenuManager.addMenuListener(new IMenuListener() {
2271 @Override
2272 public void menuAboutToShow(IMenuManager manager) {
f8f46a52 2273 fillTimeGraphEntryContextMenu(fEntryMenuManager);
9bdf1671
BH
2274 fEntryMenuManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
2275 }
2276 });
2277 getSite().registerContextMenu(fEntryMenuManager, fTimeGraphWrapper.getSelectionProvider());
90bb3a0c
BH
2278 }
2279
2280 /**
2281 * Fill context menu
2282 *
2283 * @param menuManager
2284 * a menuManager to fill
2285 * @since 2.0
2286 */
2287 protected void fillTimeGraphEntryContextMenu (@NonNull IMenuManager menuManager) {
36299425
JCK
2288 }
2289
2290 /*
2291 * Inner classes used for searching
2292 */
2293 class FindTarget {
2294 public ITimeGraphEntry getSelection() {
2295 return fTimeGraphWrapper.getSelection();
2296 }
90bb3a0c 2297
36299425
JCK
2298 public void selectAndReveal(@NonNull ITimeGraphEntry entry) {
2299 fTimeGraphWrapper.selectAndReveal(entry);
2300 }
2301
2302 public ITimeGraphEntry[] getEntries() {
2303 TimeGraphViewer viewer = getTimeGraphViewer();
2304 return viewer.getTimeGraphContentProvider().getElements(viewer.getInput());
2305 }
2306
2307 public Shell getShell() {
2308 return getSite().getShell();
2309 }
2310 }
2311
2312 class TimeGraphPartListener implements IPartListener {
2313 @Override
2314 public void partActivated(IWorkbenchPart part) {
2315 if (part == AbstractTimeGraphView.this) {
2316 synchronized (FIND_ACTION) {
2317 if (fFindActionHandler == null) {
2318 fFindActionHandler = new ActionHandler(FIND_ACTION);
2319 }
2320 final Object service = PlatformUI.getWorkbench().getService(IHandlerService.class);
2321 fFindHandlerActivation = ((IHandlerService) service).activateHandler(ActionFactory.FIND.getCommandId(), fFindActionHandler);
2322 }
2323 }
2324 // Notify action for all parts
2325 FIND_ACTION.partActivated(part);
2326 }
2327 @Override
2328 public void partDeactivated(IWorkbenchPart part) {
2329 if ((part == AbstractTimeGraphView.this) && (fFindHandlerActivation != null)) {
2330 final Object service = PlatformUI.getWorkbench().getService(IHandlerService.class);
2331 ((IHandlerService) service).deactivateHandler(fFindHandlerActivation);
2332 }
2333 }
2334 @Override
2335 public void partBroughtToTop(IWorkbenchPart part) {
2336 }
2337 @Override
2338 public void partClosed(IWorkbenchPart part) {
2339 }
2340 @Override
2341 public void partOpened(IWorkbenchPart part) {
2342 }
90bb3a0c 2343 }
4999a196 2344}
This page took 0.238112 seconds and 5 git commands to generate.