/* ZoomBookTool.java created 2008-03-06 * */ package org.signalml.app.view.book.tools; import java.awt.Cursor; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import javax.swing.JLayeredPane; import javax.swing.SwingUtilities; import org.signalml.app.util.IconUtils; import org.signalml.app.view.book.BookPlot; import org.signalml.app.view.book.BookView; import org.signalml.app.view.book.ZoomBookAreaPlot; /** ZoomBookTool * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class ZoomBookTool extends BookTool { public static final double MIN_POSITION_RANGE = 0.01; public static final double MIN_FREQUENCY_RANGE = 0.01; private Point dragStart = null; private BookPlot plot; private ZoomBookAreaPlot zoomAreaPlot; private boolean plotVisible = false; private boolean wasDragged = false; private boolean zoomOut = false; private boolean preserveRatio = true; public ZoomBookTool(BookView bookView) { super(bookView); zoomAreaPlot = new ZoomBookAreaPlot(); } @Override public Cursor getDefaultCursor() { return IconUtils.getCrosshairCursor(); } private void startZooming(MouseEvent e) { Object source = e.getSource(); if (!(source instanceof BookPlot)) { plot = null; return; } plot = (BookPlot) source; dragStart = e.getPoint(); zoomAreaPlot.setFrame(null); engaged = true; e.consume(); } private void finishZooming(MouseEvent e) { hidePlot(); Point point = e.getPoint(); if (wasDragged && !point.equals(dragStart)) { dragZoom(point); } else { pointZoom(point); } zoomOut = false; dragStart = null; engaged = false; plot = null; e.consume(); } @Override public void mousePressed(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { if (e.isControlDown()) { zoomOut = true; } // if (e.isShiftDown()) { // wasDragged = true; // } startZooming(e); } } @Override public void mouseReleased(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { finishZooming(e); wasDragged = false; } } @Override public void mouseWheelMoved(MouseWheelEvent e) { super.mouseWheelMoved(e); zoomOut = e.getWheelRotation() > 0 ? true : false; wasDragged = false; startZooming(e); finishZooming(e); } @Override public void mouseDragged(MouseEvent e) { if (plot != null) { if (SwingUtilities.isLeftMouseButton(e)) { Point point = e.getPoint(); measureTo(point); wasDragged = true; } } } private void showPlot() { if (plot != null) { if (!plotVisible) { Rectangle mapRectangle = plot.getMapRectangle(); if (mapRectangle == null) { return; } JLayeredPane layeredPane = plot.getRootPane().getLayeredPane(); Point location = SwingUtilities.convertPoint(plot, mapRectangle.getLocation(), layeredPane); zoomAreaPlot.setBounds(location.x, location.y, mapRectangle.width, mapRectangle.height); layeredPane.add(zoomAreaPlot, new Integer(JLayeredPane.DRAG_LAYER)); plotVisible = true; } } } private void hidePlot() { if (plot != null) { if (plotVisible) { JLayeredPane layeredPane = plot.getRootPane().getLayeredPane(); layeredPane.remove(zoomAreaPlot); plotVisible = false; plot.repaint(); } } } private void measureTo(Point point) { if (plot != null) { Rectangle mapRectangle = plot.getMapRectangle(); if (mapRectangle == null) { return; } // TODO consider setting bounds rather than internal frame - may be faster zoomAreaPlot.setFrame(getFrame(mapRectangle, point)); showPlot(); } } private Rectangle getFrame(Rectangle mapRectangle, Point point) { Rectangle frame = new Rectangle(); frame.x = Math.min(dragStart.x, point.x); frame.y = Math.min(dragStart.y, point.y); // int width = point.x - dragStart.x; // int height = point.y - dragStart.y; // // if (width / mapRectangle.width < height / mapRectangle.height) { // frame.width = width; // frame.height = mapRectangle.height * (width / mapRectangle.width); // } else { // frame.width = mapRectangle.width * (width / mapRectangle.height); // frame.height = height; // } frame.width = Math.abs(point.x - dragStart.x); frame.height = Math.abs(point.y - dragStart.y); frame = mapRectangle.intersection(frame); frame.translate(-mapRectangle.x, -mapRectangle.y); return frame; } private void pointZoom(Point point) { Rectangle mapRectangle = plot.getMapRectangle(); if (mapRectangle == null) { return; } if (!mapRectangle.contains(point)) { return; } Point mapPoint = new Point(point); mapPoint.translate(-mapRectangle.x, -mapRectangle.y); double centerPosition = plot.toPosition(mapPoint.x); double centerFrequency = plot.toFrequency(mapPoint.y); double positionRange = plot.getMaxPosition() - plot.getMinPosition(); double frequencyRange = plot.getMaxFrequency() - plot.getMinFrequency(); if (zoomOut) { positionRange *= 2; frequencyRange *= 2; } else { positionRange /= 2; frequencyRange /= 2; } zoom(centerPosition, centerFrequency, positionRange, frequencyRange); } private void dragZoom(Point point) { Rectangle mapRectangle = plot.getMapRectangle(); if (mapRectangle == null) { return; } if (zoomOut) { plot.setZoom( 0, plot.getSegment().getSegmentLength(), 0, bookView.getDocument().getBook().getSamplingFrequency()/2 ); } else { Rectangle frame = getFrame(mapRectangle, point); double minPosition = plot.toPosition(frame.x); double maxPosition = plot.toPosition(frame.x+frame.width-1); double minFrequency = plot.toFrequency(frame.y+frame.height-1); double maxFrequency = plot.toFrequency(frame.y); double positionRange = maxPosition - minPosition; double frequencyRange = maxFrequency - minFrequency; zoom(minPosition + positionRange/2, minFrequency + frequencyRange/2, positionRange, frequencyRange); } } private void zoom(double centerPosition, double centerFrequency, double positionRange, double frequencyRange) { double maxPosition = plot.getSegment().getSegmentLength(); double maxFrequency = bookView.getDocument().getBook().getSamplingFrequency()/2; if (positionRange > maxPosition) { positionRange = maxPosition; } else if (positionRange < MIN_POSITION_RANGE) { positionRange = MIN_POSITION_RANGE; } if (frequencyRange > maxFrequency) { frequencyRange = maxFrequency; } else if (frequencyRange < MIN_FREQUENCY_RANGE) { frequencyRange = MIN_FREQUENCY_RANGE; } double newMinPosition = centerPosition - positionRange/2; if (newMinPosition < 0) { newMinPosition = 0; } double newMaxPosition = newMinPosition + positionRange; if (newMaxPosition > maxPosition) { newMaxPosition = maxPosition; newMinPosition = newMaxPosition - positionRange; } double newMinFrequency = centerFrequency - frequencyRange/2; if (newMinFrequency < 0) { newMinFrequency = 0; } double newMaxFrequency = newMinFrequency + frequencyRange; if (newMaxFrequency > maxFrequency) { newMaxFrequency = maxFrequency; newMinFrequency = newMaxFrequency - frequencyRange; } plot.setZoom(newMinPosition, newMaxPosition, newMinFrequency, newMaxFrequency); } public boolean isPreserveRatio() { return preserveRatio; } public void setPreserveRatio(boolean preserveRatio) { this.preserveRatio = preserveRatio; } }