tmf.ui: Add a SWTbot condition for XY charts ready
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / viewers / xycharts / TmfXYChartViewer.java
CommitLineData
d7d40e67 1/**********************************************************************
25033fef 2 * Copyright (c) 2013, 2016 Ericsson, École Polytechnique de Montréal
d7d40e67
BH
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
843c272b 11 * Geneviève Bastien - Moved some methods to TmfTimeViewer
abf7b9b0 12 * Patrick Tasse - Fix setFocus
d7d40e67 13 **********************************************************************/
2bdf0193 14package org.eclipse.tracecompass.tmf.ui.viewers.xycharts;
d7d40e67 15
d7d40e67 16import org.eclipse.swt.SWT;
abf7b9b0
PT
17import org.eclipse.swt.events.MouseAdapter;
18import org.eclipse.swt.events.MouseEvent;
d7d40e67
BH
19import org.eclipse.swt.widgets.Composite;
20import org.eclipse.swt.widgets.Control;
21import org.eclipse.swt.widgets.Display;
97c71024 22import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
54404589 23import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
2bdf0193 24import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
54404589 25import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
2bdf0193 26import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
c27e9fec
GB
27import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
28import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
2bdf0193 29import org.eclipse.tracecompass.tmf.ui.viewers.TmfTimeViewer;
d7d40e67
BH
30import org.swtchart.Chart;
31import org.swtchart.IAxis;
32import org.swtchart.ISeries;
33import org.swtchart.ISeriesSet;
bf06b33c 34import org.swtchart.Range;
d7d40e67 35
c27e9fec
GB
36import com.google.common.annotations.VisibleForTesting;
37
d7d40e67
BH
38/**
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.
42 *
43 * @author Bernd Hufmann
d7d40e67 44 */
843c272b 45public abstract class TmfXYChartViewer extends TmfTimeViewer implements ITmfChartTimeProvider {
d7d40e67
BH
46
47 // ------------------------------------------------------------------------
48 // Attributes
49 // ------------------------------------------------------------------------
d7d40e67
BH
50 /** The SWT Chart reference */
51 private Chart fSwtChart;
0b09e0cf
BH
52 /** The mouse selection provider */
53 private TmfBaseProvider fMouseSelectionProvider;
73920960
BH
54 /** The mouse drag zoom provider */
55 private TmfBaseProvider fMouseDragZoomProvider;
4bcc4ed6
BH
56 /** The mouse wheel zoom provider */
57 private TmfBaseProvider fMouseWheelZoomProvider;
5791dcef
BH
58 /** The tooltip provider */
59 private TmfBaseProvider fToolTipProvider;
eee2beeb
BH
60 /** The middle mouse drag provider */
61 private TmfBaseProvider fMouseDragProvider;
54404589
MAL
62 /**
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.
65 */
66 private boolean fSendTimeAlignSignals = false;
67
d7d40e67
BH
68
69 // ------------------------------------------------------------------------
70 // Constructors
71 // ------------------------------------------------------------------------
72
73 /**
74 * Constructs a TmfXYChartViewer.
75 *
76 * @param parent
77 * The parent composite
78 * @param title
79 * The title of the viewer
80 * @param xLabel
81 * The label of the xAxis
82 * @param yLabel
83 * The label of the yAXIS
84 */
85 public TmfXYChartViewer(Composite parent, String title, String xLabel, String yLabel) {
86 super(parent, title);
abf7b9b0
PT
87 fSwtChart = new Chart(parent, SWT.NONE) {
88 @Override
89 public boolean setFocus() {
90 return fSwtChart.getPlotArea().setFocus();
91 }
92 };
93 fSwtChart.getPlotArea().addMouseListener(new MouseAdapter() {
94 @Override
95 public void mouseDown(MouseEvent e) {
96 fSwtChart.getPlotArea().setFocus();
97 }
98 });
d7d40e67
BH
99
100 IAxis xAxis = fSwtChart.getAxisSet().getXAxis(0);
101 IAxis yAxis = fSwtChart.getAxisSet().getYAxis(0);
102
103 /* Set the title/labels, or hide them if they are not provided */
104 if (title == null) {
105 fSwtChart.getTitle().setVisible(false);
106 } else {
107 fSwtChart.getTitle().setText(title);
108 }
109 if (xLabel == null) {
110 xAxis.getTitle().setVisible(false);
111 } else {
112 xAxis.getTitle().setText(xLabel);
113 }
114 if (yLabel == null) {
115 yAxis.getTitle().setVisible(false);
116 } else {
117 yAxis.getTitle().setText(yLabel);
118 }
0b09e0cf
BH
119
120 fMouseSelectionProvider = new TmfMouseSelectionProvider(this);
73920960 121 fMouseDragZoomProvider = new TmfMouseDragZoomProvider(this);
4bcc4ed6 122 fMouseWheelZoomProvider = new TmfMouseWheelZoomProvider(this);
5791dcef 123 fToolTipProvider = new TmfSimpleTooltipProvider(this);
eee2beeb 124 fMouseDragProvider = new TmfMouseDragProvider(this);
25033fef
PT
125
126 fSwtChart.addDisposeListener((e) -> {
127 internalDispose();
128 });
d7d40e67
BH
129 }
130
131 // ------------------------------------------------------------------------
132 // Getter/Setters
133 // ------------------------------------------------------------------------
d7d40e67 134
d7d40e67
BH
135 /**
136 * Sets the SWT Chart reference
137 *
138 * @param chart
139 * The SWT chart to set.
140 */
141 protected void setSwtChart(Chart chart) {
142 fSwtChart = chart;
143 }
144
145 /**
146 * Gets the SWT Chart reference
147 *
148 * @return the SWT chart to set.
149 */
150 protected Chart getSwtChart() {
151 return fSwtChart;
152 }
153
0b09e0cf
BH
154 /**
155 * Sets a mouse selection provider. An existing provider will be
156 * disposed. Use <code>null</code> to disable the mouse selection provider.
157 *
158 * @param provider
159 * The selection provider to set
160 */
161 public void setSelectionProvider(TmfBaseProvider provider) {
162 if (fMouseSelectionProvider != null) {
163 fMouseSelectionProvider.dispose();
164 }
165 fMouseSelectionProvider = provider;
166 }
167
73920960
BH
168 /**
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.
171 *
172 * @param provider
173 * The mouse drag zoom provider to set
174 */
175 public void setMouseDragZoomProvider(TmfBaseProvider provider) {
176 if (fMouseDragZoomProvider != null) {
177 fMouseDragZoomProvider.dispose();
178 }
179 fMouseDragZoomProvider = provider;
180 }
181
4bcc4ed6
BH
182 /**
183 * Sets a mouse wheel zoom provider. An existing provider will be
184 * disposed. Use <code>null</code> to disable the mouse wheel zoom
185 * provider.
186 *
187 * @param provider
188 * The mouse wheel zoom provider to set
189 */
190 public void setMouseWheelZoomProvider(TmfBaseProvider provider) {
191 if (fMouseWheelZoomProvider != null) {
192 fMouseWheelZoomProvider.dispose();
193 }
194 fMouseWheelZoomProvider = provider;
195 }
196
5791dcef
BH
197 /**
198 * Sets a tooltip provider. An existing provider will be
199 * disposed. Use <code>null</code> to disable the tooltip provider.
200 *
201 * @param provider
202 * The tooltip provider to set
203 */
204 public void setTooltipProvider(TmfBaseProvider provider) {
205 if (fToolTipProvider != null) {
206 fToolTipProvider.dispose();
207 }
208 fToolTipProvider = provider;
209 }
210
eee2beeb
BH
211 /**
212 * Sets a mouse drag provider. An existing provider will be
213 * disposed. Use <code>null</code> to disable the mouse drag provider.
214 *
215 * @param provider
216 * The mouse drag provider to set
217 */
218 public void setMouseDrageProvider(TmfBaseProvider provider) {
219 if (fMouseDragProvider != null) {
220 fMouseDragProvider.dispose();
221 }
222 fMouseDragProvider = provider;
223 }
224
d7d40e67
BH
225 // ------------------------------------------------------------------------
226 // ITmfChartTimeProvider
227 // ------------------------------------------------------------------------
d7d40e67
BH
228
229 @Override
230 public long getTimeOffset() {
4e72adee 231 return getWindowStartTime() - 1;
d7d40e67
BH
232 }
233
234 // ------------------------------------------------------------------------
235 // ITmfViewer interface
236 // ------------------------------------------------------------------------
237 @Override
238 public Control getControl() {
239 return fSwtChart;
240 }
241
242 @Override
243 public void refresh() {
244 fSwtChart.redraw();
245 }
246
247 // ------------------------------------------------------------------------
248 // TmfComponent
249 // ------------------------------------------------------------------------
25033fef 250
d7d40e67
BH
251 @Override
252 public void dispose() {
d7d40e67 253 fSwtChart.dispose();
25033fef
PT
254 }
255
256 private void internalDispose() {
257 super.dispose();
0b09e0cf
BH
258
259 if (fMouseSelectionProvider != null) {
260 fMouseSelectionProvider.dispose();
261 }
73920960
BH
262
263 if (fMouseDragZoomProvider != null) {
264 fMouseDragZoomProvider.dispose();
265 }
4bcc4ed6
BH
266
267 if (fMouseWheelZoomProvider != null) {
268 fMouseWheelZoomProvider.dispose();
269 }
5791dcef
BH
270
271 if (fToolTipProvider != null) {
272 fToolTipProvider.dispose();
273 }
eee2beeb
BH
274
275 if (fMouseDragProvider != null) {
276 fMouseDragProvider.dispose();
277 }
d7d40e67
BH
278 }
279
280 // ------------------------------------------------------------------------
281 // Operations
282 // ------------------------------------------------------------------------
283 /**
284 * A Method to load a trace into the viewer.
285 *
286 * @param trace
287 * A trace to apply in the viewer
288 */
843c272b 289 @Override
d7d40e67 290 public void loadTrace(ITmfTrace trace) {
843c272b 291 super.loadTrace(trace);
d7d40e67
BH
292 clearContent();
293 updateContent();
294 }
295
296 /**
297 * Resets the content of the viewer
298 */
843c272b 299 @Override
d7d40e67 300 public void reset() {
843c272b 301 super.reset();
bf06b33c
MK
302 setStartTime(0);
303 setEndTime(0);
d7d40e67
BH
304 clearContent();
305 }
306
307 /**
308 * Method to implement to update the chart content.
309 */
310 protected abstract void updateContent();
311
c27e9fec
GB
312 /**
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.
315 *
316 * This method is meant to be used by tests in order to know when it is safe
317 * to proceed.
318 *
319 * @return true if the time graph view has yet to completely update its
320 * model, false otherwise
321 * @since 2.2
322 */
323 @VisibleForTesting
324 public boolean isDirty() {
325 if (getTrace() == null) {
326 return false;
327 }
328
329 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
330 long startTime = ctx.getWindowRange().getStartTime().toNanos();
331 long endTime = ctx.getWindowRange().getEndTime().toNanos();
332
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);
336 }
337
d7d40e67
BH
338 // ------------------------------------------------------------------------
339 // Signal Handler
340 // ------------------------------------------------------------------------
341
d7d40e67
BH
342 /**
343 * Signal handler for handling of the time synch signal.
344 *
345 * @param signal
97c71024 346 * The time synch signal {@link TmfSelectionRangeUpdatedSignal}
d7d40e67 347 */
843c272b 348 @Override
d7d40e67 349 @TmfSignalHandler
97c71024 350 public void selectionRangeUpdated(TmfSelectionRangeUpdatedSignal signal) {
843c272b 351 super.selectionRangeUpdated(signal);
7d65c2b5 352 if (signal != null && (signal.getSource() != this) && (getTrace() != null)) {
0b09e0cf
BH
353 if (fMouseSelectionProvider != null) {
354 fMouseSelectionProvider.refresh();
355 }
d7d40e67
BH
356 }
357 }
358
359 /**
97c71024 360 * Signal handler for handling of the window range signal.
d7d40e67
BH
361 *
362 * @param signal
97c71024 363 * The {@link TmfWindowRangeUpdatedSignal}
d7d40e67 364 */
843c272b 365 @Override
d7d40e67 366 @TmfSignalHandler
97c71024
AM
367 public void windowRangeUpdated(TmfWindowRangeUpdatedSignal signal) {
368 super.windowRangeUpdated(signal);
d7d40e67
BH
369 updateContent();
370 }
371
d7d40e67
BH
372 /**
373 * Signal handler for handling the signal that notifies about an updated
374 * timestamp format.
375 *
376 * @param signal
377 * The trace updated signal
378 * {@link TmfTimestampFormatUpdateSignal}
379 */
380 @TmfSignalHandler
381 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
382 fSwtChart.getAxisSet().adjustRange();
383 fSwtChart.redraw();
384 }
385
386 // ------------------------------------------------------------------------
387 // Helper Methods
388 // ------------------------------------------------------------------------
389
390 /**
391 * Clears the view content.
392 */
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());
399 }
bf06b33c
MK
400 for (IAxis axis: fSwtChart.getAxisSet().getAxes()){
401 axis.setRange(new Range(0,1));
402 }
d7d40e67
BH
403 fSwtChart.redraw();
404 }
405 }
406
407 /**
408 * Returns the current or default display.
409 *
410 * @return the current or default display
411 */
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();
417 }
418 return display;
419 }
420
54404589
MAL
421 /**
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.
425 *
426 * @return the offset in pixels
427 *
428 * @since 1.0
429 */
430 public int getPointAreaOffset() {
7c56e8ed 431
54404589
MAL
432 int pixelCoordinate = 0;
433 IAxis[] xAxes = getSwtChart().getAxisSet().getXAxes();
d9789e33 434 if (xAxes.length > 0) {
54404589 435 IAxis axis = xAxes[0];
d9789e33 436 pixelCoordinate = axis.getPixelCoordinate(axis.getRange().lower);
54404589
MAL
437 }
438 return getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(pixelCoordinate, 0)).x;
439 }
440
441 /**
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.
447 *
448 * @return the width in pixels
449 *
450 * @since 1.0
451 */
452 public int getPointAreaWidth() {
453 IAxis[] xAxes = getSwtChart().getAxisSet().getXAxes();
d9789e33 454 if (xAxes.length > 0) {
54404589
MAL
455 IAxis axis = xAxes[0];
456 int x1 = getPointAreaOffset();
d9789e33 457 int x2 = axis.getPixelCoordinate(axis.getRange().upper);
54404589
MAL
458 x2 = getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(x2, 0)).x;
459 int width = x2 - x1;
460 return width;
461 }
462
463 return getSwtChart().getPlotArea().getSize().x;
464 }
465
54404589
MAL
466 /**
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.
469 *
470 * @param sendTimeAlignSignals
471 * whether or not to send time alignment signals
472 * @since 1.0
473 */
474 public void setSendTimeAlignSignals(boolean sendTimeAlignSignals) {
475 fSendTimeAlignSignals = sendTimeAlignSignals;
476 }
477
478 /**
479 * Returns whether or not to send time alignment signals.
480 *
481 * @return whether or not to send time alignment signals.
482 * @since 1.0
483 */
484 public boolean isSendTimeAlignSignals() {
485 return fSendTimeAlignSignals;
486 }
d7d40e67 487}
This page took 0.123812 seconds and 5 git commands to generate.