1 /**********************************************************************
2 * Copyright (c) 2013, 2016 Ericsson, École Polytechnique de Montréal
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
10 * Bernd Hufmann - Initial API and implementation
11 * Geneviève Bastien - Moved some methods to TmfTimeViewer
12 * Patrick Tasse - Fix setFocus
13 **********************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.xycharts
;
16 import org
.eclipse
.swt
.SWT
;
17 import org
.eclipse
.swt
.events
.MouseAdapter
;
18 import org
.eclipse
.swt
.events
.MouseEvent
;
19 import org
.eclipse
.swt
.widgets
.Composite
;
20 import org
.eclipse
.swt
.widgets
.Control
;
21 import org
.eclipse
.swt
.widgets
.Display
;
22 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
29 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.TmfTimeViewer
;
30 import org
.swtchart
.Chart
;
31 import org
.swtchart
.IAxis
;
32 import org
.swtchart
.ISeries
;
33 import org
.swtchart
.ISeriesSet
;
34 import org
.swtchart
.Range
;
36 import com
.google
.common
.annotations
.VisibleForTesting
;
39 * Base class for a XY-Chart based on SWT chart. It provides a methods to define
40 * zoom, selection and tool tip providers. It also provides call backs to be
41 * notified by any changes caused by selection and zoom.
43 * @author Bernd Hufmann
45 public abstract class TmfXYChartViewer
extends TmfTimeViewer
implements ITmfChartTimeProvider
{
47 // ------------------------------------------------------------------------
49 // ------------------------------------------------------------------------
50 /** The SWT Chart reference */
51 private Chart fSwtChart
;
52 /** The mouse selection provider */
53 private TmfBaseProvider fMouseSelectionProvider
;
54 /** The mouse drag zoom provider */
55 private TmfBaseProvider fMouseDragZoomProvider
;
56 /** The mouse wheel zoom provider */
57 private TmfBaseProvider fMouseWheelZoomProvider
;
58 /** The tooltip provider */
59 private TmfBaseProvider fToolTipProvider
;
60 /** The middle mouse drag provider */
61 private TmfBaseProvider fMouseDragProvider
;
63 * Whether or not to send time alignment signals. This should be set to true
64 * for viewers that are part of an aligned view.
66 private boolean fSendTimeAlignSignals
= false;
69 // ------------------------------------------------------------------------
71 // ------------------------------------------------------------------------
74 * Constructs a TmfXYChartViewer.
77 * The parent composite
79 * The title of the viewer
81 * The label of the xAxis
83 * The label of the yAXIS
85 public TmfXYChartViewer(Composite parent
, String title
, String xLabel
, String yLabel
) {
87 fSwtChart
= new Chart(parent
, SWT
.NONE
) {
89 public boolean setFocus() {
90 return fSwtChart
.getPlotArea().setFocus();
93 fSwtChart
.getPlotArea().addMouseListener(new MouseAdapter() {
95 public void mouseDown(MouseEvent e
) {
96 fSwtChart
.getPlotArea().setFocus();
100 IAxis xAxis
= fSwtChart
.getAxisSet().getXAxis(0);
101 IAxis yAxis
= fSwtChart
.getAxisSet().getYAxis(0);
103 /* Set the title/labels, or hide them if they are not provided */
105 fSwtChart
.getTitle().setVisible(false);
107 fSwtChart
.getTitle().setText(title
);
109 if (xLabel
== null) {
110 xAxis
.getTitle().setVisible(false);
112 xAxis
.getTitle().setText(xLabel
);
114 if (yLabel
== null) {
115 yAxis
.getTitle().setVisible(false);
117 yAxis
.getTitle().setText(yLabel
);
120 fMouseSelectionProvider
= new TmfMouseSelectionProvider(this);
121 fMouseDragZoomProvider
= new TmfMouseDragZoomProvider(this);
122 fMouseWheelZoomProvider
= new TmfMouseWheelZoomProvider(this);
123 fToolTipProvider
= new TmfSimpleTooltipProvider(this);
124 fMouseDragProvider
= new TmfMouseDragProvider(this);
126 fSwtChart
.addDisposeListener((e
) -> {
131 // ------------------------------------------------------------------------
133 // ------------------------------------------------------------------------
136 * Sets the SWT Chart reference
139 * The SWT chart to set.
141 protected void setSwtChart(Chart chart
) {
146 * Gets the SWT Chart reference
148 * @return the SWT chart to set.
150 protected Chart
getSwtChart() {
155 * Sets a mouse selection provider. An existing provider will be
156 * disposed. Use <code>null</code> to disable the mouse selection provider.
159 * The selection provider to set
161 public void setSelectionProvider(TmfBaseProvider provider
) {
162 if (fMouseSelectionProvider
!= null) {
163 fMouseSelectionProvider
.dispose();
165 fMouseSelectionProvider
= provider
;
169 * Sets a mouse drag zoom provider. An existing provider will be
170 * disposed. Use <code>null</code> to disable the mouse drag zoom provider.
173 * The mouse drag zoom provider to set
175 public void setMouseDragZoomProvider(TmfBaseProvider provider
) {
176 if (fMouseDragZoomProvider
!= null) {
177 fMouseDragZoomProvider
.dispose();
179 fMouseDragZoomProvider
= provider
;
183 * Sets a mouse wheel zoom provider. An existing provider will be
184 * disposed. Use <code>null</code> to disable the mouse wheel zoom
188 * The mouse wheel zoom provider to set
190 public void setMouseWheelZoomProvider(TmfBaseProvider provider
) {
191 if (fMouseWheelZoomProvider
!= null) {
192 fMouseWheelZoomProvider
.dispose();
194 fMouseWheelZoomProvider
= provider
;
198 * Sets a tooltip provider. An existing provider will be
199 * disposed. Use <code>null</code> to disable the tooltip provider.
202 * The tooltip provider to set
204 public void setTooltipProvider(TmfBaseProvider provider
) {
205 if (fToolTipProvider
!= null) {
206 fToolTipProvider
.dispose();
208 fToolTipProvider
= provider
;
212 * Sets a mouse drag provider. An existing provider will be
213 * disposed. Use <code>null</code> to disable the mouse drag provider.
216 * The mouse drag provider to set
218 public void setMouseDrageProvider(TmfBaseProvider provider
) {
219 if (fMouseDragProvider
!= null) {
220 fMouseDragProvider
.dispose();
222 fMouseDragProvider
= provider
;
225 // ------------------------------------------------------------------------
226 // ITmfChartTimeProvider
227 // ------------------------------------------------------------------------
230 public long getTimeOffset() {
231 return getWindowStartTime() - 1;
234 // ------------------------------------------------------------------------
235 // ITmfViewer interface
236 // ------------------------------------------------------------------------
238 public Control
getControl() {
243 public void refresh() {
247 // ------------------------------------------------------------------------
249 // ------------------------------------------------------------------------
252 public void dispose() {
256 private void internalDispose() {
259 if (fMouseSelectionProvider
!= null) {
260 fMouseSelectionProvider
.dispose();
263 if (fMouseDragZoomProvider
!= null) {
264 fMouseDragZoomProvider
.dispose();
267 if (fMouseWheelZoomProvider
!= null) {
268 fMouseWheelZoomProvider
.dispose();
271 if (fToolTipProvider
!= null) {
272 fToolTipProvider
.dispose();
275 if (fMouseDragProvider
!= null) {
276 fMouseDragProvider
.dispose();
280 // ------------------------------------------------------------------------
282 // ------------------------------------------------------------------------
284 * A Method to load a trace into the viewer.
287 * A trace to apply in the viewer
290 public void loadTrace(ITmfTrace trace
) {
291 super.loadTrace(trace
);
297 * Resets the content of the viewer
300 public void reset() {
308 * Method to implement to update the chart content.
310 protected abstract void updateContent();
313 * Returns whether or not this chart viewer is dirty. The viewer is
314 * considered dirty if it has yet to completely update its model.
316 * This method is meant to be used by tests in order to know when it is safe
319 * @return true if the time graph view has yet to completely update its
320 * model, false otherwise
324 public boolean isDirty() {
325 if (getTrace() == null) {
329 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
330 long startTime
= ctx
.getWindowRange().getStartTime().toNanos();
331 long endTime
= ctx
.getWindowRange().getEndTime().toNanos();
333 // If the chart viewer hasn't updated all the way to the end of
334 // the window range then it's dirty. A refresh should happen later.
335 return (getWindowStartTime() != startTime
|| getWindowEndTime() != endTime
);
338 // ------------------------------------------------------------------------
340 // ------------------------------------------------------------------------
343 * Signal handler for handling of the time synch signal.
346 * The time synch signal {@link TmfSelectionRangeUpdatedSignal}
350 public void selectionRangeUpdated(TmfSelectionRangeUpdatedSignal signal
) {
351 super.selectionRangeUpdated(signal
);
352 if (signal
!= null && (signal
.getSource() != this) && (getTrace() != null)) {
353 if (fMouseSelectionProvider
!= null) {
354 fMouseSelectionProvider
.refresh();
360 * Signal handler for handling of the window range signal.
363 * The {@link TmfWindowRangeUpdatedSignal}
367 public void windowRangeUpdated(TmfWindowRangeUpdatedSignal signal
) {
368 super.windowRangeUpdated(signal
);
373 * Signal handler for handling the signal that notifies about an updated
377 * The trace updated signal
378 * {@link TmfTimestampFormatUpdateSignal}
381 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal
) {
382 fSwtChart
.getAxisSet().adjustRange();
386 // ------------------------------------------------------------------------
388 // ------------------------------------------------------------------------
391 * Clears the view content.
393 protected void clearContent() {
394 if (!fSwtChart
.isDisposed()) {
395 ISeriesSet set
= fSwtChart
.getSeriesSet();
396 ISeries
[] series
= set
.getSeries();
397 for (int i
= 0; i
< series
.length
; i
++) {
398 set
.deleteSeries(series
[i
].getId());
400 for (IAxis axis
: fSwtChart
.getAxisSet().getAxes()){
401 axis
.setRange(new Range(0,1));
408 * Returns the current or default display.
410 * @return the current or default display
412 protected static Display
getDisplay() {
413 Display display
= Display
.getCurrent();
414 // may be null if outside the UI thread
415 if (display
== null) {
416 display
= Display
.getDefault();
422 * Get the offset of the point area, relative to the XY chart viewer
423 * control. We consider the point area to be from where the first point
424 * could be drawn to where the last point could be drawn.
426 * @return the offset in pixels
430 public int getPointAreaOffset() {
432 int pixelCoordinate
= 0;
433 IAxis
[] xAxes
= getSwtChart().getAxisSet().getXAxes();
434 if (xAxes
.length
> 0) {
435 IAxis axis
= xAxes
[0];
436 pixelCoordinate
= axis
.getPixelCoordinate(axis
.getRange().lower
);
438 return getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(pixelCoordinate
, 0)).x
;
442 * Get the width of the point area. We consider the point area to be from
443 * where the first point could be drawn to where the last point could be
444 * drawn. The point area differs from the plot area because there might be a
445 * gap between where the plot area start and where the fist point is drawn.
446 * This also matches the width that the use can select.
448 * @return the width in pixels
452 public int getPointAreaWidth() {
453 IAxis
[] xAxes
= getSwtChart().getAxisSet().getXAxes();
454 if (xAxes
.length
> 0) {
455 IAxis axis
= xAxes
[0];
456 int x1
= getPointAreaOffset();
457 int x2
= axis
.getPixelCoordinate(axis
.getRange().upper
);
458 x2
= getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(x2
, 0)).x
;
463 return getSwtChart().getPlotArea().getSize().x
;
467 * Sets whether or not to send time alignment signals. This should be set to
468 * true for viewers that are part of an aligned view.
470 * @param sendTimeAlignSignals
471 * whether or not to send time alignment signals
474 public void setSendTimeAlignSignals(boolean sendTimeAlignSignals
) {
475 fSendTimeAlignSignals
= sendTimeAlignSignals
;
479 * Returns whether or not to send time alignment signals.
481 * @return whether or not to send time alignment signals.
484 public boolean isSendTimeAlignSignals() {
485 return fSendTimeAlignSignals
;