tmf: Update the AbstractTimeGraphView to use the refresh handler
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / timegraph / AbstractTimeGraphView.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
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
13 * Marc-Andre Laperle - Add time zone preference
14 * Geneviève Bastien - Add event links between entries
15 *******************************************************************************/
16
17 package org.eclipse.linuxtools.tmf.ui.views.timegraph;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.CopyOnWriteArrayList;
27
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.eclipse.jface.action.Action;
32 import org.eclipse.jface.action.IAction;
33 import org.eclipse.jface.action.IStatusLineManager;
34 import org.eclipse.jface.action.IToolBarManager;
35 import org.eclipse.jface.action.Separator;
36 import org.eclipse.jface.viewers.ILabelProviderListener;
37 import org.eclipse.jface.viewers.ISelectionProvider;
38 import org.eclipse.jface.viewers.ITableLabelProvider;
39 import org.eclipse.jface.viewers.ITreeContentProvider;
40 import org.eclipse.jface.viewers.TreeViewer;
41 import org.eclipse.jface.viewers.Viewer;
42 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
43 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
44 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
45 import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal;
46 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
47 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
48 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
49 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
50 import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
51 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
52 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
53 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
54 import org.eclipse.linuxtools.tmf.ui.TmfUiRefreshHandler;
55 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
56 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
57 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
58 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
59 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
60 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
61 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo;
62 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
63 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
64 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
65 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
66 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
67 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent;
68 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
69 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
70 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
71 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
72 import org.eclipse.swt.SWT;
73 import org.eclipse.swt.graphics.Image;
74 import org.eclipse.swt.widgets.Composite;
75 import org.eclipse.swt.widgets.Display;
76 import org.eclipse.swt.widgets.TreeColumn;
77 import org.eclipse.ui.IActionBars;
78
79 /**
80 * An abstract view all time graph views can inherit
81 *
82 * This view contains either a time graph viewer, or a time graph combo which is
83 * divided between a tree viewer on the left and a time graph viewer on the right.
84 *
85 * @since 2.1
86 */
87 public abstract class AbstractTimeGraphView extends TmfView {
88
89 /**
90 * Redraw state enum
91 */
92 private enum State {
93 IDLE, BUSY, PENDING
94 }
95
96 // ------------------------------------------------------------------------
97 // Fields
98 // ------------------------------------------------------------------------
99
100 /** The timegraph wrapper */
101 private ITimeGraphWrapper fTimeGraphWrapper;
102
103 /** The selected trace */
104 private ITmfTrace fTrace;
105
106 /** The timegraph entry list */
107 private List<TimeGraphEntry> fEntryList;
108
109 /** The trace to entry list hash map */
110 private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
111
112 /** The trace to build thread hash map */
113 private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
114
115 /** The start time */
116 private long fStartTime;
117
118 /** The end time */
119 private long fEndTime;
120
121 /** The display width */
122 private final int fDisplayWidth;
123
124 /** The zoom thread */
125 private ZoomThread fZoomThread;
126
127 /** The next resource action */
128 private Action fNextResourceAction;
129
130 /** The previous resource action */
131 private Action fPreviousResourceAction;
132
133 /** A comparator class */
134 private Comparator<ITimeGraphEntry> fEntryComparator = null;
135
136 /** The redraw state used to prevent unnecessary queuing of display runnables */
137 private State fRedrawState = State.IDLE;
138
139 /** The redraw synchronization object */
140 private final Object fSyncObj = new Object();
141
142 /** The presentation provider for this view */
143 private final TimeGraphPresentationProvider fPresentation;
144
145 /** The tree column label array, or null if combo is not used */
146 private String[] fColumns;
147
148 /** The tree label provider, or null if combo is not used */
149 private TreeLabelProvider fLabelProvider = null;
150
151 /** The relative weight of the sash, ignored if combo is not used */
152 private int[] fWeight = { 1, 1 };
153
154 /** The filter column label array, or null if filter is not used */
155 private String[] fFilterColumns;
156
157 /** The pack done flag */
158 private boolean fPackDone = false;
159
160 /** The filter label provider, or null if filter is not used */
161 private TreeLabelProvider fFilterLabelProvider;
162
163 // ------------------------------------------------------------------------
164 // Classes
165 // ------------------------------------------------------------------------
166
167 private interface ITimeGraphWrapper {
168
169 void setTimeGraphProvider(TimeGraphPresentationProvider fPresentation);
170
171 TimeGraphViewer getTimeGraphViewer();
172
173 void addSelectionListener(ITimeGraphSelectionListener iTimeGraphSelectionListener);
174
175 ISelectionProvider getSelectionProvider();
176
177 void setFocus();
178
179 boolean isDisposed();
180
181 void refresh();
182
183 void setInput(Object input);
184
185 Object getInput();
186
187 void redraw();
188
189 void update();
190
191 }
192
193 private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
194 private TimeGraphViewer viewer;
195
196 private TimeGraphViewerWrapper(Composite parent, int style) {
197 viewer = new TimeGraphViewer(parent, style);
198 }
199
200 @Override
201 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
202 viewer.setTimeGraphProvider(timeGraphProvider);
203 }
204
205 @Override
206 public TimeGraphViewer getTimeGraphViewer() {
207 return viewer;
208 }
209
210 @Override
211 public void addSelectionListener(ITimeGraphSelectionListener listener) {
212 viewer.addSelectionListener(listener);
213 }
214
215 @Override
216 public ISelectionProvider getSelectionProvider() {
217 return viewer.getSelectionProvider();
218 }
219
220 @Override
221 public void setFocus() {
222 viewer.setFocus();
223 }
224
225 @Override
226 public boolean isDisposed() {
227 return viewer.getControl().isDisposed();
228 }
229
230 @Override
231 public void setInput(Object input) {
232 viewer.setInput(input);
233 }
234
235 @Override
236 public Object getInput() {
237 return viewer.getInput();
238 }
239
240 @Override
241 public void refresh() {
242 viewer.refresh();
243 }
244
245 @Override
246 public void redraw() {
247 viewer.getControl().redraw();
248 }
249
250 @Override
251 public void update() {
252 viewer.getControl().update();
253 }
254 }
255
256 private class TimeGraphComboWrapper implements ITimeGraphWrapper {
257 private TimeGraphCombo combo;
258
259 private TimeGraphComboWrapper(Composite parent, int style) {
260 combo = new TimeGraphCombo(parent, style, fWeight);
261 }
262
263 @Override
264 public void setTimeGraphProvider(TimeGraphPresentationProvider timeGraphProvider) {
265 combo.setTimeGraphProvider(timeGraphProvider);
266 }
267
268 @Override
269 public TimeGraphViewer getTimeGraphViewer() {
270 return combo.getTimeGraphViewer();
271 }
272
273 @Override
274 public void addSelectionListener(ITimeGraphSelectionListener listener) {
275 combo.addSelectionListener(listener);
276 }
277
278 @Override
279 public ISelectionProvider getSelectionProvider() {
280 return combo.getTreeViewer();
281 }
282
283 @Override
284 public void setFocus() {
285 combo.setFocus();
286 }
287
288 @Override
289 public boolean isDisposed() {
290 return combo.isDisposed();
291 }
292
293 @Override
294 public void setInput(Object input) {
295 combo.setInput(input);
296 }
297
298 @Override
299 public Object getInput() {
300 return combo.getInput();
301 }
302
303 @Override
304 public void refresh() {
305 combo.refresh();
306 }
307
308 @Override
309 public void redraw() {
310 combo.redraw();
311 }
312
313 @Override
314 public void update() {
315 combo.update();
316 }
317
318 TimeGraphCombo getTimeGraphCombo() {
319 return combo;
320 }
321
322 TreeViewer getTreeViewer() {
323 return combo.getTreeViewer();
324 }
325
326 IAction getShowFilterAction() {
327 return combo.getShowFilterAction();
328 }
329 }
330
331 private class TreeContentProvider implements ITreeContentProvider {
332
333 @Override
334 public void dispose() {
335 }
336
337 @Override
338 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
339 }
340
341 @Override
342 public ITimeGraphEntry[] getElements(Object inputElement) {
343 if (inputElement != null) {
344 try {
345 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
346 } catch (ClassCastException e) {
347 }
348 }
349 return new ITimeGraphEntry[0];
350 }
351
352 @Override
353 public Object[] getChildren(Object parentElement) {
354 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
355 List<? extends ITimeGraphEntry> children = entry.getChildren();
356 return children.toArray(new ITimeGraphEntry[children.size()]);
357 }
358
359 @Override
360 public Object getParent(Object element) {
361 ITimeGraphEntry entry = (ITimeGraphEntry) element;
362 return entry.getParent();
363 }
364
365 @Override
366 public boolean hasChildren(Object element) {
367 ITimeGraphEntry entry = (ITimeGraphEntry) element;
368 return entry.hasChildren();
369 }
370
371 }
372
373 private class TimeGraphContentProvider implements ITimeGraphContentProvider {
374
375 @Override
376 public ITimeGraphEntry[] getElements(Object inputElement) {
377 if (inputElement != null) {
378 try {
379 return ((List<?>) inputElement).toArray(new ITimeGraphEntry[0]);
380 } catch (ClassCastException e) {
381 }
382 }
383 return new ITimeGraphEntry[0];
384 }
385
386 }
387
388 /**
389 * Base class to provide the labels for the tree viewer. Views extending
390 * this class typically need to override the getColumnText method if they
391 * have more than one column to display
392 */
393 protected static class TreeLabelProvider implements ITableLabelProvider {
394
395 @Override
396 public void addListener(ILabelProviderListener listener) {
397 }
398
399 @Override
400 public void dispose() {
401 }
402
403 @Override
404 public boolean isLabelProperty(Object element, String property) {
405 return false;
406 }
407
408 @Override
409 public void removeListener(ILabelProviderListener listener) {
410 }
411
412 @Override
413 public Image getColumnImage(Object element, int columnIndex) {
414 return null;
415 }
416
417 @Override
418 public String getColumnText(Object element, int columnIndex) {
419 TimeGraphEntry entry = (TimeGraphEntry) element;
420 if (columnIndex == 0) {
421 return entry.getName();
422 }
423 return new String();
424 }
425
426 }
427
428 private class BuildThread extends Thread {
429 private final ITmfTrace fBuildTrace;
430 private final ITmfTrace fParentTrace;
431 private final IProgressMonitor fMonitor;
432
433 public BuildThread(final ITmfTrace trace, final ITmfTrace parentTrace, final String name) {
434 super(name + " build"); //$NON-NLS-1$
435 fBuildTrace = trace;
436 fParentTrace = parentTrace;
437 fMonitor = new NullProgressMonitor();
438 }
439
440 @Override
441 public void run() {
442 buildEventList(fBuildTrace, fParentTrace, fMonitor);
443 synchronized (fBuildThreadMap) {
444 fBuildThreadMap.remove(fBuildTrace);
445 }
446 }
447
448 public void cancel() {
449 fMonitor.setCanceled(true);
450 }
451 }
452
453 private class ZoomThread extends Thread {
454 private final List<TimeGraphEntry> fZoomEntryList;
455 private final long fZoomStartTime;
456 private final long fZoomEndTime;
457 private final long fResolution;
458 private final IProgressMonitor fMonitor;
459
460 public ZoomThread(List<TimeGraphEntry> entryList, long startTime, long endTime, String name) {
461 super(name + " zoom"); //$NON-NLS-1$
462 fZoomEntryList = entryList;
463 fZoomStartTime = startTime;
464 fZoomEndTime = endTime;
465 fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
466 fMonitor = new NullProgressMonitor();
467 }
468
469 @Override
470 public void run() {
471 if (fZoomEntryList == null) {
472 return;
473 }
474 for (TimeGraphEntry entry : fZoomEntryList) {
475 if (fMonitor.isCanceled()) {
476 return;
477 }
478 zoom(entry, fMonitor);
479 }
480 /* Refresh the arrows when zooming */
481 List<ILinkEvent> events = getLinkList(fZoomStartTime, fZoomEndTime, fResolution, fMonitor);
482 if (events != null) {
483 fTimeGraphWrapper.getTimeGraphViewer().setLinks(events);
484 redraw();
485 }
486 }
487
488 private void zoom(TimeGraphEntry entry, IProgressMonitor monitor) {
489 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
490 entry.setZoomedEventList(null);
491 } else {
492 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor);
493 if (zoomedEventList != null) {
494 entry.setZoomedEventList(zoomedEventList);
495 }
496 }
497 redraw();
498 for (TimeGraphEntry child : entry.getChildren()) {
499 if (fMonitor.isCanceled()) {
500 return;
501 }
502 zoom(child, monitor);
503 }
504 }
505
506 public void cancel() {
507 fMonitor.setCanceled(true);
508 }
509 }
510
511 // ------------------------------------------------------------------------
512 // Constructors
513 // ------------------------------------------------------------------------
514
515 /**
516 * Constructs a time graph view that contains either a time graph viewer or
517 * a time graph combo.
518 *
519 * By default, the view uses a time graph viewer. To use a time graph combo,
520 * the subclass constructor must call {@link #setTreeColumns(String[])} and
521 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
522 *
523 * @param id
524 * The id of the view
525 * @param pres
526 * The presentation provider
527 */
528 public AbstractTimeGraphView(String id, TimeGraphPresentationProvider pres) {
529 super(id);
530 fPresentation = pres;
531 fDisplayWidth = Display.getDefault().getBounds().width;
532 }
533
534 // ------------------------------------------------------------------------
535 // Getters and setters
536 // ------------------------------------------------------------------------
537
538 /**
539 * Getter for the time graph combo
540 *
541 * @return The time graph combo, or null if combo is not used
542 */
543 protected TimeGraphCombo getTimeGraphCombo() {
544 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
545 return ((TimeGraphComboWrapper) fTimeGraphWrapper).getTimeGraphCombo();
546 }
547 return null;
548 }
549
550 /**
551 * Getter for the time graph viewer
552 *
553 * @return The time graph viewer
554 */
555 protected TimeGraphViewer getTimeGraphViewer() {
556 return fTimeGraphWrapper.getTimeGraphViewer();
557 }
558
559 /**
560 * Getter for the presentation provider
561 *
562 * @return The time graph presentation provider
563 * @since 3.0
564 */
565 protected ITimeGraphPresentationProvider2 getPresentationProvider() {
566 return fPresentation;
567 }
568
569 /**
570 * Sets the tree column labels.
571 * This should be called from the constructor.
572 *
573 * @param columns
574 * The array of tree column labels
575 */
576 protected void setTreeColumns(final String[] columns) {
577 fColumns = columns;
578 }
579
580 /**
581 * Sets the tree label provider.
582 * This should be called from the constructor.
583 *
584 * @param tlp
585 * The tree label provider
586 */
587 protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
588 fLabelProvider = tlp;
589 }
590
591 /**
592 * Sets the relative weight of each part of the time graph combo.
593 * This should be called from the constructor.
594 *
595 * @param weights
596 * The array (length 2) of relative weights of each part of the combo
597 */
598 protected void setWeight(final int[] weights) {
599 fWeight = weights;
600 }
601
602 /**
603 * Sets the filter column labels.
604 * This should be called from the constructor.
605 *
606 * @param filterColumns
607 * The array of filter column labels
608 */
609 protected void setFilterColumns(final String[] filterColumns) {
610 fFilterColumns = filterColumns;
611 }
612
613 /**
614 * Sets the filter label provider.
615 * This should be called from the constructor.
616 *
617 * @param labelProvider
618 * The filter label provider
619 *
620 * @since 3.0
621 */
622 protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
623 fFilterLabelProvider = labelProvider;
624 }
625
626 /**
627 * Gets the display width
628 *
629 * @return the display width
630 */
631 protected int getDisplayWidth() {
632 return fDisplayWidth;
633 }
634
635 /**
636 * Gets the comparator for the entries
637 *
638 * @return The entry comparator
639 */
640 protected Comparator<ITimeGraphEntry> getEntryComparator() {
641 return fEntryComparator;
642 }
643
644 /**
645 * Sets the comparator class for the entries
646 *
647 * @param comparator
648 * A comparator object
649 */
650 protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) {
651 fEntryComparator = comparator;
652 }
653
654 /**
655 * Gets the trace displayed in the view
656 *
657 * @return The trace
658 */
659 protected ITmfTrace getTrace() {
660 return fTrace;
661 }
662
663 /**
664 * Gets the start time
665 *
666 * @return The start time
667 */
668 protected long getStartTime() {
669 return fStartTime;
670 }
671
672 /**
673 * Sets the start time
674 *
675 * @param time
676 * The start time
677 */
678 protected void setStartTime(long time) {
679 fStartTime = time;
680 }
681
682 /**
683 * Gets the end time
684 *
685 * @return The end time
686 */
687 protected long getEndTime() {
688 return fEndTime;
689 }
690
691 /**
692 * Sets the end time
693 *
694 * @param time
695 * The end time
696 */
697 protected void setEndTime(long time) {
698 fEndTime = time;
699 }
700
701 /**
702 * Gets the entry list for a trace
703 *
704 * @param trace
705 * the trace
706 *
707 * @return the entry list map
708 * @since 3.0
709 */
710 protected List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
711 synchronized (fEntryListMap) {
712 return fEntryListMap.get(trace);
713 }
714 }
715
716 /**
717 * Adds a trace entry list to the entry list map
718 *
719 * @param trace
720 * the trace to add
721 * @param list
722 * the list of time graph entries
723 */
724 protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
725 synchronized (fEntryListMap) {
726 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
727 }
728 }
729
730 /**
731 * Adds a list of entries to a trace's entry list
732 *
733 * @param trace
734 * the trace
735 * @param list
736 * the list of time graph entries to add
737 * @since 3.0
738 */
739 protected void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
740 synchronized (fEntryListMap) {
741 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
742 if (entryList == null) {
743 fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
744 } else {
745 entryList.addAll(list);
746 }
747 }
748 }
749
750 /**
751 * Removes a list of entries from a trace's entry list
752 *
753 * @param trace
754 * the trace
755 * @param list
756 * the list of time graph entries to remove
757 * @since 3.0
758 */
759 protected void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
760 synchronized (fEntryListMap) {
761 List<TimeGraphEntry> entryList = fEntryListMap.get(trace);
762 if (entryList != null) {
763 entryList.removeAll(list);
764 }
765 }
766 }
767
768 /**
769 * Text for the "next" button
770 *
771 * @return The "next" button text
772 */
773 protected String getNextText() {
774 return Messages.AbstractTimeGraphtView_NextText;
775 }
776
777 /**
778 * Tooltip for the "next" button
779 *
780 * @return Tooltip for the "next" button
781 */
782 protected String getNextTooltip() {
783 return Messages.AbstractTimeGraphView_NextTooltip;
784 }
785
786 /**
787 * Text for the "Previous" button
788 *
789 * @return The "Previous" button text
790 */
791 protected String getPrevText() {
792 return Messages.AbstractTimeGraphView_PreviousText;
793 }
794
795 /**
796 * Tooltip for the "previous" button
797 *
798 * @return Tooltip for the "previous" button
799 */
800 protected String getPrevTooltip() {
801 return Messages.AbstractTimeGraphView_PreviousTooltip;
802 }
803
804 // ------------------------------------------------------------------------
805 // ViewPart
806 // ------------------------------------------------------------------------
807
808 @Override
809 public void createPartControl(Composite parent) {
810 if (fColumns == null || fLabelProvider == null) {
811 fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE);
812 TimeGraphViewer viewer = fTimeGraphWrapper.getTimeGraphViewer();
813 viewer.setTimeGraphContentProvider(new TimeGraphContentProvider());
814 } else {
815 TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE);
816 fTimeGraphWrapper = wrapper;
817 TimeGraphCombo combo = wrapper.getTimeGraphCombo();
818 combo.setTreeContentProvider(new TreeContentProvider());
819 combo.setTreeLabelProvider(fLabelProvider);
820 combo.setTreeColumns(fColumns);
821 combo.setFilterContentProvider(new TreeContentProvider());
822 combo.setFilterLabelProvider(fFilterLabelProvider);
823 combo.setFilterColumns(fFilterColumns);
824 combo.setTimeGraphContentProvider(new TimeGraphContentProvider());
825 }
826
827 fTimeGraphWrapper.setTimeGraphProvider(fPresentation);
828
829 fTimeGraphWrapper.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
830 @Override
831 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
832 final long startTime = event.getStartTime();
833 final long endTime = event.getEndTime();
834 TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
835 broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView.this, range));
836 if (fZoomThread != null) {
837 fZoomThread.cancel();
838 }
839 startZoomThread(startTime, endTime);
840 }
841 });
842
843 fTimeGraphWrapper.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
844 @Override
845 public void timeSelected(TimeGraphTimeEvent event) {
846 TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime());
847 TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime());
848 broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView.this, startTime, endTime));
849 }
850 });
851
852 fTimeGraphWrapper.addSelectionListener(new ITimeGraphSelectionListener() {
853 @Override
854 public void selectionChanged(TimeGraphSelectionEvent event) {
855 // ITimeGraphEntry selection = event.getSelection();
856 }
857 });
858
859 fTimeGraphWrapper.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
860
861 IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
862 fTimeGraphWrapper.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
863
864 // View Action Handling
865 makeActions();
866 contributeToActionBars();
867
868 ITmfTrace trace = getActiveTrace();
869 if (trace != null) {
870 traceSelected(new TmfTraceSelectedSignal(this, trace));
871 }
872
873 // make selection available to other views
874 getSite().setSelectionProvider(fTimeGraphWrapper.getSelectionProvider());
875 }
876
877 @Override
878 public void setFocus() {
879 fTimeGraphWrapper.setFocus();
880 }
881
882 // ------------------------------------------------------------------------
883 // Signal handlers
884 // ------------------------------------------------------------------------
885
886 /**
887 * Handler for the trace opened signal.
888 *
889 * @param signal
890 * The incoming signal
891 * @since 2.0
892 */
893 @TmfSignalHandler
894 public void traceOpened(TmfTraceOpenedSignal signal) {
895 fTrace = signal.getTrace();
896 loadTrace();
897 }
898
899 /**
900 * Handler for the trace selected signal
901 *
902 * @param signal
903 * The incoming signal
904 */
905 @TmfSignalHandler
906 public void traceSelected(final TmfTraceSelectedSignal signal) {
907 if (signal.getTrace() == fTrace) {
908 return;
909 }
910 fTrace = signal.getTrace();
911
912 loadTrace();
913 }
914
915 /**
916 * Trace is closed: clear the data structures and the view
917 *
918 * @param signal
919 * the signal received
920 */
921 @TmfSignalHandler
922 public void traceClosed(final TmfTraceClosedSignal signal) {
923 synchronized (fBuildThreadMap) {
924 for (ITmfTrace trace : getTracesToBuild(signal.getTrace())) {
925 BuildThread buildThread = fBuildThreadMap.remove(trace);
926 if (buildThread != null) {
927 buildThread.cancel();
928 }
929 }
930 }
931 synchronized (fEntryListMap) {
932 fEntryListMap.remove(signal.getTrace());
933 }
934 if (signal.getTrace() == fTrace) {
935 fTrace = null;
936 fStartTime = 0;
937 fEndTime = 0;
938 if (fZoomThread != null) {
939 fZoomThread.cancel();
940 }
941 refresh();
942 }
943 }
944
945 /**
946 * Handler for the time synch signal
947 *
948 * @param signal
949 * The signal that's received
950 */
951 @TmfSignalHandler
952 public void synchToTime(final TmfTimeSynchSignal signal) {
953 if (signal.getSource() == this || fTrace == null) {
954 return;
955 }
956 final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
957 final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
958
959 Display.getDefault().asyncExec(new Runnable() {
960 @Override
961 public void run() {
962 if (fTimeGraphWrapper.isDisposed()) {
963 return;
964 }
965 if (beginTime == endTime) {
966 fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
967 } else {
968 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
969 }
970 startZoomThread(fTimeGraphWrapper.getTimeGraphViewer().getTime0(), fTimeGraphWrapper.getTimeGraphViewer().getTime1());
971
972 synchingToTime(beginTime);
973 }
974 });
975 }
976
977 /**
978 * Handler for the range synch signal
979 *
980 * @param signal
981 * The signal that's received
982 */
983 @TmfSignalHandler
984 public void synchToRange(final TmfRangeSynchSignal signal) {
985 if (signal.getSource() == this || fTrace == null) {
986 return;
987 }
988 if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
989 return;
990 }
991 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
992 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
993 Display.getDefault().asyncExec(new Runnable() {
994 @Override
995 public void run() {
996 if (fTimeGraphWrapper.isDisposed()) {
997 return;
998 }
999 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1000 startZoomThread(startTime, endTime);
1001 }
1002 });
1003 }
1004
1005 /**
1006 * @param signal the format of the timestamps was updated.
1007 * @since 2.1
1008 */
1009 @TmfSignalHandler
1010 public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){
1011 fTimeGraphWrapper.refresh();
1012 }
1013
1014 // ------------------------------------------------------------------------
1015 // Internal
1016 // ------------------------------------------------------------------------
1017
1018 private void loadTrace() {
1019 synchronized (fEntryListMap) {
1020 fEntryList = fEntryListMap.get(fTrace);
1021 if (fEntryList == null) {
1022 rebuild();
1023 } else {
1024 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1025 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1026 refresh();
1027 }
1028 }
1029 }
1030
1031 /**
1032 * Forces a rebuild of the entries list, even if entries already exist for this trace
1033 * @since 3.0
1034 */
1035 protected void rebuild() {
1036 setStartTime(Long.MAX_VALUE);
1037 setEndTime(Long.MIN_VALUE);
1038 synchronized (fBuildThreadMap) {
1039 for (ITmfTrace trace : getTracesToBuild(fTrace)) {
1040 BuildThread buildThread = new BuildThread(trace, fTrace, getName());
1041 fBuildThreadMap.put(trace, buildThread);
1042 buildThread.start();
1043 }
1044 }
1045 }
1046
1047 /**
1048 * Method called when synching to a given timestamp. Inheriting classes can
1049 * perform actions here to update the view at the given timestamp.
1050 *
1051 * @param time
1052 * The currently selected time
1053 */
1054 protected void synchingToTime(long time) {
1055
1056 }
1057
1058 /**
1059 * Return the list of traces whose data or analysis results will be used to
1060 * populate the view. By default, if the trace is an experiment, the traces
1061 * under it will be returned, otherwise, the trace itself is returned.
1062 *
1063 * A build thread will be started for each trace returned by this method,
1064 * some of which may receive events in live streaming mode.
1065 *
1066 * @param trace
1067 * The trace associated with this view
1068 * @return List of traces with data to display
1069 * @since 3.0
1070 */
1071 protected Iterable<ITmfTrace> getTracesToBuild(ITmfTrace trace) {
1072 return Arrays.asList(TmfTraceManager.getTraceSet(trace));
1073 }
1074
1075 /**
1076 * Build the entries list to show in this time graph
1077 *
1078 * Called from the BuildThread
1079 *
1080 * @param trace
1081 * The trace being built
1082 * @param parentTrace
1083 * The parent of the trace set, or the trace itself
1084 * @param monitor
1085 * The progress monitor object
1086 * @since 3.0
1087 */
1088 protected abstract void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor);
1089
1090 /**
1091 * Gets the list of event for an entry in a given timerange
1092 *
1093 * @param entry
1094 * The entry to get events for
1095 * @param startTime
1096 * Start of the time range
1097 * @param endTime
1098 * End of the time range
1099 * @param resolution
1100 * The resolution
1101 * @param monitor
1102 * The progress monitor object
1103 * @return The list of events for the entry
1104 */
1105 protected abstract @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry,
1106 long startTime, long endTime, long resolution,
1107 IProgressMonitor monitor);
1108
1109 /**
1110 * Gets the list of links (displayed as arrows) for a trace in a given
1111 * timerange. Default implementation returns an empty list.
1112 *
1113 * @param startTime
1114 * Start of the time range
1115 * @param endTime
1116 * End of the time range
1117 * @param resolution
1118 * The resolution
1119 * @param monitor
1120 * The progress monitor object
1121 * @return The list of link events
1122 * @since 2.1
1123 */
1124 protected List<ILinkEvent> getLinkList(long startTime, long endTime,
1125 long resolution, IProgressMonitor monitor) {
1126 return new ArrayList<>();
1127 }
1128
1129
1130 /**
1131 * Refresh the display
1132 */
1133 protected void refresh() {
1134 TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
1135 @Override
1136 public void run() {
1137 if (fTimeGraphWrapper.isDisposed()) {
1138 return;
1139 }
1140 boolean hasEntries = false;
1141 synchronized (fEntryListMap) {
1142 fEntryList = fEntryListMap.get(fTrace);
1143 if (fEntryList == null) {
1144 fEntryList = new CopyOnWriteArrayList<>();
1145 } else if (fEntryComparator != null) {
1146 List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
1147 Collections.sort(list, fEntryComparator);
1148 fEntryList.clear();
1149 fEntryList.addAll(list);
1150 }
1151 hasEntries = fEntryList.size() != 0;
1152 }
1153 if (fEntryList != fTimeGraphWrapper.getInput()) {
1154 fTimeGraphWrapper.setInput(fEntryList);
1155 } else {
1156 fTimeGraphWrapper.refresh();
1157 }
1158 fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
1159
1160 long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1161 long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1162 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1163 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
1164 startTime = Math.max(startTime, fStartTime);
1165 endTime = Math.min(endTime, fEndTime);
1166 fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
1167 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
1168
1169 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
1170 for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
1171 column.pack();
1172 }
1173 if (hasEntries) {
1174 fPackDone = true;
1175 }
1176 }
1177
1178 startZoomThread(startTime, endTime);
1179 }
1180 });
1181 }
1182
1183 /**
1184 * Redraw the canvas
1185 */
1186 protected void redraw() {
1187 synchronized (fSyncObj) {
1188 if (fRedrawState == State.IDLE) {
1189 fRedrawState = State.BUSY;
1190 } else {
1191 fRedrawState = State.PENDING;
1192 return;
1193 }
1194 }
1195 Display.getDefault().asyncExec(new Runnable() {
1196 @Override
1197 public void run() {
1198 if (fTimeGraphWrapper.isDisposed()) {
1199 return;
1200 }
1201 fTimeGraphWrapper.redraw();
1202 fTimeGraphWrapper.update();
1203 synchronized (fSyncObj) {
1204 if (fRedrawState == State.PENDING) {
1205 fRedrawState = State.IDLE;
1206 redraw();
1207 } else {
1208 fRedrawState = State.IDLE;
1209 }
1210 }
1211 }
1212 });
1213 }
1214
1215 private void startZoomThread(long startTime, long endTime) {
1216 if (fZoomThread != null) {
1217 fZoomThread.cancel();
1218 }
1219 fZoomThread = new ZoomThread(fEntryList, startTime, endTime, getName());
1220 fZoomThread.start();
1221 }
1222
1223 private void makeActions() {
1224 fPreviousResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getPreviousItemAction();
1225 fPreviousResourceAction.setText(getPrevText());
1226 fPreviousResourceAction.setToolTipText(getPrevTooltip());
1227 fNextResourceAction = fTimeGraphWrapper.getTimeGraphViewer().getNextItemAction();
1228 fNextResourceAction.setText(getNextText());
1229 fNextResourceAction.setToolTipText(getNextTooltip());
1230 }
1231
1232 private void contributeToActionBars() {
1233 IActionBars bars = getViewSite().getActionBars();
1234 fillLocalToolBar(bars.getToolBarManager());
1235 }
1236
1237 /**
1238 * Add actions to local tool bar manager
1239 *
1240 * @param manager the tool bar manager
1241 */
1242 protected void fillLocalToolBar(IToolBarManager manager) {
1243 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
1244 if (fFilterColumns != null && fFilterLabelProvider != null && fFilterColumns.length > 0) {
1245 manager.add(((TimeGraphComboWrapper) fTimeGraphWrapper).getShowFilterAction());
1246 }
1247 }
1248 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getShowLegendAction());
1249 manager.add(new Separator());
1250 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getResetScaleAction());
1251 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getPreviousEventAction());
1252 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getNextEventAction());
1253 manager.add(fPreviousResourceAction);
1254 manager.add(fNextResourceAction);
1255 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomInAction());
1256 manager.add(fTimeGraphWrapper.getTimeGraphViewer().getZoomOutAction());
1257 manager.add(new Separator());
1258 }
1259 }
This page took 0.084491 seconds and 6 git commands to generate.