tmf: add dragging support with middle mouse button
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / xycharts / TmfXYChartViewer.java
1 /**********************************************************************
2 * Copyright (c) 2013 Ericsson
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 * Bernd Hufmann - Initial API and implementation
11 **********************************************************************/
12 package org.eclipse.linuxtools.tmf.ui.viewers.xycharts;
13
14 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
15 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
16 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalThrottler;
17 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
18 import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal;
19 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
20 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
21 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
22 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
23 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
24 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
25 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
26 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
27 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
28 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
29 import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
30 import org.eclipse.swt.SWT;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.swt.widgets.Display;
34 import org.swtchart.Chart;
35 import org.swtchart.IAxis;
36 import org.swtchart.ISeries;
37 import org.swtchart.ISeriesSet;
38
39 /**
40 * Base class for a XY-Chart based on SWT chart. It provides a methods to define
41 * zoom, selection and tool tip providers. It also provides call backs to be
42 * notified by any changes caused by selection and zoom.
43 *
44 * @author Bernd Hufmann
45 * @since 3.0
46 */
47 public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTimeProvider {
48
49 // ------------------------------------------------------------------------
50 // Attributes
51 // ------------------------------------------------------------------------
52 /**
53 * The offset to apply to any x position. This offset ensures better
54 * precision when converting long to double and back.
55 */
56 private long fTimeOffset;
57 /** Start time of trace */
58 private long fStartTime;
59 /** End time of trace */
60 private long fEndTime;
61 /** Start time of current time range */
62 private long fWindowStartTime;
63 /** End time of current time range */
64 private long fWindowEndTime;
65 /** Duration of current time range */
66 private long fWindowDuration;
67 /** Current begin time of selection range */
68 private long fSelectionBeginTime;
69 /** Current end of selection range */
70 private long fSelectionEndTime;
71 /** The trace that is displayed by this viewer */
72 private ITmfTrace fTrace;
73 /** The SWT Chart reference */
74 private Chart fSwtChart;
75 /** A signal throttler for range updates */
76 private final TmfSignalThrottler fTimeRangeSyncThrottle = new TmfSignalThrottler(this, 200);
77 /** The mouse selection provider */
78 private TmfBaseProvider fMouseSelectionProvider;
79 /** The mouse drag zoom provider */
80 private TmfBaseProvider fMouseDragZoomProvider;
81 /** The mouse wheel zoom provider */
82 private TmfBaseProvider fMouseWheelZoomProvider;
83 /** The tooltip provider */
84 private TmfBaseProvider fToolTipProvider;
85 /** The middle mouse drag provider */
86 private TmfBaseProvider fMouseDragProvider;
87
88 // ------------------------------------------------------------------------
89 // Constructors
90 // ------------------------------------------------------------------------
91
92 /**
93 * Constructs a TmfXYChartViewer.
94 *
95 * @param parent
96 * The parent composite
97 * @param title
98 * The title of the viewer
99 * @param xLabel
100 * The label of the xAxis
101 * @param yLabel
102 * The label of the yAXIS
103 */
104 public TmfXYChartViewer(Composite parent, String title, String xLabel, String yLabel) {
105 super(parent, title);
106 fSwtChart = new Chart(parent, SWT.NONE);
107
108 IAxis xAxis = fSwtChart.getAxisSet().getXAxis(0);
109 IAxis yAxis = fSwtChart.getAxisSet().getYAxis(0);
110
111 /* Set the title/labels, or hide them if they are not provided */
112 if (title == null) {
113 fSwtChart.getTitle().setVisible(false);
114 } else {
115 fSwtChart.getTitle().setText(title);
116 }
117 if (xLabel == null) {
118 xAxis.getTitle().setVisible(false);
119 } else {
120 xAxis.getTitle().setText(xLabel);
121 }
122 if (yLabel == null) {
123 yAxis.getTitle().setVisible(false);
124 } else {
125 yAxis.getTitle().setText(yLabel);
126 }
127
128 fMouseSelectionProvider = new TmfMouseSelectionProvider(this);
129 fMouseDragZoomProvider = new TmfMouseDragZoomProvider(this);
130 fMouseWheelZoomProvider = new TmfMouseWheelZoomProvider(this);
131 fToolTipProvider = new TmfSimpleTooltipProvider(this);
132 fMouseDragProvider = new TmfMouseDragProvider(this);
133 }
134
135 // ------------------------------------------------------------------------
136 // Getter/Setters
137 // ------------------------------------------------------------------------
138 /**
139 * Sets the time offset to apply.
140 * @see ITmfChartTimeProvider#getTimeOffset()
141 *
142 * @param timeOffset
143 * The time offset to apply
144 */
145 protected void setTimeOffset(long timeOffset) {
146 fTimeOffset = timeOffset;
147 }
148
149 /**
150 * Sets the start time of the trace
151 *
152 * @param startTime
153 * The start time to set
154 */
155 protected void setStartTime(long startTime) {
156 fStartTime = startTime;
157 }
158
159 /**
160 * Sets the end time of the trace
161 *
162 * @param endTime
163 * The start time to set
164 */
165 protected void setEndTime(long endTime) {
166 fEndTime = endTime;
167 }
168
169 /**
170 * Sets the start time of the current time range window
171 *
172 * @param windowStartTime
173 * The start time to set
174 */
175 protected void setWindowStartTime(long windowStartTime) {
176 fWindowStartTime = windowStartTime;
177 }
178
179 /**
180 * Sets the end time of the current time range window
181 *
182 * @param windowEndTime
183 * The start time to set
184 */
185 protected void setWindowEndTime(long windowEndTime) {
186 fWindowEndTime = windowEndTime;
187 }
188
189 /**
190 * Sets the start time of the current time range window
191 *
192 * @param windowDuration
193 * The start time to set
194 */
195 protected void setWindowDuration(long windowDuration) {
196 fWindowDuration = windowDuration;
197 }
198
199 /**
200 * Sets the begin time of the selection range.
201 *
202 * @param selectionBeginTime
203 * The begin time to set
204 */
205 protected void setSelectionBeginTime(long selectionBeginTime) {
206 fSelectionBeginTime = selectionBeginTime;
207 }
208
209 /**
210 * Sets the end time of the selection range.
211 *
212 * @param selectionEndTime
213 * The end time to set
214 */
215 protected void setSelectionEndTime(long selectionEndTime) {
216 fSelectionEndTime = selectionEndTime;
217 }
218
219 /**
220 * Sets the trace that is displayed by this viewer.
221 *
222 * @param trace
223 * The trace to set
224 */
225 protected void setTrace(ITmfTrace trace) {
226 fTrace = trace;
227 }
228
229 /**
230 * Gets the trace that is displayed by this viewer.
231 *
232 * @return the trace
233 */
234 protected ITmfTrace getTrace() {
235 return fTrace;
236 }
237
238 /**
239 * Sets the SWT Chart reference
240 *
241 * @param chart
242 * The SWT chart to set.
243 */
244 protected void setSwtChart(Chart chart) {
245 fSwtChart = chart;
246 }
247
248 /**
249 * Gets the SWT Chart reference
250 *
251 * @return the SWT chart to set.
252 */
253 protected Chart getSwtChart() {
254 return fSwtChart;
255 }
256
257 /**
258 * Sets a mouse selection provider. An existing provider will be
259 * disposed. Use <code>null</code> to disable the mouse selection provider.
260 *
261 * @param provider
262 * The selection provider to set
263 */
264 public void setSelectionProvider(TmfBaseProvider provider) {
265 if (fMouseSelectionProvider != null) {
266 fMouseSelectionProvider.dispose();
267 }
268 fMouseSelectionProvider = provider;
269 }
270
271 /**
272 * Sets a mouse drag zoom provider. An existing provider will be
273 * disposed. Use <code>null</code> to disable the mouse drag zoom provider.
274 *
275 * @param provider
276 * The mouse drag zoom provider to set
277 */
278 public void setMouseDragZoomProvider(TmfBaseProvider provider) {
279 if (fMouseDragZoomProvider != null) {
280 fMouseDragZoomProvider.dispose();
281 }
282 fMouseDragZoomProvider = provider;
283 }
284
285 /**
286 * Sets a mouse wheel zoom provider. An existing provider will be
287 * disposed. Use <code>null</code> to disable the mouse wheel zoom
288 * provider.
289 *
290 * @param provider
291 * The mouse wheel zoom provider to set
292 */
293 public void setMouseWheelZoomProvider(TmfBaseProvider provider) {
294 if (fMouseWheelZoomProvider != null) {
295 fMouseWheelZoomProvider.dispose();
296 }
297 fMouseWheelZoomProvider = provider;
298 }
299
300 /**
301 * Sets a tooltip provider. An existing provider will be
302 * disposed. Use <code>null</code> to disable the tooltip provider.
303 *
304 * @param provider
305 * The tooltip provider to set
306 */
307 public void setTooltipProvider(TmfBaseProvider provider) {
308 if (fToolTipProvider != null) {
309 fToolTipProvider.dispose();
310 }
311 fToolTipProvider = provider;
312 }
313
314 /**
315 * Sets a mouse drag provider. An existing provider will be
316 * disposed. Use <code>null</code> to disable the mouse drag provider.
317 *
318 * @param provider
319 * The mouse drag provider to set
320 */
321 public void setMouseDrageProvider(TmfBaseProvider provider) {
322 if (fMouseDragProvider != null) {
323 fMouseDragProvider.dispose();
324 }
325 fMouseDragProvider = provider;
326 }
327
328 // ------------------------------------------------------------------------
329 // ITmfChartTimeProvider
330 // ------------------------------------------------------------------------
331 @Override
332 public long getStartTime() {
333 return fStartTime;
334 }
335
336 @Override
337 public long getEndTime() {
338 return fEndTime;
339 }
340
341 @Override
342 public long getWindowStartTime() {
343 return fWindowStartTime;
344 }
345
346 @Override
347 public long getWindowEndTime() {
348 return fWindowEndTime;
349 }
350
351 @Override
352 public long getWindowDuration() {
353 return fWindowDuration;
354 }
355
356 @Override
357 public long getSelectionBeginTime() {
358 return fSelectionBeginTime;
359 }
360
361 @Override
362 public long getSelectionEndTime() {
363 return fSelectionEndTime;
364 }
365
366 @Override
367 public long getTimeOffset() {
368 return fTimeOffset;
369 }
370
371 @Override
372 public void updateSelectionRange(final long currentBeginTime, final long currentEndTime) {
373 if (fTrace != null) {
374 setSelectionBeginTime(currentBeginTime);
375 setSelectionEndTime(currentEndTime);
376
377 final ITmfTimestamp startTimestamp = new TmfTimestamp(fSelectionBeginTime, ITmfTimestamp.NANOSECOND_SCALE);
378 final ITmfTimestamp endTimestamp = new TmfTimestamp(fSelectionEndTime, ITmfTimestamp.NANOSECOND_SCALE);
379
380 TmfTimeSynchSignal signal = new TmfTimeSynchSignal(TmfXYChartViewer.this, startTimestamp, endTimestamp);
381 broadcast(signal);
382 }
383 }
384
385 @Override
386 public void updateWindow(long windowStartTime, long windowEndTime) {
387
388 setWindowStartTime(windowStartTime);
389 setWindowEndTime(windowEndTime);
390 fWindowDuration = windowEndTime - windowStartTime;
391
392 // Build the new time range; keep the current time
393 TmfTimeRange timeRange = new TmfTimeRange(
394 new TmfTimestamp(fWindowStartTime, ITmfTimestamp.NANOSECOND_SCALE),
395 new TmfTimestamp(fWindowEndTime, ITmfTimestamp.NANOSECOND_SCALE));
396
397 // Send the signal
398 TmfRangeSynchSignal signal = new TmfRangeSynchSignal(this, timeRange);
399 fTimeRangeSyncThrottle.queue(signal);
400 }
401
402 // ------------------------------------------------------------------------
403 // ITmfViewer interface
404 // ------------------------------------------------------------------------
405 @Override
406 public Control getControl() {
407 return fSwtChart;
408 }
409
410 @Override
411 public void refresh() {
412 fSwtChart.redraw();
413 }
414
415 // ------------------------------------------------------------------------
416 // TmfComponent
417 // ------------------------------------------------------------------------
418 @Override
419 public void dispose() {
420 super.dispose();
421 fSwtChart.dispose();
422
423 if (fMouseSelectionProvider != null) {
424 fMouseSelectionProvider.dispose();
425 }
426
427 if (fMouseDragZoomProvider != null) {
428 fMouseDragZoomProvider.dispose();
429 }
430
431 if (fMouseWheelZoomProvider != null) {
432 fMouseWheelZoomProvider.dispose();
433 }
434
435 if (fToolTipProvider != null) {
436 fToolTipProvider.dispose();
437 }
438
439 if (fMouseDragProvider != null) {
440 fMouseDragProvider.dispose();
441 }
442 }
443
444 // ------------------------------------------------------------------------
445 // Operations
446 // ------------------------------------------------------------------------
447 /**
448 * A Method to load a trace into the viewer.
449 *
450 * @param trace
451 * A trace to apply in the viewer
452 */
453 public void loadTrace(ITmfTrace trace) {
454 fTrace = trace;
455
456 long timestamp = TmfTraceManager.getInstance().getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
457 long windowStartTime = TmfTraceManager.getInstance().getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
458 long startTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
459 long endTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
460
461 setSelectionBeginTime(timestamp);
462 setSelectionEndTime(timestamp);
463 setStartTime(startTime);
464 setWindowStartTime(windowStartTime);
465 setWindowDuration(fTrace.getInitialRangeOffset().getValue());
466 setEndTime(endTime);
467 setWindowEndTime(windowStartTime + getWindowDuration());
468 clearContent();
469 updateContent();
470 }
471
472 /**
473 * Resets the content of the viewer
474 */
475 public void reset() {
476 // Reset the internal data
477 setSelectionBeginTime(0);
478 setSelectionEndTime(0);
479 setStartTime(0);
480 setWindowStartTime(0);
481 setWindowDuration(0);
482 setEndTime(0);
483 setWindowEndTime(0);
484 setTrace(null);
485 clearContent();
486 }
487
488 /**
489 * Method to implement to update the chart content.
490 */
491 protected abstract void updateContent();
492
493 // ------------------------------------------------------------------------
494 // Signal Handler
495 // ------------------------------------------------------------------------
496
497 /**
498 * Signal handler for handling of the trace opened signal.
499 *
500 * @param signal
501 * The trace opened signal {@link TmfTraceOpenedSignal}
502 */
503 @TmfSignalHandler
504 public void traceOpened(TmfTraceOpenedSignal signal) {
505 fTrace = signal.getTrace();
506 loadTrace(getTrace());
507 }
508
509 /**
510 * Signal handler for handling of the trace selected signal.
511 *
512 * @param signal
513 * The trace selected signal {@link TmfTraceSelectedSignal}
514 */
515 @TmfSignalHandler
516 public void traceSelected(TmfTraceSelectedSignal signal) {
517 if (fTrace != signal.getTrace()) {
518 fTrace = signal.getTrace();
519 loadTrace(getTrace());
520 }
521 }
522
523 /**
524 * Signal handler for handling of the trace closed signal.
525 *
526 * @param signal
527 * The trace closed signal {@link TmfTraceClosedSignal}
528 */
529 @TmfSignalHandler
530 public void traceClosed(TmfTraceClosedSignal signal) {
531
532 if (signal.getTrace() != fTrace) {
533 return;
534 }
535
536 // Reset the internal data
537 fTrace = null;
538 reset();
539 }
540
541 /**
542 * Signal handler for handling of the time synch signal.
543 *
544 * @param signal
545 * The time synch signal {@link TmfTimeSynchSignal}
546 */
547 @TmfSignalHandler
548 public void selectionRangeUpdated(TmfTimeSynchSignal signal) {
549 if ((signal.getSource() != this) && (fTrace != null)) {
550 ITmfTimestamp selectedTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE);
551 ITmfTimestamp selectedEndTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE);
552 setSelectionBeginTime(selectedTime.getValue());
553 setSelectionEndTime(selectedEndTime.getValue());
554 if (fMouseSelectionProvider != null) {
555 fMouseSelectionProvider.refresh();
556 }
557 }
558 }
559
560 /**
561 * Signal handler for handling of the time range synch signal.
562 *
563 * @param signal
564 * The time range synch signal {@link TmfRangeSynchSignal}
565 */
566 @TmfSignalHandler
567 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
568
569 if (fTrace != null) {
570 // Validate the time range
571 TmfTimeRange range = signal.getCurrentRange().getIntersection(fTrace.getTimeRange());
572 if (range == null) {
573 return;
574 }
575
576 if (signal.getSource() != this) {
577 // Update the time range
578 long windowStartTime = range.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
579 long windowEndTime = range.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
580 long windowDuration = windowEndTime - windowStartTime;
581
582 setWindowStartTime(windowStartTime);
583 setWindowEndTime(windowEndTime);
584 setWindowDuration(windowDuration);
585 }
586 }
587 updateContent();
588 }
589
590 /**
591 * Signal handler for handling of the trace range updated signal.
592 *
593 * @param signal
594 * The trace range signal {@link TmfTraceRangeUpdatedSignal}
595 */
596 @TmfSignalHandler
597 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
598
599 if (signal.getTrace() != fTrace) {
600 return;
601 }
602
603 TmfTimeRange fullRange = signal.getRange();
604
605 long traceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
606 long traceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
607
608 setStartTime(traceStartTime);
609 setEndTime(traceEndTime);
610 }
611
612 /**
613 * Signal handler for handling of the trace updated signal.
614 *
615 * @param signal
616 * The trace updated signal {@link TmfTraceUpdatedSignal}
617 */
618 @TmfSignalHandler
619 public void traceUpdated(TmfTraceUpdatedSignal signal) {
620 if (signal.getTrace() != fTrace) {
621 return;
622 }
623 TmfTimeRange fullRange = signal.getTrace().getTimeRange();
624 long traceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
625 long traceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
626
627 setStartTime(traceStartTime);
628 setEndTime(traceEndTime);
629 }
630
631 /**
632 * Signal handler for handling the signal that notifies about an updated
633 * timestamp format.
634 *
635 * @param signal
636 * The trace updated signal
637 * {@link TmfTimestampFormatUpdateSignal}
638 */
639 @TmfSignalHandler
640 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
641 fSwtChart.getAxisSet().adjustRange();
642 fSwtChart.redraw();
643 }
644
645 // ------------------------------------------------------------------------
646 // Helper Methods
647 // ------------------------------------------------------------------------
648
649 /**
650 * Clears the view content.
651 */
652 protected void clearContent() {
653 if (!fSwtChart.isDisposed()) {
654 ISeriesSet set = fSwtChart.getSeriesSet();
655 ISeries[] series = set.getSeries();
656 for (int i = 0; i < series.length; i++) {
657 set.deleteSeries(series[i].getId());
658 }
659 fSwtChart.redraw();
660 }
661 }
662
663 /**
664 * Returns the current or default display.
665 *
666 * @return the current or default display
667 */
668 protected static Display getDisplay() {
669 Display display = Display.getCurrent();
670 // may be null if outside the UI thread
671 if (display == null) {
672 display = Display.getDefault();
673 }
674 return display;
675 }
676
677 }
This page took 0.04734 seconds and 5 git commands to generate.