tmf: Allow AbstractTimeGraphView subclass to set filter content provider
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractTimeGraphView.java
CommitLineData
4999a196 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2012, 2015 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;
91512088 25import java.util.HashSet;
4999a196
GB
26import java.util.List;
27import java.util.Map;
91512088 28import java.util.Set;
1cf25311 29import java.util.concurrent.CopyOnWriteArrayList;
9c274768
PT
30import java.util.regex.Matcher;
31import java.util.regex.Pattern;
32
33import org.eclipse.core.resources.IFile;
34import org.eclipse.core.resources.IMarker;
35import org.eclipse.core.resources.IMarkerDelta;
36import org.eclipse.core.resources.IResource;
37import org.eclipse.core.resources.IResourceChangeEvent;
38import org.eclipse.core.resources.IResourceChangeListener;
39import org.eclipse.core.resources.IWorkspaceRunnable;
40import org.eclipse.core.resources.ResourcesPlugin;
41import org.eclipse.core.runtime.CoreException;
4999a196
GB
42import org.eclipse.core.runtime.IProgressMonitor;
43import org.eclipse.core.runtime.NullProgressMonitor;
dfa0ef96 44import org.eclipse.jdt.annotation.NonNull;
d2120fb6 45import org.eclipse.jdt.annotation.Nullable;
4999a196 46import org.eclipse.jface.action.Action;
747adf5c 47import org.eclipse.jface.action.IAction;
91512088 48import org.eclipse.jface.action.IMenuManager;
0fcf3b09 49import org.eclipse.jface.action.IStatusLineManager;
4999a196
GB
50import org.eclipse.jface.action.IToolBarManager;
51import org.eclipse.jface.action.Separator;
5d021ccf 52import org.eclipse.jface.viewers.AbstractTreeViewer;
40b7b614 53import org.eclipse.jface.viewers.ILabelProvider;
4999a196 54import org.eclipse.jface.viewers.ILabelProviderListener;
747adf5c 55import org.eclipse.jface.viewers.ISelectionProvider;
4999a196 56import org.eclipse.jface.viewers.ITableLabelProvider;
cfcfd964 57import org.eclipse.jface.viewers.ITreeContentProvider;
747adf5c 58import org.eclipse.jface.viewers.TreeViewer;
4923d7b9 59import org.eclipse.jface.viewers.ViewerFilter;
7697e148 60import org.eclipse.osgi.util.NLS;
4999a196 61import org.eclipse.swt.SWT;
9c274768 62import org.eclipse.swt.graphics.Color;
4999a196
GB
63import org.eclipse.swt.graphics.Image;
64import org.eclipse.swt.widgets.Composite;
65import org.eclipse.swt.widgets.Display;
66import org.eclipse.swt.widgets.TreeColumn;
9c274768 67import org.eclipse.tracecompass.internal.tmf.ui.Activator;
7697e148 68import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker;
97c71024 69import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
d2e4afa7 70import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
2bdf0193
AM
71import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
72import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
73import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
74import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
d2e4afa7 75import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
2bdf0193
AM
76import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
77import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
78import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
79import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
24333461 80import org.eclipse.tracecompass.tmf.core.trace.TmfTraceAdapterManager;
21852dfa 81import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
2bdf0193
AM
82import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
83import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
d2e4afa7
MAL
84import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
85import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
2bdf0193 86import org.eclipse.tracecompass.tmf.ui.views.TmfView;
9c274768 87import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphBookmarkListener;
2bdf0193
AM
88import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
89import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
90import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
91import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
92import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
9c274768 93import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphBookmarkEvent;
2bdf0193 94import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
d8a230f8 95import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
2bdf0193
AM
96import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
97import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
98import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
99import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
100import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
e790b877 101import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
24333461 102import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEventSource;
2bdf0193
AM
103import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
104import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
9c274768 105import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
2bdf0193
AM
106import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
107import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
4999a196
GB
108import org.eclipse.ui.IActionBars;
109
110/**
111 * An abstract view all time graph views can inherit
112 *
747adf5c
PT
113 * This view contains either a time graph viewer, or a time graph combo which is
114 * divided between a tree viewer on the left and a time graph viewer on the right.
4999a196 115 */
9c274768 116public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeAligned, IResourceChangeListener {
4999a196 117
5d021ccf
GB
118 /** Constant indicating that all levels of the time graph should be expanded */
119 protected static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
120
9c274768
PT
121 private static final Pattern RGBA_PATTERN = Pattern.compile("RGBA \\{(\\d+), (\\d+), (\\d+), (\\d+)\\}"); //$NON-NLS-1$
122
4999a196
GB
123 /**
124 * Redraw state enum
125 */
126 private enum State {
127 IDLE, BUSY, PENDING
128 }
129
130 // ------------------------------------------------------------------------
131 // Fields
132 // ------------------------------------------------------------------------
133
747adf5c
PT
134 /** The timegraph wrapper */
135 private ITimeGraphWrapper fTimeGraphWrapper;
4999a196
GB
136
137 /** The selected trace */
138 private ITmfTrace fTrace;
139
9c274768
PT
140 /** The selected trace editor file*/
141 private IFile fEditorFile;
142
4999a196
GB
143 /** The timegraph entry list */
144 private List<TimeGraphEntry> fEntryList;
145
146 /** The trace to entry list hash map */
507b1336 147 private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
4999a196 148
4923d7b9
PT
149 /** The trace to filters hash map */
150 private final Map<ITmfTrace, ViewerFilter[]> fFiltersMap = new HashMap<>();
151
24333461
PT
152 /** The trace to marker event sources hash map */
153 private final Map<ITmfTrace, List<IMarkerEventSource>> fMarkerEventSourcesMap = new HashMap<>();
154
1cf25311 155 /** The trace to build thread hash map */
507b1336 156 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
4999a196
GB
157
158 /** The start time */
335b04e6 159 private long fStartTime = SWT.DEFAULT;
4999a196
GB
160
161 /** The end time */
335b04e6 162 private long fEndTime = SWT.DEFAULT;
4999a196
GB
163
164 /** The display width */
165 private final int fDisplayWidth;
166
167 /** The zoom thread */
168 private ZoomThread fZoomThread;
169
170 /** The next resource action */
171 private Action fNextResourceAction;
172
173 /** The previous resource action */
174 private Action fPreviousResourceAction;
175
4999a196
GB
176 /** A comparator class */
177 private Comparator<ITimeGraphEntry> fEntryComparator = null;
178
1cf25311 179 /** The redraw state used to prevent unnecessary queuing of display runnables */
4999a196
GB
180 private State fRedrawState = State.IDLE;
181
182 /** The redraw synchronization object */
183 private final Object fSyncObj = new Object();
184
185 /** The presentation provider for this view */
186 private final TimeGraphPresentationProvider fPresentation;
187
747adf5c
PT
188 /** The tree column label array, or null if combo is not used */
189 private String[] fColumns;
190
191 /** The tree label provider, or null if combo is not used */
192 private TreeLabelProvider fLabelProvider = null;
193
a12aae87
GB
194 /** The time graph content provider */
195 private @NonNull ITimeGraphContentProvider fTimeGraphContentProvider = new TimeGraphContentProvider();
196
747adf5c 197 /** The relative weight of the sash, ignored if combo is not used */
59387be3 198 private int[] fWeight = { 1, 3 };
747adf5c
PT
199
200 /** The filter column label array, or null if filter is not used */
201 private String[] fFilterColumns;
4999a196 202
1cf25311
PT
203 /** The pack done flag */
204 private boolean fPackDone = false;
205
737792b6
PT
206 /** The filter content provider, or null if filter is not used */
207 private ITreeContentProvider fFilterContentProvider;
208
a03b7ee4
PT
209 /** The filter label provider, or null if filter is not used */
210 private TreeLabelProvider fFilterLabelProvider;
211
5d021ccf
GB
212 private int fAutoExpandLevel = ALL_LEVELS;
213
9c274768
PT
214 /** The list of color resources created by this view */
215 private final List<Color> fColors = new ArrayList<>();
216
4999a196 217 // ------------------------------------------------------------------------
747adf5c 218 // Classes
4999a196
GB
219 // ------------------------------------------------------------------------
220
747adf5c 221 private interface ITimeGraphWrapper {
4999a196 222
cfcfd964
PT
223 void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider);
224
225 void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider);
4999a196 226
747adf5c 227 TimeGraphViewer getTimeGraphViewer();
4999a196 228
cfcfd964 229 void addSelectionListener(ITimeGraphSelectionListener listener);
4999a196 230
747adf5c 231 ISelectionProvider getSelectionProvider();
4999a196 232
747adf5c 233 void setFocus();
4999a196 234
747adf5c 235 boolean isDisposed();
4999a196 236
747adf5c 237 void refresh();
4999a196 238
1cf25311
PT
239 void setInput(Object input);
240
241 Object getInput();
4999a196 242
4923d7b9
PT
243 void setFilters(ViewerFilter[] filters);
244
245 ViewerFilter[] getFilters();
246
747adf5c 247 void redraw();
4999a196 248
747adf5c 249 void update();
4999a196 250
5d021ccf
GB
251 void setAutoExpandLevel(int level);
252
cfcfd964
PT
253 void setFilterColumns(String[] columnNames);
254
255 void setFilterContentProvider(ITreeContentProvider contentProvider);
256
257 void setFilterLabelProvider(ITableLabelProvider labelProvider);
258
259 IAction getShowFilterDialogAction();
260
d2e4afa7
MAL
261 void performAlign(int offset, int width);
262
263 TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo();
264
265 int getAvailableWidth(int requestedOffset);
4999a196
GB
266 }
267
747adf5c
PT
268 private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
269 private TimeGraphViewer viewer;
4999a196 270
747adf5c
PT
271 private TimeGraphViewerWrapper(Composite parent, int style) {
272 viewer = new TimeGraphViewer(parent, style);
4999a196 273 }
4999a196 274
747adf5c 275 @Override
cfcfd964
PT
276 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
277 viewer.setTimeGraphContentProvider(timeGraphContentProvider);
278 }
279
280 @Override
281 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
282 viewer.setTimeGraphProvider(timeGraphPresentationProvider);
747adf5c 283 }
4999a196 284
747adf5c
PT
285 @Override
286 public TimeGraphViewer getTimeGraphViewer() {
287 return viewer;
288 }
4999a196 289
747adf5c
PT
290 @Override
291 public void addSelectionListener(ITimeGraphSelectionListener listener) {
292 viewer.addSelectionListener(listener);
293 }
4999a196 294
747adf5c
PT
295 @Override
296 public ISelectionProvider getSelectionProvider() {
297 return viewer.getSelectionProvider();
298 }
299
300 @Override
301 public void setFocus() {
302 viewer.setFocus();
303 }
304
305 @Override
306 public boolean isDisposed() {
307 return viewer.getControl().isDisposed();
308 }
309
310 @Override
1cf25311 311 public void setInput(Object input) {
747adf5c
PT
312 viewer.setInput(input);
313 }
314
1cf25311
PT
315 @Override
316 public Object getInput() {
317 return viewer.getInput();
318 }
319
cfcfd964
PT
320 @Override
321 public void setFilterColumns(String[] columnNames) {
322 viewer.setFilterColumns(columnNames);
323 }
324
325 @Override
326 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
327 viewer.setFilterContentProvider(contentProvider);
328 }
329
330 @Override
331 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
332 viewer.setFilterLabelProvider(labelProvider);
333 }
334
4923d7b9
PT
335 @Override
336 public void setFilters(ViewerFilter[] filters) {
337 viewer.setFilters(filters);
338 }
339
340 @Override
341 public ViewerFilter[] getFilters() {
342 return viewer.getFilters();
343 }
344
cfcfd964
PT
345 @Override
346 public IAction getShowFilterDialogAction() {
347 return viewer.getShowFilterDialogAction();
348 }
349
747adf5c
PT
350 @Override
351 public void refresh() {
352 viewer.refresh();
353 }
354
355 @Override
356 public void redraw() {
357 viewer.getControl().redraw();
358 }
359
360 @Override
361 public void update() {
362 viewer.getControl().update();
363 }
5d021ccf
GB
364
365 @Override
366 public void setAutoExpandLevel(int level) {
367 viewer.setAutoExpandLevel(level);
368 }
d2e4afa7
MAL
369
370 @Override
371 public void performAlign(int offset, int width) {
372 viewer.performAlign(offset, width);
373 }
374
375 @Override
376 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
377 return viewer.getTimeViewAlignmentInfo();
378 }
379
380 @Override
381 public int getAvailableWidth(int requestedOffset) {
382 return viewer.getAvailableWidth(requestedOffset);
383 }
4999a196
GB
384 }
385
747adf5c
PT
386 private class TimeGraphComboWrapper implements ITimeGraphWrapper {
387 private TimeGraphCombo combo;
388
389 private TimeGraphComboWrapper(Composite parent, int style) {
390 combo = new TimeGraphCombo(parent, style, fWeight);
391 }
392
393 @Override
cfcfd964
PT
394 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
395 combo.setTimeGraphContentProvider(timeGraphContentProvider);
396 }
397
398 @Override
399 public void setTimeGraphPresentationProvider(TimeGraphPresentationProvider timeGraphPresentationProvider) {
400 combo.setTimeGraphProvider(timeGraphPresentationProvider);
747adf5c
PT
401 }
402
403 @Override
404 public TimeGraphViewer getTimeGraphViewer() {
405 return combo.getTimeGraphViewer();
406 }
407
408 @Override
409 public void addSelectionListener(ITimeGraphSelectionListener listener) {
410 combo.addSelectionListener(listener);
411 }
412
413 @Override
414 public ISelectionProvider getSelectionProvider() {
415 return combo.getTreeViewer();
416 }
417
418 @Override
419 public void setFocus() {
420 combo.setFocus();
421 }
422
423 @Override
424 public boolean isDisposed() {
425 return combo.isDisposed();
426 }
427
428 @Override
1cf25311 429 public void setInput(Object input) {
747adf5c
PT
430 combo.setInput(input);
431 }
432
1cf25311
PT
433 @Override
434 public Object getInput() {
435 return combo.getInput();
436 }
437
cfcfd964
PT
438 @Override
439 public void setFilterColumns(String[] columnNames) {
440 combo.setFilterColumns(columnNames);
441 }
442
443 @Override
444 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
445 combo.setFilterContentProvider(contentProvider);
446 }
447
448 @Override
449 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
450 combo.setFilterLabelProvider(labelProvider);
451 }
452
4923d7b9
PT
453 @Override
454 public void setFilters(ViewerFilter[] filters) {
455 combo.setFilters(filters);
456 }
457
458 @Override
459 public ViewerFilter[] getFilters() {
460 return combo.getFilters();
461 }
462
cfcfd964
PT
463 @Override
464 public IAction getShowFilterDialogAction() {
465 return combo.getShowFilterDialogAction();
466 }
467
747adf5c
PT
468 @Override
469 public void refresh() {
470 combo.refresh();
471 }
472
473 @Override
474 public void redraw() {
475 combo.redraw();
476 }
477
478 @Override
479 public void update() {
480 combo.update();
481 }
482
5d021ccf
GB
483 @Override
484 public void setAutoExpandLevel(int level) {
485 combo.setAutoExpandLevel(level);
486 }
487
747adf5c
PT
488 TimeGraphCombo getTimeGraphCombo() {
489 return combo;
490 }
491
492 TreeViewer getTreeViewer() {
493 return combo.getTreeViewer();
494 }
495
d2e4afa7
MAL
496 @Override
497 public void performAlign(int offset, int width) {
498 combo.performAlign(offset, width);
499 }
500
501 @Override
502 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
503 return combo.getTimeViewAlignmentInfo();
504 }
505
506 @Override
507 public int getAvailableWidth(int requestedOffset) {
508 return combo.getAvailableWidth(requestedOffset);
509 }
747adf5c 510 }
4999a196 511
4999a196 512 /**
747adf5c
PT
513 * Base class to provide the labels for the tree viewer. Views extending
514 * this class typically need to override the getColumnText method if they
515 * have more than one column to display
4999a196 516 */
40b7b614 517 protected static class TreeLabelProvider implements ITableLabelProvider, ILabelProvider {
4999a196
GB
518
519 @Override
520 public void addListener(ILabelProviderListener listener) {
521 }
522
523 @Override
524 public void dispose() {
525 }
526
527 @Override
528 public boolean isLabelProperty(Object element, String property) {
529 return false;
530 }
531
532 @Override
533 public void removeListener(ILabelProviderListener listener) {
534 }
535
536 @Override
537 public Image getColumnImage(Object element, int columnIndex) {
538 return null;
539 }
540
541 @Override
542 public String getColumnText(Object element, int columnIndex) {
543 TimeGraphEntry entry = (TimeGraphEntry) element;
544 if (columnIndex == 0) {
545 return entry.getName();
546 }
76fccfb0 547 return new String();
4999a196
GB
548 }
549
40b7b614
GP
550 @Override
551 public Image getImage(Object element) {
552 return null;
553 }
554
40b7b614
GP
555 @Override
556 public String getText(Object element) {
557 TimeGraphEntry entry = (TimeGraphEntry) element;
558 return entry.getName();
559 }
560
4999a196
GB
561 }
562
563 private class BuildThread extends Thread {
dfa0ef96
GB
564 private final @NonNull ITmfTrace fBuildTrace;
565 private final @NonNull ITmfTrace fParentTrace;
566 private final @NonNull IProgressMonitor fMonitor;
4999a196 567
dfa0ef96 568 public BuildThread(final @NonNull ITmfTrace trace, final @NonNull ITmfTrace parentTrace, final String name) {
4999a196
GB
569 super(name + " build"); //$NON-NLS-1$
570 fBuildTrace = trace;
1cf25311 571 fParentTrace = parentTrace;
4999a196
GB
572 fMonitor = new NullProgressMonitor();
573 }
574
575 @Override
576 public void run() {
1cf25311 577 buildEventList(fBuildTrace, fParentTrace, fMonitor);
4999a196 578 synchronized (fBuildThreadMap) {
1cf25311 579 fBuildThreadMap.remove(fBuildTrace);
4999a196
GB
580 }
581 }
582
583 public void cancel() {
584 fMonitor.setCanceled(true);
585 }
586 }
587
6ae6c5bd
PT
588 /**
589 * Zoom thread
0336f981 590 * @since 1.1
6ae6c5bd
PT
591 */
592 protected abstract class ZoomThread extends Thread {
4999a196
GB
593 private final long fZoomStartTime;
594 private final long fZoomEndTime;
595 private final long fResolution;
dfa0ef96 596 private final @NonNull IProgressMonitor fMonitor;
4999a196 597
6ae6c5bd
PT
598 /**
599 * Constructor
600 *
601 * @param startTime
602 * the start time
603 * @param endTime
604 * the end time
605 * @param resolution
606 * the resolution
607 */
608 public ZoomThread(long startTime, long endTime, long resolution) {
609 super(AbstractTimeGraphView.this.getName() + " zoom"); //$NON-NLS-1$
4999a196
GB
610 fZoomStartTime = startTime;
611 fZoomEndTime = endTime;
6ae6c5bd 612 fResolution = resolution;
4999a196
GB
613 fMonitor = new NullProgressMonitor();
614 }
615
6ae6c5bd
PT
616 /**
617 * @return the zoom start time
618 */
619 public long getZoomStartTime() {
620 return fZoomStartTime;
621 }
622
623 /**
624 * @return the zoom end time
625 */
626 public long getZoomEndTime() {
627 return fZoomEndTime;
628 }
629
630 /**
631 * @return the resolution
632 */
633 public long getResolution() {
634 return fResolution;
635 }
636
637 /**
638 * @return the monitor
639 */
640 public @NonNull IProgressMonitor getMonitor() {
641 return fMonitor;
642 }
643
644 /**
645 * Cancel the zoom thread
646 */
647 public void cancel() {
648 fMonitor.setCanceled(true);
649 }
650 }
651
652 private class ZoomThreadByEntry extends ZoomThread {
653 private final @NonNull List<TimeGraphEntry> fZoomEntryList;
654
655 public ZoomThreadByEntry(@NonNull List<TimeGraphEntry> entryList, long startTime, long endTime, long resolution) {
656 super(startTime, endTime, resolution);
657 fZoomEntryList = entryList;
658 }
659
4999a196
GB
660 @Override
661 public void run() {
4999a196 662 for (TimeGraphEntry entry : fZoomEntryList) {
6ae6c5bd 663 if (getMonitor().isCanceled()) {
79ec0b89 664 return;
4999a196 665 }
dfa0ef96
GB
666 if (entry == null) {
667 break;
668 }
6ae6c5bd 669 zoom(entry, getMonitor());
4999a196 670 }
bec1f1ac 671 /* Refresh the arrows when zooming */
6ae6c5bd 672 List<ILinkEvent> events = getLinkList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
79ec0b89 673 if (events != null) {
747adf5c 674 fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
79ec0b89
PT
675 redraw();
676 }
24333461
PT
677 /* Refresh the view-specific markers when zooming */
678 List<IMarkerEvent> markers = new ArrayList<>(getViewMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
679 /* Refresh the trace-specific markers when zooming */
680 markers.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
f72cd563 681 fTimeGraphWrapper.getTimeGraphViewer().setMarkers(markers);
24333461 682 redraw();
4999a196
GB
683 }
684
dfa0ef96 685 private void zoom(@NonNull TimeGraphEntry entry, @NonNull IProgressMonitor monitor) {
6ae6c5bd 686 if (getZoomStartTime() <= fStartTime && getZoomEndTime() >= fEndTime) {
4999a196
GB
687 entry.setZoomedEventList(null);
688 } else {
6ae6c5bd 689 List<ITimeEvent> zoomedEventList = getEventList(entry, getZoomStartTime(), getZoomEndTime(), getResolution(), monitor);
4999a196
GB
690 if (zoomedEventList != null) {
691 entry.setZoomedEventList(zoomedEventList);
692 }
693 }
694 redraw();
a3188982 695 for (ITimeGraphEntry child : entry.getChildren()) {
6ae6c5bd 696 if (monitor.isCanceled()) {
4999a196
GB
697 return;
698 }
a3188982
PT
699 if (child instanceof TimeGraphEntry) {
700 zoom((TimeGraphEntry) child, monitor);
701 }
4999a196
GB
702 }
703 }
704
4999a196
GB
705 }
706
707 // ------------------------------------------------------------------------
708 // Constructors
709 // ------------------------------------------------------------------------
710
711 /**
747adf5c
PT
712 * Constructs a time graph view that contains either a time graph viewer or
713 * a time graph combo.
714 *
715 * By default, the view uses a time graph viewer. To use a time graph combo,
716 * the subclass constructor must call {@link #setTreeColumns(String[])} and
717 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
4999a196
GB
718 *
719 * @param id
720 * The id of the view
4999a196
GB
721 * @param pres
722 * The presentation provider
723 */
747adf5c 724 public AbstractTimeGraphView(String id, TimeGraphPresentationProvider pres) {
4999a196 725 super(id);
4999a196
GB
726 fPresentation = pres;
727 fDisplayWidth = Display.getDefault().getBounds().width;
728 }
729
730 // ------------------------------------------------------------------------
747adf5c 731 // Getters and setters
4999a196
GB
732 // ------------------------------------------------------------------------
733
747adf5c
PT
734 /**
735 * Getter for the time graph combo
736 *
737 * @return The time graph combo, or null if combo is not used
738 */
739 protected TimeGraphCombo getTimeGraphCombo() {
740 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
741 return ((TimeGraphComboWrapper) fTimeGraphWrapper).getTimeGraphCombo();
742 }
743 return null;
744 }
4999a196 745
747adf5c
PT
746 /**
747 * Getter for the time graph viewer
748 *
749 * @return The time graph viewer
750 */
751 protected TimeGraphViewer getTimeGraphViewer() {
752 return fTimeGraphWrapper.getTimeGraphViewer();
753 }
754
50c2da9e
GB
755 /**
756 * Getter for the presentation provider
757 *
758 * @return The time graph presentation provider
50c2da9e
GB
759 */
760 protected ITimeGraphPresentationProvider2 getPresentationProvider() {
761 return fPresentation;
762 }
763
747adf5c
PT
764 /**
765 * Sets the tree column labels.
766 * This should be called from the constructor.
767 *
768 * @param columns
769 * The array of tree column labels
770 */
771 protected void setTreeColumns(final String[] columns) {
772 fColumns = columns;
773 }
774
775 /**
776 * Sets the tree label provider.
777 * This should be called from the constructor.
778 *
779 * @param tlp
780 * The tree label provider
781 */
782 protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
783 fLabelProvider = tlp;
784 }
785
a12aae87
GB
786 /**
787 * Sets the time graph content provider. This should be called from the
788 * constructor.
789 *
790 * @param tgcp
791 * The time graph content provider
792 * @since 1.0
793 */
794 protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp) {
795 fTimeGraphContentProvider = tgcp;
796 }
797
747adf5c
PT
798 /**
799 * Sets the relative weight of each part of the time graph combo.
800 * This should be called from the constructor.
801 *
802 * @param weights
803 * The array (length 2) of relative weights of each part of the combo
804 */
805 protected void setWeight(final int[] weights) {
806 fWeight = weights;
807 }
4999a196 808
747adf5c
PT
809 /**
810 * Sets the filter column labels.
811 * This should be called from the constructor.
812 *
813 * @param filterColumns
814 * The array of filter column labels
815 */
816 protected void setFilterColumns(final String[] filterColumns) {
817 fFilterColumns = filterColumns;
818 }
4999a196 819
737792b6
PT
820 /**
821 * Sets the filter content provider.
822 * This should be called from the constructor.
823 *
824 * @param contentProvider
825 * The filter content provider
826 * @since 2.0
827 */
828 protected void setFilterContentProvider(final ITreeContentProvider contentProvider) {
829 fFilterContentProvider = contentProvider;
830 }
831
a03b7ee4
PT
832 /**
833 * Sets the filter label provider.
834 * This should be called from the constructor.
835 *
836 * @param labelProvider
837 * The filter label provider
a03b7ee4
PT
838 */
839 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
840 fFilterLabelProvider = labelProvider;
841 }
842
747adf5c
PT
843 /**
844 * Gets the display width
845 *
846 * @return the display width
847 */
848 protected int getDisplayWidth() {
849 return fDisplayWidth;
850 }
4999a196 851
747adf5c
PT
852 /**
853 * Gets the comparator for the entries
854 *
855 * @return The entry comparator
856 */
857 protected Comparator<ITimeGraphEntry> getEntryComparator() {
858 return fEntryComparator;
859 }
4999a196 860
747adf5c 861 /**
304e446c
PT
862 * Sets the comparator class for the entries.
863 * <p>
864 * This comparator will apply recursively to entries that implement
865 * {@link TimeGraphEntry#sortChildren(Comparator)}.
747adf5c
PT
866 *
867 * @param comparator
868 * A comparator object
869 */
870 protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) {
871 fEntryComparator = comparator;
872 }
4999a196 873
747adf5c
PT
874 /**
875 * Gets the trace displayed in the view
876 *
877 * @return The trace
878 */
879 protected ITmfTrace getTrace() {
880 return fTrace;
881 }
4999a196 882
747adf5c
PT
883 /**
884 * Gets the start time
885 *
886 * @return The start time
887 */
888 protected long getStartTime() {
889 return fStartTime;
890 }
4999a196 891
747adf5c
PT
892 /**
893 * Sets the start time
894 *
895 * @param time
896 * The start time
897 */
898 protected void setStartTime(long time) {
899 fStartTime = time;
900 }
901
902 /**
903 * Gets the end time
904 *
905 * @return The end time
906 */
907 protected long getEndTime() {
908 return fEndTime;
909 }
910
911 /**
912 * Sets the end time
913 *
914 * @param time
915 * The end time
916 */
917 protected void setEndTime(long time) {
918 fEndTime = time;
919 }
920
5d021ccf
GB
921 /**
922 * Sets the auto-expand level to be used for the input of the view. The
923 * value 0 means that there is no auto-expand; 1 means that top-level
924 * elements are expanded, but not their children; 2 means that top-level
925 * elements are expanded, and their children, but not grand-children; and so
926 * on.
927 * <p>
928 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
929 * </p>
930 *
931 * @param level
932 * non-negative level, or <code>ALL_LEVELS</code> to expand all
933 * levels of the tree
934 */
935 protected void setAutoExpandLevel(int level) {
936 fAutoExpandLevel = level;
937 ITimeGraphWrapper tgWrapper = fTimeGraphWrapper;
938 if (tgWrapper != null) {
939 tgWrapper.setAutoExpandLevel(level);
940 }
941 }
942
747adf5c 943 /**
1cf25311
PT
944 * Gets the entry list for a trace
945 *
946 * @param trace
947 * the trace
747adf5c
PT
948 *
949 * @return the entry list map
950 */
1cf25311
PT
951 protected List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
952 synchronized (fEntryListMap) {
953 return fEntryListMap.get(trace);
954 }
747adf5c
PT
955 }
956
957 /**
1cf25311 958 * Adds a trace entry list to the entry list map
747adf5c
PT
959 *
960 * @param trace
961 * the trace to add
962 * @param list
1cf25311 963 * the list of time graph entries
747adf5c
PT
964 */
965 protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
1cf25311
PT
966 synchronized (fEntryListMap) {
967 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
968 }
969 }
970
971 /**
972 * Adds a list of entries to a trace's entry list
973 *
974 * @param trace
975 * the trace
976 * @param list
977 * the list of time graph entries to add
1cf25311
PT
978 */
979 protected void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
980 synchronized (fEntryListMap) {
981 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
982 if (entryList == null) {
983 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
984 } else {
985 entryList.addAll(list);
986 }
987 }
988 }
989
990 /**
991 * Removes a list of entries from a trace's entry list
992 *
993 * @param trace
994 * the trace
995 * @param list
996 * the list of time graph entries to remove
1cf25311
PT
997 */
998 protected void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
999 synchronized (fEntryListMap) {
1000 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
1001 if (entryList != null) {
1002 entryList.removeAll(list);
1003 }
747adf5c
PT
1004 }
1005 }
4999a196 1006
747adf5c
PT
1007 /**
1008 * Text for the "next" button
1009 *
1010 * @return The "next" button text
1011 */
1012 protected String getNextText() {
1013 return Messages.AbstractTimeGraphtView_NextText;
1014 }
4999a196 1015
747adf5c
PT
1016 /**
1017 * Tooltip for the "next" button
1018 *
1019 * @return Tooltip for the "next" button
1020 */
1021 protected String getNextTooltip() {
1022 return Messages.AbstractTimeGraphView_NextTooltip;
1023 }
4999a196 1024
747adf5c
PT
1025 /**
1026 * Text for the "Previous" button
1027 *
1028 * @return The "Previous" button text
1029 */
1030 protected String getPrevText() {
1031 return Messages.AbstractTimeGraphView_PreviousText;
1032 }
4999a196 1033
747adf5c
PT
1034 /**
1035 * Tooltip for the "previous" button
1036 *
1037 * @return Tooltip for the "previous" button
1038 */
1039 protected String getPrevTooltip() {
1040 return Messages.AbstractTimeGraphView_PreviousTooltip;
1041 }
4999a196 1042
747adf5c
PT
1043 // ------------------------------------------------------------------------
1044 // ViewPart
1045 // ------------------------------------------------------------------------
4999a196 1046
747adf5c
PT
1047 @Override
1048 public void createPartControl(Composite parent) {
d2e4afa7 1049 super.createPartControl(parent);
747adf5c
PT
1050 if (fColumns == null || fLabelProvider == null) {
1051 fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
1052 } else {
1053 TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
1054 fTimeGraphWrapper = wrapper;
1055 TimeGraphCombo combo = wrapper.getTimeGraphCombo();
a12aae87 1056 combo.setTreeContentProvider(fTimeGraphContentProvider);
747adf5c
PT
1057 combo.setTreeLabelProvider(fLabelProvider);
1058 combo.setTreeColumns(fColumns);
747adf5c 1059 }
cfcfd964 1060 fTimeGraphWrapper.setTimeGraphContentProvider(fTimeGraphContentProvider);
737792b6 1061 fTimeGraphWrapper.setFilterContentProvider(fFilterContentProvider != null ? fFilterContentProvider : fTimeGraphContentProvider);
cfcfd964
PT
1062 fTimeGraphWrapper.setFilterLabelProvider(fFilterLabelProvider);
1063 fTimeGraphWrapper.setFilterColumns(fFilterColumns);
4999a196 1064
cfcfd964 1065 fTimeGraphWrapper.setTimeGraphPresentationProvider(fPresentation);
5d021ccf 1066 fTimeGraphWrapper.setAutoExpandLevel(fAutoExpandLevel);
4999a196 1067
747adf5c 1068 fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
4999a196
GB
1069 @Override
1070 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
1071 final long startTime = event.getStartTime();
1072 final long endTime = event.getEndTime();
f566d40a 1073 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
97c71024 1074 broadcast(new TmfWindowRangeUpdatedSignal(AbstractTimeGraphView.this, range));
4999a196
GB
1075 startZoomThread(startTime, endTime);
1076 }
1077 });
1078
747adf5c 1079 fTimeGraphWrapper.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
4999a196
GB
1080 @Override
1081 public void timeSelected(TimeGraphTimeEvent event) {
f566d40a
PT
1082 TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime());
1083 TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime());
97c71024 1084 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractTimeGraphView.this, startTime, endTime));
4999a196
GB
1085 }
1086 });
1087
9c274768
PT
1088 fTimeGraphWrapper.getTimeGraphViewer().addBookmarkListener(new ITimeGraphBookmarkListener() {
1089 @Override
1090 public void bookmarkAdded(final TimeGraphBookmarkEvent event) {
1091 try {
1092 ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
1093 @Override
1094 public void run(IProgressMonitor monitor) throws CoreException {
1095 IMarkerEvent bookmark = event.getBookmark();
1096 IMarker marker = fEditorFile.createMarker(IMarker.BOOKMARK);
1097 marker.setAttribute(IMarker.MESSAGE, bookmark.getLabel());
7697e148 1098 marker.setAttribute(ITmfMarker.MARKER_TIME, Long.toString(bookmark.getTime()));
9c274768 1099 if (bookmark.getDuration() > 0) {
7697e148 1100 marker.setAttribute(ITmfMarker.MARKER_DURATION, Long.toString(bookmark.getDuration()));
9c274768 1101 marker.setAttribute(IMarker.LOCATION,
7697e148
PT
1102 NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTimeRange,
1103 new TmfNanoTimestamp(bookmark.getTime()),
1104 new TmfNanoTimestamp(bookmark.getTime() + bookmark.getDuration())));
9c274768
PT
1105 } else {
1106 marker.setAttribute(IMarker.LOCATION,
7697e148
PT
1107 NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTime,
1108 new TmfNanoTimestamp(bookmark.getTime())));
9c274768 1109 }
7697e148 1110 marker.setAttribute(ITmfMarker.MARKER_COLOR, bookmark.getColor().getRGBA().toString());
9c274768
PT
1111 }
1112 }, null);
1113 } catch (CoreException e) {
1114 Activator.getDefault().logError(e.getMessage());
1115 }
1116 }
1117
1118 @Override
1119 public void bookmarkRemoved(TimeGraphBookmarkEvent event) {
1120 try {
1121 IMarkerEvent bookmark = event.getBookmark();
1122 IMarker[] markers = fEditorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1123 for (IMarker marker : markers) {
1124 if (bookmark.getLabel().equals(marker.getAttribute(IMarker.MESSAGE)) &&
7697e148
PT
1125 Long.toString(bookmark.getTime()).equals(marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null)) &&
1126 Long.toString(bookmark.getDuration()).equals(marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0))) &&
1127 bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(ITmfMarker.MARKER_COLOR))) {
9c274768
PT
1128 marker.delete();
1129 break;
1130 }
1131 }
1132 } catch (CoreException e) {
1133 Activator.getDefault().logError(e.getMessage());
1134 }
1135 }
1136 });
1137
747adf5c 1138 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
4999a196 1139
0fcf3b09 1140 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
747adf5c 1141 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
0fcf3b09 1142
4999a196
GB
1143 // View Action Handling
1144 makeActions();
1145 contributeToActionBars();
1146
21852dfa 1147 ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
4999a196
GB
1148 if (trace != null) {
1149 traceSelected(new TmfTraceSelectedSignal(this, trace));
1150 }
1151
1152 // make selection available to other views
747adf5c 1153 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
9c274768
PT
1154
1155 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
4999a196
GB
1156 }
1157
1158 @Override
1159 public void setFocus() {
747adf5c 1160 fTimeGraphWrapper.setFocus();
4999a196
GB
1161 }
1162
9c274768
PT
1163 @Override
1164 public void dispose() {
1165 super.dispose();
1166 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
1167 }
1168
1169 /**
1170 * @since 2.0
1171 */
1172 @Override
1173 public void resourceChanged(final IResourceChangeEvent event) {
1174 for (final IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
1175 if (delta.getResource().equals(fEditorFile)) {
1176 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
1177 redraw();
1178 return;
1179 }
1180 }
1181 }
1182
1183 private List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
1184 List<IMarkerEvent> bookmarks = new ArrayList<>();
7697e148
PT
1185 for (Color color : fColors) {
1186 color.dispose();
1187 }
1188 fColors.clear();
1189 if (editorFile == null || !editorFile.exists()) {
1190 return bookmarks;
1191 }
9c274768 1192 try {
9c274768
PT
1193 IMarker[] markers = editorFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
1194 for (IMarker marker : markers) {
1195 String label = marker.getAttribute(IMarker.MESSAGE, (String) null);
7697e148
PT
1196 String time = marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null);
1197 String duration = marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0));
1198 String rgba = marker.getAttribute(ITmfMarker.MARKER_COLOR, (String) null);
9c274768
PT
1199 if (label != null && time != null && rgba != null) {
1200 Matcher matcher = RGBA_PATTERN.matcher(rgba);
1201 if (matcher.matches()) {
1202 try {
1203 int red = Integer.valueOf(matcher.group(1));
1204 int green = Integer.valueOf(matcher.group(2));
1205 int blue = Integer.valueOf(matcher.group(3));
1206 int alpha = Integer.valueOf(matcher.group(4));
1207 Color color = new Color(Display.getDefault(), red, green, blue, alpha);
1208 fColors.add(color);
91512088 1209 bookmarks.add(new MarkerEvent(null, Long.valueOf(time), Long.valueOf(duration), IMarkerEvent.BOOKMARKS, color, label, true));
9c274768
PT
1210 } catch (NumberFormatException e) {
1211 Activator.getDefault().logError(e.getMessage());
1212 }
1213 }
1214 }
1215 }
1216 } catch (CoreException e) {
1217 Activator.getDefault().logError(e.getMessage());
1218 }
1219 return bookmarks;
1220 }
1221
4999a196
GB
1222 // ------------------------------------------------------------------------
1223 // Signal handlers
1224 // ------------------------------------------------------------------------
1225
1226 /**
1227 * Handler for the trace opened signal.
1228 *
1229 * @param signal
1230 * The incoming signal
4999a196
GB
1231 */
1232 @TmfSignalHandler
1233 public void traceOpened(TmfTraceOpenedSignal signal) {
4923d7b9 1234 loadTrace(signal.getTrace());
4999a196
GB
1235 }
1236
1237 /**
1238 * Handler for the trace selected signal
1239 *
1240 * @param signal
1241 * The incoming signal
1242 */
1243 @TmfSignalHandler
1244 public void traceSelected(final TmfTraceSelectedSignal signal) {
1245 if (signal.getTrace() == fTrace) {
1246 return;
1247 }
4923d7b9 1248 loadTrace(signal.getTrace());
4999a196
GB
1249 }
1250
1251 /**
1252 * Trace is closed: clear the data structures and the view
1253 *
1254 * @param signal
1255 * the signal received
1256 */
1257 @TmfSignalHandler
1258 public void traceClosed(final TmfTraceClosedSignal signal) {
1259 synchronized (fBuildThreadMap) {
41cc4f90 1260 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
1cf25311
PT
1261 BuildThread buildThread = fBuildThreadMap.remove(trace);
1262 if (buildThread != null) {
1263 buildThread.cancel();
1264 }
4999a196
GB
1265 }
1266 }
4e94ae24 1267 fMarkerEventSourcesMap.remove(signal.getTrace());
4999a196
GB
1268 synchronized (fEntryListMap) {
1269 fEntryListMap.remove(signal.getTrace());
1270 }
4923d7b9 1271 fFiltersMap.remove(signal.getTrace());
4999a196
GB
1272 if (signal.getTrace() == fTrace) {
1273 fTrace = null;
7697e148 1274 fEditorFile = null;
335b04e6
PT
1275 fStartTime = SWT.DEFAULT;
1276 fEndTime = SWT.DEFAULT;
4999a196
GB
1277 if (fZoomThread != null) {
1278 fZoomThread.cancel();
6ae6c5bd 1279 fZoomThread = null;
4999a196
GB
1280 }
1281 refresh();
1282 }
1283 }
1284
1285 /**
97c71024 1286 * Handler for the selection range signal.
4999a196
GB
1287 *
1288 * @param signal
1289 * The signal that's received
97c71024 1290 * @since 1.0
4999a196
GB
1291 */
1292 @TmfSignalHandler
97c71024 1293 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
4999a196
GB
1294 if (signal.getSource() == this || fTrace == null) {
1295 return;
1296 }
0fcf3b09
PT
1297 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1298 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
4999a196
GB
1299
1300 Display.getDefault().asyncExec(new Runnable() {
1301 @Override
1302 public void run() {
747adf5c 1303 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1304 return;
1305 }
0fcf3b09 1306 if (beginTime == endTime) {
747adf5c 1307 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
0fcf3b09 1308 } else {
84c8aef7 1309 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
0fcf3b09 1310 }
64de182d 1311 synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getSelectionBegin());
4999a196
GB
1312 }
1313 });
1314 }
1315
1316 /**
97c71024 1317 * Handler for the window range signal.
4999a196
GB
1318 *
1319 * @param signal
1320 * The signal that's received
97c71024 1321 * @since 1.0
4999a196
GB
1322 */
1323 @TmfSignalHandler
97c71024 1324 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
4999a196
GB
1325 if (signal.getSource() == this || fTrace == null) {
1326 return;
1327 }
1328 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
1329 return;
1330 }
1331 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1332 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
4999a196
GB
1333 Display.getDefault().asyncExec(new Runnable() {
1334 @Override
1335 public void run() {
747adf5c 1336 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1337 return;
1338 }
747adf5c 1339 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196
GB
1340 startZoomThread(startTime, endTime);
1341 }
1342 });
1343 }
1344
c1cd9635
MAL
1345 /**
1346 * @param signal the format of the timestamps was updated.
1347 */
1348 @TmfSignalHandler
1349 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
747adf5c 1350 fTimeGraphWrapper.refresh();
c1cd9635
MAL
1351 }
1352
4999a196
GB
1353 // ------------------------------------------------------------------------
1354 // Internal
1355 // ------------------------------------------------------------------------
1356
4923d7b9 1357 private void loadTrace(final ITmfTrace trace) {
6ae6c5bd
PT
1358 if (fZoomThread != null) {
1359 fZoomThread.cancel();
1360 fZoomThread = null;
1361 }
4923d7b9
PT
1362 if (fTrace != null) {
1363 /* save the filters of the previous trace */
1364 fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
1365 }
1366 fTrace = trace;
9c274768 1367 fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
4999a196
GB
1368 synchronized (fEntryListMap) {
1369 fEntryList = fEntryListMap.get(fTrace);
1370 if (fEntryList == null) {
50c2da9e 1371 rebuild();
4999a196
GB
1372 } else {
1373 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1374 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1375 refresh();
1376 }
1377 }
1378 }
1379
50c2da9e
GB
1380 /**
1381 * Forces a rebuild of the entries list, even if entries already exist for this trace
50c2da9e
GB
1382 */
1383 protected void rebuild() {
1384 setStartTime(Long.MAX_VALUE);
1385 setEndTime(Long.MIN_VALUE);
6b8d11bd 1386 refresh();
dfa0ef96
GB
1387 ITmfTrace viewTrace = fTrace;
1388 if (viewTrace == null) {
1389 return;
1390 }
4e94ae24 1391 List<IMarkerEventSource> markerEventSources = new ArrayList<>();
50c2da9e 1392 synchronized (fBuildThreadMap) {
dfa0ef96
GB
1393 for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
1394 if (trace == null) {
1395 break;
1396 }
4e94ae24 1397 markerEventSources.addAll(TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class));
dfa0ef96 1398 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
50c2da9e
GB
1399 fBuildThreadMap.put(trace, buildThread);
1400 buildThread.start();
1401 }
1402 }
4e94ae24 1403 fMarkerEventSourcesMap.put(viewTrace, markerEventSources);
50c2da9e
GB
1404 }
1405
4999a196
GB
1406 /**
1407 * Method called when synching to a given timestamp. Inheriting classes can
1408 * perform actions here to update the view at the given timestamp.
1409 *
1410 * @param time
1411 * The currently selected time
1412 */
1413 protected void synchingToTime(long time) {
1414
1415 }
1416
41cc4f90
GB
1417 /**
1418 * Return the list of traces whose data or analysis results will be used to
1419 * populate the view. By default, if the trace is an experiment, the traces
1420 * under it will be returned, otherwise, the trace itself is returned.
1421 *
1422 * A build thread will be started for each trace returned by this method,
1423 * some of which may receive events in live streaming mode.
1424 *
1425 * @param trace
1426 * The trace associated with this view
1427 * @return List of traces with data to display
41cc4f90 1428 */
dfa0ef96 1429 protected @NonNull Iterable<ITmfTrace> getTracesToBuild(@NonNull ITmfTrace trace) {
c14c0757 1430 return TmfTraceManager.getTraceSet(trace);
41cc4f90
GB
1431 }
1432
4999a196
GB
1433 /**
1434 * Build the entries list to show in this time graph
1435 *
1436 * Called from the BuildThread
1437 *
1438 * @param trace
1439 * The trace being built
1cf25311
PT
1440 * @param parentTrace
1441 * The parent of the trace set, or the trace itself
4999a196
GB
1442 * @param monitor
1443 * The progress monitor object
1444 */
dfa0ef96 1445 protected abstract void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor);
4999a196
GB
1446
1447 /**
1448 * Gets the list of event for an entry in a given timerange
1449 *
1450 * @param entry
1451 * The entry to get events for
1452 * @param startTime
1453 * Start of the time range
1454 * @param endTime
1455 * End of the time range
1456 * @param resolution
1457 * The resolution
1458 * @param monitor
1459 * The progress monitor object
1460 * @return The list of events for the entry
1461 */
4c4e2816 1462 protected abstract @Nullable List<@NonNull ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
4999a196 1463 long startTime, long endTime, long resolution,
dfa0ef96 1464 @NonNull IProgressMonitor monitor);
4999a196 1465
bec1f1ac
GB
1466 /**
1467 * Gets the list of links (displayed as arrows) for a trace in a given
1468 * timerange. Default implementation returns an empty list.
1469 *
1470 * @param startTime
1471 * Start of the time range
1472 * @param endTime
1473 * End of the time range
1474 * @param resolution
1475 * The resolution
1476 * @param monitor
1477 * The progress monitor object
1478 * @return The list of link events
bec1f1ac 1479 */
4c4e2816 1480 protected @Nullable List<@NonNull ILinkEvent> getLinkList(long startTime, long endTime,
dfa0ef96 1481 long resolution, @NonNull IProgressMonitor monitor) {
507b1336 1482 return new ArrayList<>();
bec1f1ac
GB
1483 }
1484
91512088
PT
1485 /**
1486 * Gets the list of view-specific marker categories. Default implementation
1487 * returns an empty list.
1488 *
1489 * @return The list of marker categories
1490 * @since 2.0
1491 */
1492 protected @NonNull List<String> getViewMarkerCategories() {
1493 return new ArrayList<>();
1494 }
1495
e790b877 1496 /**
24333461
PT
1497 * Gets the list of view-specific markers for a trace in a given time range.
1498 * Default implementation returns an empty list.
e790b877
PT
1499 *
1500 * @param startTime
1501 * Start of the time range
1502 * @param endTime
1503 * End of the time range
1504 * @param resolution
1505 * The resolution
1506 * @param monitor
1507 * The progress monitor object
1508 * @return The list of marker events
1509 * @since 2.0
1510 */
24333461 1511 protected @NonNull List<IMarkerEvent> getViewMarkerList(long startTime, long endTime,
e790b877
PT
1512 long resolution, @NonNull IProgressMonitor monitor) {
1513 return new ArrayList<>();
1514 }
bec1f1ac 1515
24333461
PT
1516 /**
1517 * Gets the list of trace-specific markers for a trace in a given time range.
1518 *
1519 * @param startTime
1520 * Start of the time range
1521 * @param endTime
1522 * End of the time range
1523 * @param resolution
1524 * The resolution
1525 * @param monitor
1526 * The progress monitor object
1527 * @return The list of marker events
1528 * @since 2.0
1529 */
1530 protected @NonNull List<IMarkerEvent> getTraceMarkerList(long startTime, long endTime,
1531 long resolution, @NonNull IProgressMonitor monitor) {
1532 List<IMarkerEvent> markers = new ArrayList<>();
4e94ae24 1533 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
2f72084f
PT
1534 for (String category : markerEventSource.getMarkerCategories()) {
1535 if (monitor.isCanceled()) {
1536 break;
1537 }
1538 markers.addAll(markerEventSource.getMarkerList(checkNotNull(category), startTime, endTime, resolution, monitor));
24333461 1539 }
24333461
PT
1540 }
1541 return markers;
1542 }
1543
91512088
PT
1544 /**
1545 * Get the list of current marker categories.
1546 *
1547 * @return The list of marker categories
1548 * @since 2.0
1549 */
1550 private @NonNull List<String> getMarkerCategories() {
1551 Set<String> categories = new HashSet<>(getViewMarkerCategories());
1552 for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
1553 categories.addAll(markerEventSource.getMarkerCategories());
1554 }
1555 return new ArrayList<>(categories);
1556 }
1557
24333461
PT
1558 /**
1559 * Gets the list of marker event sources for a given trace.
1560 *
1561 * @param trace
1562 * The trace
1563 * @return The list of marker event sources
1564 * @since 2.0
1565 */
91512088 1566 private @NonNull List<IMarkerEventSource> getMarkerEventSources(ITmfTrace trace) {
24333461
PT
1567 List<IMarkerEventSource> markerEventSources = fMarkerEventSourcesMap.get(trace);
1568 if (markerEventSources == null) {
1569 markerEventSources = checkNotNull(Collections.<IMarkerEventSource>emptyList());
1570 }
1571 return markerEventSources;
1572 }
1573
4999a196
GB
1574 /**
1575 * Refresh the display
1576 */
1577 protected void refresh() {
6ae6c5bd 1578 final boolean zoomThread = Thread.currentThread() instanceof ZoomThread;
08593856 1579 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
4999a196
GB
1580 @Override
1581 public void run() {
747adf5c 1582 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1583 return;
1584 }
1cf25311 1585 boolean hasEntries = false;
4999a196
GB
1586 synchronized (fEntryListMap) {
1587 fEntryList = fEntryListMap.get(fTrace);
1588 if (fEntryList == null) {
1cf25311
PT
1589 fEntryList = new CopyOnWriteArrayList<>();
1590 } else if (fEntryComparator != null) {
1591 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1592 Collections.sort(list, fEntryComparator);
304e446c
PT
1593 for (ITimeGraphEntry entry : list) {
1594 sortChildren(entry, fEntryComparator);
1595 }
1cf25311
PT
1596 fEntryList.clear();
1597 fEntryList.addAll(list);
4999a196 1598 }
1cf25311 1599 hasEntries = fEntryList.size() != 0;
4999a196 1600 }
1cf25311
PT
1601 if (fEntryList != fTimeGraphWrapper.getInput()) {
1602 fTimeGraphWrapper.setInput(fEntryList);
4923d7b9
PT
1603 /* restore the previously saved filters, if any */
1604 fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
6ae6c5bd 1605 fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
9c274768 1606 fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
91512088 1607 fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
6d5b0ba1 1608 fTimeGraphWrapper.getTimeGraphViewer().setMarkers(null);
1cf25311
PT
1609 } else {
1610 fTimeGraphWrapper.refresh();
4999a196 1611 }
335b04e6
PT
1612 long startBound = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : fStartTime);
1613 long endBound = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : fEndTime);
1614 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(startBound, endBound);
4999a196 1615
21852dfa 1616 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
335b04e6
PT
1617 long selectionBeginTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1618 long selectionEndTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1619 long startTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1620 long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1621 startTime = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : Math.max(startTime, fStartTime));
1622 endTime = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : Math.min(endTime, fEndTime));
84c8aef7 1623 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime, false);
747adf5c 1624 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
4999a196 1625
1cf25311 1626 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
747adf5c
PT
1627 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1628 column.pack();
1629 }
1cf25311
PT
1630 if (hasEntries) {
1631 fPackDone = true;
1632 }
4999a196
GB
1633 }
1634
6ae6c5bd
PT
1635 if (!zoomThread) {
1636 startZoomThread(startTime, endTime);
1637 }
4999a196
GB
1638 }
1639 });
1640 }
1641
1642 /**
1643 * Redraw the canvas
1644 */
1645 protected void redraw() {
1646 synchronized (fSyncObj) {
1647 if (fRedrawState == State.IDLE) {
1648 fRedrawState = State.BUSY;
1649 } else {
1650 fRedrawState = State.PENDING;
1651 return;
1652 }
1653 }
1654 Display.getDefault().asyncExec(new Runnable() {
1655 @Override
1656 public void run() {
747adf5c 1657 if (fTimeGraphWrapper.isDisposed()) {
4999a196
GB
1658 return;
1659 }
747adf5c
PT
1660 fTimeGraphWrapper.redraw();
1661 fTimeGraphWrapper.update();
4999a196
GB
1662 synchronized (fSyncObj) {
1663 if (fRedrawState == State.PENDING) {
1664 fRedrawState = State.IDLE;
1665 redraw();
1666 } else {
1667 fRedrawState = State.IDLE;
1668 }
1669 }
1670 }
1671 });
1672 }
1673
304e446c
PT
1674 private static void sortChildren(ITimeGraphEntry entry, Comparator<ITimeGraphEntry> comparator) {
1675 if (entry instanceof TimeGraphEntry) {
1676 ((TimeGraphEntry) entry).sortChildren(comparator);
1677 }
1678 for (ITimeGraphEntry child : entry.getChildren()) {
1679 sortChildren(child, comparator);
1680 }
1681 }
1682
0c283816
PT
1683 /**
1684 * Start or restart the zoom thread.
1685 *
1686 * @param startTime
1687 * the zoom start time
1688 * @param endTime
1689 * the zoom end time
1690 * @since 2.0
1691 */
1692 protected void startZoomThread(long startTime, long endTime) {
6ae6c5bd 1693 boolean restart = false;
4999a196
GB
1694 if (fZoomThread != null) {
1695 fZoomThread.cancel();
6ae6c5bd
PT
1696 if (fZoomThread.fZoomStartTime == startTime && fZoomThread.fZoomEndTime == endTime) {
1697 restart = true;
1698 }
1699 }
1700 long resolution = Math.max(1, (endTime - startTime) / fDisplayWidth);
1701 fZoomThread = createZoomThread(startTime, endTime, resolution, restart);
1702 if (fZoomThread != null) {
1703 fZoomThread.start();
4999a196 1704 }
6ae6c5bd
PT
1705 }
1706
1707 /**
1708 * Create a zoom thread.
1709 *
1710 * @param startTime
1711 * the zoom start time
1712 * @param endTime
1713 * the zoom end time
1714 * @param resolution
1715 * the resolution
1716 * @param restart
1717 * true if restarting zoom for the same time range
1718 * @return a zoom thread
0336f981 1719 * @since 1.1
6ae6c5bd
PT
1720 */
1721 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
dfa0ef96
GB
1722 final List<TimeGraphEntry> entryList = fEntryList;
1723 if (entryList == null) {
6ae6c5bd 1724 return null;
dfa0ef96 1725 }
6ae6c5bd 1726 return new ZoomThreadByEntry(entryList, startTime, endTime, resolution);
4999a196
GB
1727 }
1728
1729 private void makeActions() {
747adf5c 1730 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
4999a196
GB
1731 fPreviousResourceAction.setText(getPrevText());
1732 fPreviousResourceAction.setToolTipText(getPrevTooltip());
747adf5c 1733 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
4999a196
GB
1734 fNextResourceAction.setText(getNextText());
1735 fNextResourceAction.setToolTipText(getNextTooltip());
1736 }
1737
1738 private void contributeToActionBars() {
1739 IActionBars bars = getViewSite().getActionBars();
1740 fillLocalToolBar(bars.getToolBarManager());
91512088 1741 fillLocalMenu(bars.getMenuManager());
4999a196
GB
1742 }
1743
79ec0b89
PT
1744 /**
1745 * Add actions to local tool bar manager
1746 *
1747 * @param manager the tool bar manager
1748 */
1749 protected void fillLocalToolBar(IToolBarManager manager) {
cfcfd964
PT
1750 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
1751 manager.add(fTimeGraphWrapper.getShowFilterDialogAction());
4999a196 1752 }
747adf5c 1753 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
4999a196 1754 manager.add(new Separator());
747adf5c
PT
1755 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1756 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1757 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
91512088 1758 manager.add(new Separator());
1d012443 1759 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getToggleBookmarkAction());
f72cd563
PT
1760 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousMarkerAction());
1761 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextMarkerAction());
91512088 1762 manager.add(new Separator());
4999a196
GB
1763 manager.add(fPreviousResourceAction);
1764 manager.add(fNextResourceAction);
747adf5c
PT
1765 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1766 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
4999a196
GB
1767 manager.add(new Separator());
1768 }
d2e4afa7 1769
91512088
PT
1770 /**
1771 * Add actions to local menu manager
1772 *
1773 * @param manager the tool bar manager
1774 * @since 2.0
1775 */
1776 protected void fillLocalMenu(IMenuManager manager) {
1777 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getMarkersMenu());
1778 }
1779
d2e4afa7
MAL
1780 /**
1781 * @since 1.0
1782 */
1783 @Override
1784 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
1785 if (fTimeGraphWrapper == null) {
1786 return null;
1787 }
1788 return fTimeGraphWrapper.getTimeViewAlignmentInfo();
1789 }
1790
1791 /**
1792 * @since 1.0
1793 */
1794 @Override
1795 public int getAvailableWidth(int requestedOffset) {
1796 if (fTimeGraphWrapper == null) {
1797 return 0;
1798 }
1799 return fTimeGraphWrapper.getAvailableWidth(requestedOffset);
1800 }
1801
1802 /**
1803 * @since 1.0
1804 */
1805 @Override
1806 public void performAlign(int offset, int width) {
1807 if (fTimeGraphWrapper != null) {
1808 fTimeGraphWrapper.performAlign(offset, width);
1809 }
1810 }
4999a196 1811}
This page took 0.175487 seconds and 5 git commands to generate.