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