From 0b09e0cf60a157419b1c28bcdd731273e1ad9b0f Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Thu, 19 Dec 2013 13:42:15 -0500 Subject: [PATCH] tmf: add mouse selection provider for swt charts Change-Id: Ibe73dfdea14354c149ae411e09f1f39a4a7a6220 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/20081 Tested-by: Hudson CI Reviewed-by: Genevieve Bastien IP-Clean: Genevieve Bastien Tested-by: Genevieve Bastien Reviewed-by: Bernd Hufmann --- .../xycharts/ITmfChartTimeProvider.java | 10 ++ .../ui/viewers/xycharts/TmfBaseProvider.java | 155 +++++++++++++++++ .../xycharts/TmfMouseSelectionProvider.java | 162 ++++++++++++++++++ .../ui/viewers/xycharts/TmfXYChartViewer.java | 40 +++++ 4 files changed, 367 insertions(+) create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfBaseProvider.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfMouseSelectionProvider.java diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java index b7ebb6266b..f9f4aaf724 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java @@ -100,4 +100,14 @@ public interface ITmfChartTimeProvider extends ITmfViewer { */ long getTimeOffset(); + /** + * Method to notify about a change of the current selected time. + * + * @param currentBeginTime + * The current selection begin time + * @param currentEndTime + * The current selection end time + */ + void updateSelectionRange(long currentBeginTime, long currentEndTime); + } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfBaseProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfBaseProvider.java new file mode 100644 index 0000000000..86d8ad5325 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfBaseProvider.java @@ -0,0 +1,155 @@ +/********************************************************************** + * Copyright (c) 2013 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bernd Hufmann - Initial API and implementation + **********************************************************************/ +package org.eclipse.linuxtools.tmf.ui.viewers.xycharts; + +import org.swtchart.Chart; +import org.swtchart.IAxis; + +/** + * Base class for any provider such as tool tip, zoom and selection providers. + * + * @author Bernd Hufmann + * @since 3.0 + */ +abstract public class TmfBaseProvider { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + /** Reference to the chart viewer */ + private final ITmfChartTimeProvider fChartViewer; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Standard constructor. + * + * @param tmfChartViewer + * The parent histogram object + */ + public TmfBaseProvider(ITmfChartTimeProvider tmfChartViewer) { + fChartViewer = tmfChartViewer; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + /** + * Returns the chart viewer reference. + * @return the chart viewer reference + */ + public ITmfChartTimeProvider getChartViewer() { + return fChartViewer; + } + + /** + * Returns the SWT chart reference + * + * @return SWT chart reference. + */ + protected Chart getChart() { + return (Chart) fChartViewer.getControl(); + } + + /** + * Limits x data coordinate to window start and window end range + * + * @param x + * x to limit + * @return x if x >= begin && x <= end + * begin if x < begin + * end if x > end + */ + protected long limitXDataCoordinate(double x) { + ITmfChartTimeProvider viewer = getChartViewer(); + long windowStartTime = viewer.getWindowStartTime() - viewer.getTimeOffset(); + long windowEndTime = viewer.getWindowEndTime() - viewer.getTimeOffset(); + + if (x < windowStartTime) { + return windowStartTime; + } + + if (x > windowEndTime) { + return windowEndTime; + } + + return (long) x; + } + + /** + * Limits x pixel coordinate to window start and window end range + * + * @param axisIndex + * index of x-axis + * @param x + * x to limit + * @return x if x >= begin && x <= end + * begin if x < begin + * end if x > end + */ + protected int limitXPixelCoordinate(int axisIndex, int x) { + ITmfChartTimeProvider viewer = getChartViewer(); + long windowStartTime = viewer.getWindowStartTime() - viewer.getTimeOffset(); + long windowEndTime = viewer.getWindowEndTime() - viewer.getTimeOffset(); + + IAxis xAxis = getChart().getAxisSet().getXAxis(0); + int startX = xAxis.getPixelCoordinate(windowStartTime); + if (x < startX) { + return startX; + } + + int endX = xAxis.getPixelCoordinate(windowEndTime); + if (x > endX) { + return endX; + } + + return x; + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + /** + * Method deregisters provider from chart viewer. Subclasses may override this method + * to dispose any resources. + */ + public void dispose() { + deregister(); + } + + /** + * Method to refresh the viewer. It will redraw the viewer. + */ + public void refresh() { + if (!TmfXYChartViewer.getDisplay().isDisposed()) { + TmfXYChartViewer.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + getChart().redraw(); + } + }); + } + } + + /** + * Method to register the provider to chart viewer. + */ + abstract void register(); + + /** + * Method to deregister the provider from chart viewer. + */ + abstract void deregister(); + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfMouseSelectionProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfMouseSelectionProvider.java new file mode 100644 index 0000000000..ace4dac854 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfMouseSelectionProvider.java @@ -0,0 +1,162 @@ +/********************************************************************** + * Copyright (c) 2013 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bernd Hufmann - Initial API and implementation + **********************************************************************/ +package org.eclipse.linuxtools.tmf.ui.viewers.xycharts; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.swtchart.IAxis; +import org.swtchart.ICustomPaintListener; +import org.swtchart.IPlotArea; + +/** + * Class for providing selection of ranges with the left mouse button. + * It also notifies the viewer about a change of selection. + * + * @author Bernd Hufmann + * @since 3.0 + */ +public class TmfMouseSelectionProvider extends TmfBaseProvider implements MouseListener, MouseMoveListener, ICustomPaintListener { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + /** Cached start time */ + private long fBeginTime; + /** Cached end time */ + private long fEndTime; + /** Flag indicating that an update is ongoing */ + private boolean fIsInternalUpdate; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + /** + * Default constructor + * + * @param tmfChartViewer + * The chart viewer reference. + */ + public TmfMouseSelectionProvider(ITmfChartTimeProvider tmfChartViewer) { + super(tmfChartViewer); + register(); + } + + // ------------------------------------------------------------------------ + // TmfBaseProvider + // ------------------------------------------------------------------------ + @Override + public void register() { + getChart().getPlotArea().addMouseListener(this); + getChart().getPlotArea().addMouseMoveListener(this); + ((IPlotArea) getChart().getPlotArea()).addCustomPaintListener(this); + } + + @Override + public void deregister() { + if ((getChartViewer().getControl() != null) && !getChartViewer().getControl().isDisposed()) { + getChart().getPlotArea().removeMouseListener(this); + getChart().getPlotArea().removeMouseMoveListener(this); + ((IPlotArea) getChart().getPlotArea()).removeCustomPaintListener(this); + } + } + + // ------------------------------------------------------------------------ + // MouseListener + // ------------------------------------------------------------------------ + @Override + public void mouseDoubleClick(MouseEvent e) { + } + + @Override + public void mouseDown(MouseEvent e) { + if ((getChartViewer().getWindowDuration() != 0) && (e.button == 1)) { + IAxis xAxis = getChart().getAxisSet().getXAxis(0); + fBeginTime = limitXDataCoordinate(xAxis.getDataCoordinate(e.x)); + fEndTime = fBeginTime; + fIsInternalUpdate = true; + } + } + + @Override + public void mouseUp(MouseEvent e) { + if (fIsInternalUpdate) { + if (fBeginTime > fEndTime) { + // Swap time + long tmp = fBeginTime; + fBeginTime = fEndTime; + fEndTime = tmp; + } + ITmfChartTimeProvider viewer = getChartViewer(); + viewer.updateSelectionRange(fBeginTime + viewer.getTimeOffset(), fEndTime + viewer.getTimeOffset()); + fIsInternalUpdate = false; + getChart().redraw(); + } + } + + // ------------------------------------------------------------------------ + // MouseMoveListener + // ------------------------------------------------------------------------ + @Override + public void mouseMove(MouseEvent e) { + if (fIsInternalUpdate) { + IAxis xAxis = getChart().getAxisSet().getXAxis(0); + fEndTime = limitXDataCoordinate(xAxis.getDataCoordinate(e.x)); + getChart().redraw(); + } + } + + // ------------------------------------------------------------------------ + // ICustomPaintListener + // ------------------------------------------------------------------------ + @Override + public void paintControl(PaintEvent e) { + ITmfChartTimeProvider viewer = getChartViewer(); + + if (!fIsInternalUpdate) { + fBeginTime = viewer.getSelectionBeginTime() - viewer.getTimeOffset(); + fEndTime = viewer.getSelectionEndTime() - viewer.getTimeOffset(); + } + long windowStartTime = viewer.getWindowStartTime() - viewer.getTimeOffset(); + long windowEndTime = viewer.getWindowEndTime() - viewer.getTimeOffset(); + + IAxis xAxis = getChart().getAxisSet().getXAxis(0); + e.gc.setBackground(TmfXYChartViewer.getDisplay().getSystemColor(SWT.COLOR_BLUE)); + if ((fBeginTime >= windowStartTime) && (fBeginTime <= windowEndTime)) { + int beginX = xAxis.getPixelCoordinate(fBeginTime); + e.gc.drawLine(beginX, 0, beginX, e.height); + } + + if ((fEndTime >= windowStartTime) && (fEndTime <= windowEndTime) && (fBeginTime != fEndTime)) { + int endX = xAxis.getPixelCoordinate(fEndTime); + e.gc.drawLine(endX, 0, endX, e.height); + } + e.gc.setAlpha(150); + if (Math.abs(fEndTime - fBeginTime) > 1) { + e.gc.setBackground(TmfXYChartViewer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + int beginX = xAxis.getPixelCoordinate(fBeginTime); + int endX = xAxis.getPixelCoordinate(fEndTime); + if (fEndTime > fBeginTime) { + e.gc.fillRectangle(beginX + 1, 0, endX - beginX - 1, e.height); + } else { + e.gc.fillRectangle(endX + 1, 0, beginX - endX - 1, e.height); + } + } + } + + @Override + public boolean drawBehindSeries() { + return false; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java index c97f75ff24..141a044309 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java @@ -22,6 +22,7 @@ import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal; import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal; import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer; @@ -70,6 +71,8 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim private ITmfTrace fTrace; /** The SWT Chart reference */ private Chart fSwtChart; + /** The mouse selection provider */ + private TmfBaseProvider fMouseSelectionProvider; // ------------------------------------------------------------------------ // Constructors @@ -110,6 +113,8 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim } else { yAxis.getTitle().setText(yLabel); } + + fMouseSelectionProvider = new TmfMouseSelectionProvider(this); } // ------------------------------------------------------------------------ @@ -234,6 +239,20 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim return fSwtChart; } + /** + * Sets a mouse selection provider. An existing provider will be + * disposed. Use null to disable the mouse selection provider. + * + * @param provider + * The selection provider to set + */ + public void setSelectionProvider(TmfBaseProvider provider) { + if (fMouseSelectionProvider != null) { + fMouseSelectionProvider.dispose(); + } + fMouseSelectionProvider = provider; + } + // ------------------------------------------------------------------------ // ITmfChartTimeProvider // ------------------------------------------------------------------------ @@ -277,6 +296,20 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim return fTimeOffset; } + @Override + public void updateSelectionRange(final long currentBeginTime, final long currentEndTime) { + if (fTrace != null) { + setSelectionBeginTime(currentBeginTime); + setSelectionEndTime(currentEndTime); + + final ITmfTimestamp startTimestamp = new TmfTimestamp(fSelectionBeginTime, ITmfTimestamp.NANOSECOND_SCALE); + final ITmfTimestamp endTimestamp = new TmfTimestamp(fSelectionEndTime, ITmfTimestamp.NANOSECOND_SCALE); + + TmfTimeSynchSignal signal = new TmfTimeSynchSignal(TmfXYChartViewer.this, startTimestamp, endTimestamp); + broadcast(signal); + } + } + // ------------------------------------------------------------------------ // ITmfViewer interface // ------------------------------------------------------------------------ @@ -297,6 +330,10 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim public void dispose() { super.dispose(); fSwtChart.dispose(); + + if (fMouseSelectionProvider != null) { + fMouseSelectionProvider.dispose(); + } } // ------------------------------------------------------------------------ @@ -409,6 +446,9 @@ public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTim ITmfTimestamp selectedEndTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE); setSelectionBeginTime(selectedTime.getValue()); setSelectionEndTime(selectedEndTime.getValue()); + if (fMouseSelectionProvider != null) { + fMouseSelectionProvider.refresh(); + } } } -- 2.34.1