Commit | Line | Data |
---|---|---|
4999a196 GB |
1 | /******************************************************************************* |
2 | * Copyright (c) 2012, 2013 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 | |
c1cd9635 | 13 | * Marc-Andre Laperle - Add time zone preference |
bec1f1ac | 14 | * Geneviève Bastien - Add event links between entries |
4999a196 GB |
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 | ||
27 | import org.eclipse.core.runtime.IProgressMonitor; | |
28 | import org.eclipse.core.runtime.NullProgressMonitor; | |
29 | import org.eclipse.jface.action.Action; | |
0fcf3b09 | 30 | import org.eclipse.jface.action.IStatusLineManager; |
4999a196 GB |
31 | import org.eclipse.jface.action.IToolBarManager; |
32 | import org.eclipse.jface.action.Separator; | |
33 | import org.eclipse.jface.viewers.ILabelProviderListener; | |
34 | import org.eclipse.jface.viewers.ITableLabelProvider; | |
35 | import org.eclipse.jface.viewers.ITreeContentProvider; | |
36 | import org.eclipse.jface.viewers.Viewer; | |
4999a196 GB |
37 | import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; |
38 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; | |
39 | import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; | |
c1cd9635 | 40 | import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal; |
4999a196 GB |
41 | import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal; |
42 | import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal; | |
43 | import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal; | |
44 | import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; | |
f566d40a | 45 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp; |
4999a196 | 46 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; |
4999a196 GB |
47 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; |
48 | import org.eclipse.linuxtools.tmf.ui.views.TmfView; | |
49 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener; | |
50 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener; | |
51 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener; | |
52 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo; | |
53 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; | |
54 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent; | |
55 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent; | |
56 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent; | |
bec1f1ac | 57 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent; |
4999a196 GB |
58 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; |
59 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; | |
60 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; | |
61 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; | |
62 | import org.eclipse.swt.SWT; | |
63 | import org.eclipse.swt.graphics.Image; | |
64 | import org.eclipse.swt.widgets.Composite; | |
65 | import org.eclipse.swt.widgets.Display; | |
66 | import org.eclipse.swt.widgets.TreeColumn; | |
67 | import org.eclipse.ui.IActionBars; | |
68 | ||
69 | /** | |
70 | * An abstract view all time graph views can inherit | |
71 | * | |
72 | * This view contains a time graph combo, divided between a treeview on the | |
73 | * left, showing entries and a canvas on the right to draw something for these | |
74 | * entries. | |
75 | * | |
76 | * @since 2.1 | |
77 | */ | |
78 | public abstract class AbstractTimeGraphView extends TmfView { | |
79 | ||
80 | private final String[] fColumns; | |
81 | private final String[] fFilterColumns; | |
82 | ||
83 | /** | |
84 | * Redraw state enum | |
85 | */ | |
86 | private enum State { | |
87 | IDLE, BUSY, PENDING | |
88 | } | |
89 | ||
90 | // ------------------------------------------------------------------------ | |
91 | // Fields | |
92 | // ------------------------------------------------------------------------ | |
93 | ||
94 | /** The timegraph combo */ | |
95 | private TimeGraphCombo fTimeGraphCombo; | |
96 | ||
97 | /** The selected trace */ | |
98 | private ITmfTrace fTrace; | |
99 | ||
100 | /** The timegraph entry list */ | |
101 | private List<TimeGraphEntry> fEntryList; | |
102 | ||
103 | /** The trace to entry list hash map */ | |
104 | private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<ITmfTrace, List<TimeGraphEntry>>(); | |
105 | ||
106 | /* The trace to build thread hash map */ | |
107 | private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<ITmfTrace, BuildThread>(); | |
108 | ||
109 | /** The start time */ | |
110 | private long fStartTime; | |
111 | ||
112 | /** The end time */ | |
113 | private long fEndTime; | |
114 | ||
115 | /** The display width */ | |
116 | private final int fDisplayWidth; | |
117 | ||
118 | /** The zoom thread */ | |
119 | private ZoomThread fZoomThread; | |
120 | ||
121 | /** The next resource action */ | |
122 | private Action fNextResourceAction; | |
123 | ||
124 | /** The previous resource action */ | |
125 | private Action fPreviousResourceAction; | |
126 | ||
127 | /** The relative weight of the sash */ | |
128 | private int[] fWeight = { 1, 1 }; | |
129 | ||
130 | /** A comparator class */ | |
131 | private Comparator<ITimeGraphEntry> fEntryComparator = null; | |
132 | ||
133 | /** The redraw state used to prevent unnecessary queuing of display runnables */ | |
134 | private State fRedrawState = State.IDLE; | |
135 | ||
136 | /** The redraw synchronization object */ | |
137 | private final Object fSyncObj = new Object(); | |
138 | ||
139 | /** The presentation provider for this view */ | |
140 | private final TimeGraphPresentationProvider fPresentation; | |
141 | ||
142 | private TreeLabelProvider fLabelProvider = new TreeLabelProvider(); | |
143 | ||
144 | // ------------------------------------------------------------------------ | |
145 | // Getters and setters | |
146 | // ------------------------------------------------------------------------ | |
147 | ||
148 | /** | |
149 | * Getter for the time graph combo | |
150 | * | |
151 | * @return The Time graph combo | |
152 | */ | |
153 | protected TimeGraphCombo getTimeGraphCombo() { | |
154 | return fTimeGraphCombo; | |
155 | } | |
156 | ||
157 | /** | |
158 | * Sets the tree label provider | |
159 | * | |
160 | * @param tlp | |
161 | * The tree label provider | |
162 | */ | |
163 | protected void setTreeLabelProvider(final TreeLabelProvider tlp) { | |
164 | fLabelProvider = tlp; | |
165 | } | |
166 | ||
167 | /** | |
168 | * Sets the relative weight of each part of the time graph combo | |
169 | * | |
170 | * @param weights | |
171 | * The array of relative weights of each part of the combo | |
172 | */ | |
173 | protected void setWeight(final int[] weights) { | |
174 | fWeight = weights; | |
175 | } | |
176 | ||
177 | /** | |
178 | * Gets the display width | |
179 | * | |
180 | * @return the display width | |
181 | */ | |
182 | protected int getDisplayWidth() { | |
183 | return fDisplayWidth; | |
184 | } | |
185 | ||
186 | /** | |
187 | * Gets the comparator for the entries | |
188 | * | |
189 | * @return The entry comparator | |
190 | */ | |
191 | protected Comparator<ITimeGraphEntry> getEntryComparator() { | |
192 | return fEntryComparator; | |
193 | } | |
194 | ||
195 | /** | |
196 | * Sets the comparator class for the entries * Gets the display width | |
197 | * | |
198 | * @param comparator | |
199 | * A comparator object | |
200 | */ | |
201 | protected void setEntryComparator(final Comparator<ITimeGraphEntry> comparator) { | |
202 | fEntryComparator = comparator; | |
203 | } | |
204 | ||
205 | /** | |
206 | * Gets the trace displayed in the view | |
207 | * | |
208 | * @return The trace | |
209 | */ | |
210 | protected ITmfTrace getTrace() { | |
211 | return fTrace; | |
212 | } | |
213 | ||
214 | /** | |
215 | * Sets the trace to display | |
216 | * | |
217 | * @param trace | |
218 | * The trace | |
219 | */ | |
220 | protected void setTrace(final ITmfTrace trace) { | |
221 | fTrace = trace; | |
222 | } | |
223 | ||
224 | /** | |
225 | * Gets the start time | |
226 | * | |
227 | * @return The start time | |
228 | */ | |
229 | protected long getStartTime() { | |
230 | return fStartTime; | |
231 | } | |
232 | ||
233 | /** | |
234 | * Sets the start time | |
235 | * | |
236 | * @param time | |
237 | * The start time | |
238 | */ | |
239 | protected void setStartTime(long time) { | |
240 | fStartTime = time; | |
241 | } | |
242 | ||
243 | /** | |
244 | * Gets the end time | |
245 | * | |
246 | * @return The end time | |
247 | */ | |
248 | protected long getEndTime() { | |
249 | return fEndTime; | |
250 | } | |
251 | ||
252 | /** | |
253 | * Sets the end time | |
254 | * | |
255 | * @param time | |
256 | * The end time | |
257 | */ | |
258 | protected void setEndTime(long time) { | |
259 | fEndTime = time; | |
260 | } | |
261 | ||
262 | /** | |
263 | * Gets the entry list map | |
264 | * | |
265 | * @return the entry list map | |
266 | */ | |
267 | protected Map<ITmfTrace, List<TimeGraphEntry>> getEntryListMap() { | |
268 | return Collections.unmodifiableMap(fEntryListMap); | |
269 | } | |
270 | ||
271 | /** | |
272 | * Adds an entry to the entry list | |
273 | * | |
274 | * @param trace | |
275 | * the trace to add | |
276 | * @param list | |
277 | * The list of time graph entries | |
bec1f1ac | 278 | * @since 2.1 |
4999a196 GB |
279 | */ |
280 | protected void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) { | |
281 | synchronized(fEntryListMap) { | |
282 | fEntryListMap.put(trace, list); | |
283 | } | |
284 | } | |
285 | ||
286 | /** | |
287 | * Text for the "next" button | |
288 | * | |
289 | * @return The "next" button text | |
290 | */ | |
291 | protected String getNextText() { | |
292 | return Messages.AbstractTimeGraphtView_NextText; | |
293 | } | |
294 | ||
295 | /** | |
296 | * Tooltip for the "next" button | |
297 | * | |
298 | * @return Tooltip for the "next" button | |
299 | */ | |
300 | protected String getNextTooltip() { | |
301 | return Messages.AbstractTimeGraphView_NextTooltip; | |
302 | } | |
303 | ||
304 | /** | |
305 | * Text for the "Previous" button | |
306 | * | |
307 | * @return The "Previous" button text | |
308 | */ | |
309 | protected String getPrevText() { | |
310 | return Messages.AbstractTimeGraphView_PreviousText; | |
311 | } | |
312 | ||
313 | /** | |
314 | * Tooltip for the "previous" button | |
315 | * | |
316 | * @return Tooltip for the "previous" button | |
317 | */ | |
318 | protected String getPrevTooltip() { | |
319 | return Messages.AbstractTimeGraphView_PreviousTooltip; | |
320 | } | |
321 | ||
322 | // ------------------------------------------------------------------------ | |
323 | // Classes | |
324 | // ------------------------------------------------------------------------ | |
325 | ||
326 | private class TreeContentProvider implements ITreeContentProvider { | |
327 | ||
328 | @Override | |
329 | public void dispose() { | |
330 | } | |
331 | ||
332 | @Override | |
333 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { | |
334 | } | |
335 | ||
336 | @Override | |
337 | public Object[] getElements(Object inputElement) { | |
338 | return (ITimeGraphEntry[]) inputElement; | |
339 | } | |
340 | ||
341 | @Override | |
342 | public Object[] getChildren(Object parentElement) { | |
343 | ITimeGraphEntry entry = (ITimeGraphEntry) parentElement; | |
344 | List<? extends ITimeGraphEntry> children = entry.getChildren(); | |
345 | return children.toArray(new ITimeGraphEntry[children.size()]); | |
346 | } | |
347 | ||
348 | @Override | |
349 | public Object getParent(Object element) { | |
350 | ITimeGraphEntry entry = (ITimeGraphEntry) element; | |
351 | return entry.getParent(); | |
352 | } | |
353 | ||
354 | @Override | |
355 | public boolean hasChildren(Object element) { | |
356 | ITimeGraphEntry entry = (ITimeGraphEntry) element; | |
357 | return entry.hasChildren(); | |
358 | } | |
359 | ||
360 | } | |
361 | ||
362 | /** | |
363 | * Base class to provide the labels for the left tree view entry. Views | |
364 | * extending this class typically need to override the getColumnText method | |
365 | * if they have more than one column to display | |
366 | */ | |
367 | protected static class TreeLabelProvider implements ITableLabelProvider { | |
368 | ||
369 | @Override | |
370 | public void addListener(ILabelProviderListener listener) { | |
371 | } | |
372 | ||
373 | @Override | |
374 | public void dispose() { | |
375 | } | |
376 | ||
377 | @Override | |
378 | public boolean isLabelProperty(Object element, String property) { | |
379 | return false; | |
380 | } | |
381 | ||
382 | @Override | |
383 | public void removeListener(ILabelProviderListener listener) { | |
384 | } | |
385 | ||
386 | @Override | |
387 | public Image getColumnImage(Object element, int columnIndex) { | |
388 | return null; | |
389 | } | |
390 | ||
391 | @Override | |
392 | public String getColumnText(Object element, int columnIndex) { | |
393 | TimeGraphEntry entry = (TimeGraphEntry) element; | |
394 | if (columnIndex == 0) { | |
395 | return entry.getName(); | |
396 | } | |
397 | return ""; //$NON-NLS-1$ | |
398 | } | |
399 | ||
400 | } | |
401 | ||
402 | private class BuildThread extends Thread { | |
403 | private final ITmfTrace fBuildTrace; | |
404 | private final IProgressMonitor fMonitor; | |
405 | ||
406 | public BuildThread(final ITmfTrace trace, final String name) { | |
407 | super(name + " build"); //$NON-NLS-1$ | |
408 | fBuildTrace = trace; | |
409 | fMonitor = new NullProgressMonitor(); | |
410 | } | |
411 | ||
412 | @Override | |
413 | public void run() { | |
414 | buildEventList(fBuildTrace, fMonitor); | |
415 | synchronized (fBuildThreadMap) { | |
416 | fBuildThreadMap.remove(this); | |
417 | } | |
418 | } | |
419 | ||
420 | public void cancel() { | |
421 | fMonitor.setCanceled(true); | |
422 | } | |
423 | } | |
424 | ||
425 | private class ZoomThread extends Thread { | |
426 | private final List<TimeGraphEntry> fZoomEntryList; | |
427 | private final long fZoomStartTime; | |
428 | private final long fZoomEndTime; | |
429 | private final long fResolution; | |
430 | private final IProgressMonitor fMonitor; | |
431 | ||
432 | public ZoomThread(List<TimeGraphEntry> entryList, long startTime, long endTime, String name) { | |
433 | super(name + " zoom"); //$NON-NLS-1$ | |
434 | fZoomEntryList = entryList; | |
435 | fZoomStartTime = startTime; | |
436 | fZoomEndTime = endTime; | |
437 | fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth); | |
438 | fMonitor = new NullProgressMonitor(); | |
439 | } | |
440 | ||
441 | @Override | |
442 | public void run() { | |
443 | if (fZoomEntryList == null) { | |
444 | return; | |
445 | } | |
446 | for (TimeGraphEntry entry : fZoomEntryList) { | |
447 | if (fMonitor.isCanceled()) { | |
448 | break; | |
449 | } | |
450 | zoom(entry, fMonitor); | |
451 | } | |
bec1f1ac GB |
452 | /* Refresh the arrows when zooming */ |
453 | List<ILinkEvent> events = getLinkList(fZoomStartTime, fZoomEndTime, fResolution, fMonitor); | |
454 | fTimeGraphCombo.setLinks(events); | |
455 | redraw(); | |
4999a196 GB |
456 | } |
457 | ||
458 | private void zoom(TimeGraphEntry entry, IProgressMonitor monitor) { | |
459 | if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) { | |
460 | entry.setZoomedEventList(null); | |
461 | } else { | |
462 | List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor); | |
463 | if (zoomedEventList != null) { | |
464 | entry.setZoomedEventList(zoomedEventList); | |
465 | } | |
466 | } | |
467 | redraw(); | |
468 | for (TimeGraphEntry child : entry.getChildren()) { | |
469 | if (fMonitor.isCanceled()) { | |
470 | return; | |
471 | } | |
472 | zoom(child, monitor); | |
473 | } | |
474 | } | |
475 | ||
476 | public void cancel() { | |
477 | fMonitor.setCanceled(true); | |
478 | } | |
479 | } | |
480 | ||
481 | // ------------------------------------------------------------------------ | |
482 | // Constructors | |
483 | // ------------------------------------------------------------------------ | |
484 | ||
485 | /** | |
486 | * Constructor | |
487 | * | |
488 | * @param id | |
489 | * The id of the view | |
490 | * @param cols | |
491 | * The columns to display in the tree view on the left | |
492 | * @param filterCols | |
493 | * The columns list to filter the view | |
494 | * @param pres | |
495 | * The presentation provider | |
496 | */ | |
497 | public AbstractTimeGraphView(String id, String[] cols, String[] filterCols, | |
498 | TimeGraphPresentationProvider pres) { | |
499 | super(id); | |
500 | fColumns = cols; | |
501 | fFilterColumns = filterCols; | |
502 | fPresentation = pres; | |
503 | fDisplayWidth = Display.getDefault().getBounds().width; | |
504 | } | |
505 | ||
506 | // ------------------------------------------------------------------------ | |
507 | // ViewPart | |
508 | // ------------------------------------------------------------------------ | |
509 | ||
510 | @Override | |
511 | public void createPartControl(Composite parent) { | |
512 | fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE, fWeight); | |
513 | ||
514 | fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider()); | |
515 | ||
516 | fTimeGraphCombo.setTreeLabelProvider(fLabelProvider); | |
517 | ||
518 | fTimeGraphCombo.setTimeGraphProvider(fPresentation); | |
519 | ||
520 | fTimeGraphCombo.setTreeColumns(fColumns); | |
521 | ||
522 | fTimeGraphCombo.setFilterContentProvider(new TreeContentProvider()); | |
523 | ||
524 | fTimeGraphCombo.setFilterLabelProvider(new TreeLabelProvider()); | |
525 | ||
526 | fTimeGraphCombo.setFilterColumns(fFilterColumns); | |
527 | ||
528 | fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() { | |
529 | @Override | |
530 | public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) { | |
531 | final long startTime = event.getStartTime(); | |
532 | final long endTime = event.getEndTime(); | |
f566d40a | 533 | TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime)); |
0fcf3b09 | 534 | broadcast(new TmfRangeSynchSignal(AbstractTimeGraphView.this, range)); |
4999a196 GB |
535 | if (fZoomThread != null) { |
536 | fZoomThread.cancel(); | |
537 | } | |
538 | startZoomThread(startTime, endTime); | |
539 | } | |
540 | }); | |
541 | ||
542 | fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() { | |
543 | @Override | |
544 | public void timeSelected(TimeGraphTimeEvent event) { | |
f566d40a PT |
545 | TmfNanoTimestamp startTime = new TmfNanoTimestamp(event.getBeginTime()); |
546 | TmfNanoTimestamp endTime = new TmfNanoTimestamp(event.getEndTime()); | |
0fcf3b09 | 547 | broadcast(new TmfTimeSynchSignal(AbstractTimeGraphView.this, startTime, endTime)); |
4999a196 GB |
548 | } |
549 | }); | |
550 | ||
551 | fTimeGraphCombo.addSelectionListener(new ITimeGraphSelectionListener() { | |
552 | @Override | |
553 | public void selectionChanged(TimeGraphSelectionEvent event) { | |
554 | // ITimeGraphEntry selection = event.getSelection(); | |
555 | } | |
556 | }); | |
557 | ||
558 | fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR); | |
559 | ||
0fcf3b09 PT |
560 | IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager(); |
561 | fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager); | |
562 | ||
4999a196 GB |
563 | // View Action Handling |
564 | makeActions(); | |
565 | contributeToActionBars(); | |
566 | ||
567 | ITmfTrace trace = getActiveTrace(); | |
568 | if (trace != null) { | |
569 | traceSelected(new TmfTraceSelectedSignal(this, trace)); | |
570 | } | |
571 | ||
572 | // make selection available to other views | |
573 | getSite().setSelectionProvider(fTimeGraphCombo.getTreeViewer()); | |
574 | } | |
575 | ||
576 | @Override | |
577 | public void setFocus() { | |
578 | fTimeGraphCombo.setFocus(); | |
579 | } | |
580 | ||
581 | // ------------------------------------------------------------------------ | |
582 | // Signal handlers | |
583 | // ------------------------------------------------------------------------ | |
584 | ||
585 | /** | |
586 | * Handler for the trace opened signal. | |
587 | * | |
588 | * @param signal | |
589 | * The incoming signal | |
590 | * @since 2.0 | |
591 | */ | |
592 | @TmfSignalHandler | |
593 | public void traceOpened(TmfTraceOpenedSignal signal) { | |
594 | fTrace = signal.getTrace(); | |
595 | loadTrace(); | |
596 | } | |
597 | ||
598 | /** | |
599 | * Handler for the trace selected signal | |
600 | * | |
601 | * @param signal | |
602 | * The incoming signal | |
603 | */ | |
604 | @TmfSignalHandler | |
605 | public void traceSelected(final TmfTraceSelectedSignal signal) { | |
606 | if (signal.getTrace() == fTrace) { | |
607 | return; | |
608 | } | |
609 | fTrace = signal.getTrace(); | |
610 | ||
611 | loadTrace(); | |
612 | } | |
613 | ||
614 | /** | |
615 | * Trace is closed: clear the data structures and the view | |
616 | * | |
617 | * @param signal | |
618 | * the signal received | |
619 | */ | |
620 | @TmfSignalHandler | |
621 | public void traceClosed(final TmfTraceClosedSignal signal) { | |
622 | synchronized (fBuildThreadMap) { | |
623 | BuildThread buildThread = fBuildThreadMap.remove(signal.getTrace()); | |
624 | if (buildThread != null) { | |
625 | buildThread.cancel(); | |
626 | } | |
627 | } | |
628 | synchronized (fEntryListMap) { | |
629 | fEntryListMap.remove(signal.getTrace()); | |
630 | } | |
631 | if (signal.getTrace() == fTrace) { | |
632 | fTrace = null; | |
633 | fStartTime = 0; | |
634 | fEndTime = 0; | |
635 | if (fZoomThread != null) { | |
636 | fZoomThread.cancel(); | |
637 | } | |
638 | refresh(); | |
639 | } | |
640 | } | |
641 | ||
642 | /** | |
0fcf3b09 | 643 | * Handler for the time synch signal |
4999a196 GB |
644 | * |
645 | * @param signal | |
646 | * The signal that's received | |
647 | */ | |
648 | @TmfSignalHandler | |
649 | public void synchToTime(final TmfTimeSynchSignal signal) { | |
650 | if (signal.getSource() == this || fTrace == null) { | |
651 | return; | |
652 | } | |
0fcf3b09 PT |
653 | final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); |
654 | final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
4999a196 GB |
655 | |
656 | Display.getDefault().asyncExec(new Runnable() { | |
657 | @Override | |
658 | public void run() { | |
659 | if (fTimeGraphCombo.isDisposed()) { | |
660 | return; | |
661 | } | |
0fcf3b09 PT |
662 | if (beginTime == endTime) { |
663 | fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true); | |
664 | } else { | |
665 | fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime); | |
666 | } | |
4999a196 GB |
667 | startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1()); |
668 | ||
0fcf3b09 | 669 | synchingToTime(beginTime); |
4999a196 GB |
670 | } |
671 | }); | |
672 | } | |
673 | ||
674 | /** | |
0fcf3b09 | 675 | * Handler for the range synch signal |
4999a196 GB |
676 | * |
677 | * @param signal | |
678 | * The signal that's received | |
679 | */ | |
680 | @TmfSignalHandler | |
681 | public void synchToRange(final TmfRangeSynchSignal signal) { | |
682 | if (signal.getSource() == this || fTrace == null) { | |
683 | return; | |
684 | } | |
685 | if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) { | |
686 | return; | |
687 | } | |
688 | final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
689 | final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
4999a196 GB |
690 | Display.getDefault().asyncExec(new Runnable() { |
691 | @Override | |
692 | public void run() { | |
693 | if (fTimeGraphCombo.isDisposed()) { | |
694 | return; | |
695 | } | |
696 | fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime); | |
4999a196 GB |
697 | startZoomThread(startTime, endTime); |
698 | } | |
699 | }); | |
700 | } | |
701 | ||
c1cd9635 MAL |
702 | /** |
703 | * @param signal the format of the timestamps was updated. | |
bec1f1ac | 704 | * @since 2.1 |
c1cd9635 MAL |
705 | */ |
706 | @TmfSignalHandler | |
707 | public void updateTimeFormat( final TmfTimestampFormatUpdateSignal signal){ | |
708 | this.fTimeGraphCombo.refresh(); | |
709 | } | |
710 | ||
4999a196 GB |
711 | // ------------------------------------------------------------------------ |
712 | // Internal | |
713 | // ------------------------------------------------------------------------ | |
714 | ||
715 | private void loadTrace() { | |
716 | synchronized (fEntryListMap) { | |
717 | fEntryList = fEntryListMap.get(fTrace); | |
718 | if (fEntryList == null) { | |
719 | synchronized (fBuildThreadMap) { | |
720 | BuildThread buildThread = new BuildThread(fTrace, this.getName()); | |
721 | fBuildThreadMap.put(fTrace, buildThread); | |
722 | buildThread.start(); | |
723 | } | |
724 | } else { | |
725 | fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
726 | fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
727 | refresh(); | |
728 | } | |
729 | } | |
730 | } | |
731 | ||
732 | /** | |
733 | * Method called when synching to a given timestamp. Inheriting classes can | |
734 | * perform actions here to update the view at the given timestamp. | |
735 | * | |
736 | * @param time | |
737 | * The currently selected time | |
738 | */ | |
739 | protected void synchingToTime(long time) { | |
740 | ||
741 | } | |
742 | ||
743 | /** | |
744 | * Build the entries list to show in this time graph | |
745 | * | |
746 | * Called from the BuildThread | |
747 | * | |
748 | * @param trace | |
749 | * The trace being built | |
750 | * @param monitor | |
751 | * The progress monitor object | |
752 | */ | |
753 | protected abstract void buildEventList(final ITmfTrace trace, IProgressMonitor monitor); | |
754 | ||
755 | /** | |
756 | * Gets the list of event for an entry in a given timerange | |
757 | * | |
758 | * @param entry | |
759 | * The entry to get events for | |
760 | * @param startTime | |
761 | * Start of the time range | |
762 | * @param endTime | |
763 | * End of the time range | |
764 | * @param resolution | |
765 | * The resolution | |
766 | * @param monitor | |
767 | * The progress monitor object | |
768 | * @return The list of events for the entry | |
769 | */ | |
770 | protected abstract List<ITimeEvent> getEventList(TimeGraphEntry entry, | |
771 | long startTime, long endTime, long resolution, | |
772 | IProgressMonitor monitor); | |
773 | ||
bec1f1ac GB |
774 | /** |
775 | * Gets the list of links (displayed as arrows) for a trace in a given | |
776 | * timerange. Default implementation returns an empty list. | |
777 | * | |
778 | * @param startTime | |
779 | * Start of the time range | |
780 | * @param endTime | |
781 | * End of the time range | |
782 | * @param resolution | |
783 | * The resolution | |
784 | * @param monitor | |
785 | * The progress monitor object | |
786 | * @return The list of link events | |
787 | * @since 2.1 | |
788 | */ | |
789 | protected List<ILinkEvent> getLinkList(long startTime, long endTime, | |
790 | long resolution, IProgressMonitor monitor) { | |
791 | return new ArrayList<ILinkEvent>(); | |
792 | } | |
793 | ||
794 | ||
4999a196 GB |
795 | /** |
796 | * Refresh the display | |
797 | */ | |
798 | protected void refresh() { | |
799 | Display.getDefault().asyncExec(new Runnable() { | |
800 | @Override | |
801 | public void run() { | |
802 | if (fTimeGraphCombo.isDisposed()) { | |
803 | return; | |
804 | } | |
805 | ITimeGraphEntry[] entries = null; | |
806 | synchronized (fEntryListMap) { | |
807 | fEntryList = fEntryListMap.get(fTrace); | |
808 | if (fEntryList == null) { | |
809 | fEntryList = new ArrayList<TimeGraphEntry>(); | |
810 | } | |
811 | entries = fEntryList.toArray(new ITimeGraphEntry[0]); | |
812 | } | |
813 | if (fEntryComparator != null) { | |
814 | Arrays.sort(entries, fEntryComparator); | |
815 | } | |
816 | fTimeGraphCombo.setInput(entries); | |
817 | fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime); | |
818 | ||
0fcf3b09 PT |
819 | long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); |
820 | long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
4999a196 GB |
821 | long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); |
822 | long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
823 | startTime = Math.max(startTime, fStartTime); | |
824 | endTime = Math.min(endTime, fEndTime); | |
0fcf3b09 | 825 | fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime); |
4999a196 GB |
826 | fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime); |
827 | ||
828 | for (TreeColumn column : fTimeGraphCombo.getTreeViewer().getTree().getColumns()) { | |
829 | column.pack(); | |
830 | } | |
831 | ||
832 | startZoomThread(startTime, endTime); | |
833 | } | |
834 | }); | |
835 | } | |
836 | ||
837 | /** | |
838 | * Redraw the canvas | |
839 | */ | |
840 | protected void redraw() { | |
841 | synchronized (fSyncObj) { | |
842 | if (fRedrawState == State.IDLE) { | |
843 | fRedrawState = State.BUSY; | |
844 | } else { | |
845 | fRedrawState = State.PENDING; | |
846 | return; | |
847 | } | |
848 | } | |
849 | Display.getDefault().asyncExec(new Runnable() { | |
850 | @Override | |
851 | public void run() { | |
852 | if (fTimeGraphCombo.isDisposed()) { | |
853 | return; | |
854 | } | |
855 | fTimeGraphCombo.redraw(); | |
856 | fTimeGraphCombo.update(); | |
857 | synchronized (fSyncObj) { | |
858 | if (fRedrawState == State.PENDING) { | |
859 | fRedrawState = State.IDLE; | |
860 | redraw(); | |
861 | } else { | |
862 | fRedrawState = State.IDLE; | |
863 | } | |
864 | } | |
865 | } | |
866 | }); | |
867 | } | |
868 | ||
869 | private void startZoomThread(long startTime, long endTime) { | |
870 | if (fZoomThread != null) { | |
871 | fZoomThread.cancel(); | |
872 | } | |
873 | fZoomThread = new ZoomThread(fEntryList, startTime, endTime, getName()); | |
874 | fZoomThread.start(); | |
875 | } | |
876 | ||
877 | private void makeActions() { | |
878 | fPreviousResourceAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction(); | |
879 | fPreviousResourceAction.setText(getPrevText()); | |
880 | fPreviousResourceAction.setToolTipText(getPrevTooltip()); | |
881 | fNextResourceAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction(); | |
882 | fNextResourceAction.setText(getNextText()); | |
883 | fNextResourceAction.setToolTipText(getNextTooltip()); | |
884 | } | |
885 | ||
886 | private void contributeToActionBars() { | |
887 | IActionBars bars = getViewSite().getActionBars(); | |
888 | fillLocalToolBar(bars.getToolBarManager()); | |
889 | } | |
890 | ||
891 | private void fillLocalToolBar(IToolBarManager manager) { | |
892 | if (fFilterColumns.length > 0) { | |
893 | manager.add(fTimeGraphCombo.getShowFilterAction()); | |
894 | } | |
895 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getShowLegendAction()); | |
896 | manager.add(new Separator()); | |
897 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction()); | |
898 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getPreviousEventAction()); | |
899 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getNextEventAction()); | |
900 | manager.add(fPreviousResourceAction); | |
901 | manager.add(fNextResourceAction); | |
902 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction()); | |
903 | manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction()); | |
904 | manager.add(new Separator()); | |
905 | } | |
906 | } |