/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package com.andork.plot; import java.awt.Component; import java.awt.Cursor; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import com.andork.plot.PlotAxis.Orientation; public class PlotAxisController { private class MouseHandler extends MouseAdapter implements MouseWheelListener { MouseEvent pressEvent = null; MouseEvent lastEvent = null; @Override public void mouseDragged(MouseEvent e) { if (lastEvent == null) { return; } boolean horiz = view.getOrientation() == Orientation.HORIZONTAL; LinearAxisConversion axisConversion = view.getAxisConversion(); int dx = e.getX() - lastEvent.getX(); int dy = e.getY() - lastEvent.getY(); double oldMouseDomain = axisConversion.invert(horiz ? lastEvent.getX() : lastEvent.getY()); double oldStart = axisConversion.invert(0); double oldEnd = axisConversion.invert(view.getViewSpan()); double newMouseDomain = axisConversion.invert(horiz ? e.getX() : e.getY()); double newStart = oldStart; double newEnd = oldEnd; if (pressEvent.getButton() == MouseEvent.BUTTON1 || !enableZoom) { double zoom = enableZoom ? Math.pow(dragZoomSpeed, horiz ? dy : dx) : 1.0; newStart = oldMouseDomain + (oldStart - newMouseDomain) * zoom; newEnd = oldMouseDomain + (oldEnd - newMouseDomain) * zoom; } else if (pressEvent.getButton() == MouseEvent.BUTTON3) { if (horiz ? pressEvent.getX() > view.getWidth() / 2 : pressEvent.getY() > view.getHeight() / 2) { if (newMouseDomain != oldStart) { newEnd = newStart + (newEnd - newStart) * (oldMouseDomain - oldStart) / (newMouseDomain - oldStart); } } else { if (newMouseDomain != oldEnd) { newStart = newEnd + (newStart - newEnd) * (oldMouseDomain - oldEnd) / (newMouseDomain - oldEnd); } } } if (newStart != newEnd) { setAxisRange(newStart, newEnd); } lastEvent = e; } @Override public void mousePressed(MouseEvent e) { if (pressEvent != null) { return; } if (e.getButton() == MouseEvent.BUTTON1 || e.getButton() == MouseEvent.BUTTON3) { pressEvent = lastEvent = e; } } @Override public void mouseReleased(MouseEvent e) { if (pressEvent != null && e.getButton() == pressEvent.getButton()) { lastEvent = null; pressEvent = null; } } @Override public void mouseWheelMoved(MouseWheelEvent e) { doZoom(e); } } private final PlotAxis view; private final MouseHandler mouseHandler = new MouseHandler(); private final MouseLooper mouseLooper = new MouseLooper(); private double dragZoomSpeed = 1.01; private double wheelZoomSpeed = 1.01; private boolean enableZoom = true; public PlotAxisController(PlotAxis view) { this.view = view; view.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); view.addMouseListener(mouseLooper); view.addMouseMotionListener(mouseLooper); view.addMouseWheelListener(mouseLooper); mouseLooper.addMouseAdapter(mouseHandler); } public void doZoom(MouseWheelEvent e) { LinearAxisConversion axisConversion = view.getAxisConversion(); double oldStart = axisConversion.invert(0); double oldEnd = axisConversion.invert(view.getViewSpan()); double mousePosition = axisConversion .invert(view.getOrientation() == Orientation.HORIZONTAL ? e.getX() : e.getY()); double zoom = enableZoom ? Math.pow(wheelZoomSpeed, e.getUnitsToScroll()) : 1.0; double newStart = mousePosition + (oldStart - mousePosition) * zoom; double newEnd = mousePosition + (oldEnd - mousePosition) * zoom; setAxisRange(newStart, newEnd); } public double getDragZoomSpeed() { return dragZoomSpeed; } public MouseAdapter getMouseHandler() { return mouseHandler; } public PlotAxis getView() { return view; } public double getWheelZoomSpeed() { return wheelZoomSpeed; } public boolean isEnableZoom() { return enableZoom; } public void removeMouseWheelListener() { view.removeMouseWheelListener(mouseLooper); } protected void setAxisRange(double start, double end) { view.getAxisConversion().set(start, 0, end, view.getViewSpan()); // fire an event view.setAxisConversion(view.getAxisConversion()); view.repaint(); for (Component plot : view.getPlots()) { plot.repaint(); } } public void setDragZoomSpeed(double dragZoomSpeed) { this.dragZoomSpeed = dragZoomSpeed; } public void setEnableZoom(boolean enableZoom) { this.enableZoom = enableZoom; } public void setWheelZoomSpeed(double wheelZoomSpeed) { this.wheelZoomSpeed = wheelZoomSpeed; } }