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