MoveLineChartByMouseListener.java
package de.slothsoft.charts.swt;
import java.util.Objects;
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.MouseWheelListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import de.slothsoft.charts.Area;
import de.slothsoft.charts.linechart.LineChart;
/**
* A {@link MouseListener}, {@link MouseMoveListener} and {@link MouseWheelListener} to
* move the diagram with the mouse. It's advised to add this listener by using the
* {@link MoveLineChartByMouseListener#hookToControl(Control, LineChart)} method.
*
* @author Stef Schulz
* @since 0.1.0
*/
public class MoveLineChartByMouseListener implements MouseListener, MouseMoveListener, MouseWheelListener {
/**
* Creates a new {@link MoveLineChartByMouseListener}, hooks it to a control (not
* necessary a {@link ChartControl}, but that's probably a good idea) and returns the
* brand new instance.
*
* @param control the control, probably a {@link ChartControl}
* @param chart the displayed chart
* @return the brand new listener
*/
public static MoveLineChartByMouseListener hookToControl(Control control, LineChart chart) {
final MoveLineChartByMouseListener result = new MoveLineChartByMouseListener(chart);
control.addMouseListener(result);
control.addMouseMoveListener(result);
control.addMouseWheelListener(result);
return result;
}
private static Cursor handCursor;
static Cursor getHandCursor(Display display) {
if (handCursor == null) {
handCursor = new Cursor(display, SWT.CURSOR_HAND);
}
return handCursor;
}
private final LineChart chart;
boolean mouseDown;
private int mouseDownX;
private int mouseDownY;
private int movementMouseButton = 1;
/**
* Constructor.
*
* @param chart the chart this listener uses
*/
public MoveLineChartByMouseListener(LineChart chart) {
this.chart = Objects.requireNonNull(chart);
}
@Override
public void mouseDoubleClick(MouseEvent e) {
// nothing to do yet
}
@Override
public void mouseDown(MouseEvent e) {
if (isInGraphArea(e) && e.button == this.movementMouseButton) {
this.mouseDown = true;
this.mouseDownX = e.x;
this.mouseDownY = e.y;
}
}
@Override
public void mouseUp(MouseEvent e) {
if (e.button == this.movementMouseButton) {
this.mouseDown = false;
}
}
@Override
public void mouseMove(MouseEvent e) {
final Control control = ((Control) e.widget);
if (isInGraphArea(e)) {
control.setCursor(getHandCursor(control.getDisplay()));
} else {
control.setCursor(null);
}
if (this.mouseDown) {
final int diffX = this.mouseDownX - e.x;
final int diffY = e.y - this.mouseDownY; // for line charts y is flipped
this.chart.moveDisplayedAreaByChartCoordinates(diffX, diffY);
this.mouseDownX = e.x;
this.mouseDownY = e.y;
}
}
private boolean isInGraphArea(MouseEvent e) {
final Control control = ((Control) e.widget);
final Point controlSize = control.getSize();
final Area actualArea = this.chart.calculateGraphArea(controlSize.x, controlSize.y);
return actualArea.containsPoint(e.x, e.y);
}
@Override
public void mouseScrolled(MouseEvent e) {
if (isInGraphArea(e)) {
if (e.count < 0) {
this.chart.zoomDisplayedAreaOutByChartCoordinates(e.x, e.y);
} else {
this.chart.zoomDisplayedAreaInByChartCoordinates(e.x, e.y);
}
}
}
/**
* Returns the button that needs to be pressed to move the chart.
* <ul>
* <li>1 for the first button (usually 'left')</li>
* <li>2 for the second button (usually 'middle')</li>
* <li>3 for the third button (usually 'right')</li>
* <li>etc.</li>
* </ul>
*
* @return the mouse button
*/
public int getMovementMouseButton() {
return this.movementMouseButton;
}
/**
* Sets the button that needs to be pressed to move the chart.
* <ul>
* <li>1 for the first button (usually 'left')</li>
* <li>2 for the second button (usually 'middle')</li>
* <li>3 for the third button (usually 'right')</li>
* <li>etc.</li>
* </ul>
*
* @param newMovementMouseButton the mouse button
* @return this instance
*/
public MoveLineChartByMouseListener movementMouseButton(int newMovementMouseButton) {
setMovementMouseButton(newMovementMouseButton);
return this;
}
/**
* Sets the button that needs to be pressed to move the chart.
* <ul>
* <li>1 for the first button (usually 'left')</li>
* <li>2 for the second button (usually 'middle')</li>
* <li>3 for the third button (usually 'right')</li>
* <li>etc.</li>
* </ul>
*
* @param movementMouseButton the mouse button
*/
public void setMovementMouseButton(int movementMouseButton) {
this.movementMouseButton = movementMouseButton;
}
}