MoveLineChartByMouseListener.java

  1. package de.slothsoft.charts.swt;

  2. import java.util.Objects;

  3. import org.eclipse.swt.SWT;
  4. import org.eclipse.swt.events.MouseEvent;
  5. import org.eclipse.swt.events.MouseListener;
  6. import org.eclipse.swt.events.MouseMoveListener;
  7. import org.eclipse.swt.events.MouseWheelListener;
  8. import org.eclipse.swt.graphics.Cursor;
  9. import org.eclipse.swt.graphics.Point;
  10. import org.eclipse.swt.widgets.Control;
  11. import org.eclipse.swt.widgets.Display;

  12. import de.slothsoft.charts.Area;
  13. import de.slothsoft.charts.linechart.LineChart;

  14. /**
  15.  * A {@link MouseListener}, {@link MouseMoveListener} and {@link MouseWheelListener} to
  16.  * move the diagram with the mouse. It's advised to add this listener by using the
  17.  * {@link MoveLineChartByMouseListener#hookToControl(Control, LineChart)} method.
  18.  *
  19.  * @author Stef Schulz
  20.  * @since 0.1.0
  21.  */

  22. public class MoveLineChartByMouseListener implements MouseListener, MouseMoveListener, MouseWheelListener {

  23.     /**
  24.      * Creates a new {@link MoveLineChartByMouseListener}, hooks it to a control (not
  25.      * necessary a {@link ChartControl}, but that's probably a good idea) and returns the
  26.      * brand new instance.
  27.      *
  28.      * @param control the control, probably a {@link ChartControl}
  29.      * @param chart the displayed chart
  30.      * @return the brand new listener
  31.      */

  32.     public static MoveLineChartByMouseListener hookToControl(Control control, LineChart chart) {
  33.         final MoveLineChartByMouseListener result = new MoveLineChartByMouseListener(chart);
  34.         control.addMouseListener(result);
  35.         control.addMouseMoveListener(result);
  36.         control.addMouseWheelListener(result);
  37.         return result;
  38.     }

  39.     private static Cursor handCursor;

  40.     static Cursor getHandCursor(Display display) {
  41.         if (handCursor == null) {
  42.             handCursor = new Cursor(display, SWT.CURSOR_HAND);
  43.         }
  44.         return handCursor;
  45.     }

  46.     private final LineChart chart;
  47.     boolean mouseDown;
  48.     private int mouseDownX;
  49.     private int mouseDownY;

  50.     private int movementMouseButton = 1;

  51.     /**
  52.      * Constructor.
  53.      *
  54.      * @param chart the chart this listener uses
  55.      */

  56.     public MoveLineChartByMouseListener(LineChart chart) {
  57.         this.chart = Objects.requireNonNull(chart);
  58.     }

  59.     @Override
  60.     public void mouseDoubleClick(MouseEvent e) {
  61.         // nothing to do yet
  62.     }

  63.     @Override
  64.     public void mouseDown(MouseEvent e) {
  65.         if (isInGraphArea(e) && e.button == this.movementMouseButton) {
  66.             this.mouseDown = true;
  67.             this.mouseDownX = e.x;
  68.             this.mouseDownY = e.y;
  69.         }
  70.     }

  71.     @Override
  72.     public void mouseUp(MouseEvent e) {
  73.         if (e.button == this.movementMouseButton) {
  74.             this.mouseDown = false;
  75.         }
  76.     }

  77.     @Override
  78.     public void mouseMove(MouseEvent e) {
  79.         final Control control = ((Control) e.widget);
  80.         if (isInGraphArea(e)) {
  81.             control.setCursor(getHandCursor(control.getDisplay()));
  82.         } else {
  83.             control.setCursor(null);
  84.         }

  85.         if (this.mouseDown) {
  86.             final int diffX = this.mouseDownX - e.x;
  87.             final int diffY = e.y - this.mouseDownY; // for line charts y is flipped

  88.             this.chart.moveDisplayedAreaByChartCoordinates(diffX, diffY);

  89.             this.mouseDownX = e.x;
  90.             this.mouseDownY = e.y;
  91.         }
  92.     }

  93.     private boolean isInGraphArea(MouseEvent e) {
  94.         final Control control = ((Control) e.widget);
  95.         final Point controlSize = control.getSize();
  96.         final Area actualArea = this.chart.calculateGraphArea(controlSize.x, controlSize.y);
  97.         return actualArea.containsPoint(e.x, e.y);
  98.     }

  99.     @Override
  100.     public void mouseScrolled(MouseEvent e) {
  101.         if (isInGraphArea(e)) {
  102.             if (e.count < 0) {
  103.                 this.chart.zoomDisplayedAreaOutByChartCoordinates(e.x, e.y);
  104.             } else {
  105.                 this.chart.zoomDisplayedAreaInByChartCoordinates(e.x, e.y);
  106.             }
  107.         }
  108.     }

  109.     /**
  110.      * Returns the button that needs to be pressed to move the chart.
  111.      * <ul>
  112.      * <li>1 for the first button (usually 'left')</li>
  113.      * <li>2 for the second button (usually 'middle')</li>
  114.      * <li>3 for the third button (usually 'right')</li>
  115.      * <li>etc.</li>
  116.      * </ul>
  117.      *
  118.      * @return the mouse button
  119.      */

  120.     public int getMovementMouseButton() {
  121.         return this.movementMouseButton;
  122.     }

  123.     /**
  124.      * Sets the button that needs to be pressed to move the chart.
  125.      * <ul>
  126.      * <li>1 for the first button (usually 'left')</li>
  127.      * <li>2 for the second button (usually 'middle')</li>
  128.      * <li>3 for the third button (usually 'right')</li>
  129.      * <li>etc.</li>
  130.      * </ul>
  131.      *
  132.      * @param newMovementMouseButton the mouse button
  133.      * @return this instance
  134.      */

  135.     public MoveLineChartByMouseListener movementMouseButton(int newMovementMouseButton) {
  136.         setMovementMouseButton(newMovementMouseButton);
  137.         return this;
  138.     }

  139.     /**
  140.      * Sets the button that needs to be pressed to move the chart.
  141.      * <ul>
  142.      * <li>1 for the first button (usually 'left')</li>
  143.      * <li>2 for the second button (usually 'middle')</li>
  144.      * <li>3 for the third button (usually 'right')</li>
  145.      * <li>etc.</li>
  146.      * </ul>
  147.      *
  148.      * @param movementMouseButton the mouse button
  149.      */

  150.     public void setMovementMouseButton(int movementMouseButton) {
  151.         this.movementMouseButton = movementMouseButton;
  152.     }

  153. }