/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2007 - 2008, Open Source Geospatial Foundation (OSGeo) * (C) 2008 - 2009, Johann Sorel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.render2d.control.navigation; import java.awt.Component; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import javax.swing.event.MouseInputListener; import org.geotoolkit.display2d.canvas.J2DCanvasSwing; import org.geotoolkit.gui.swing.render2d.JMap2D; import org.geotoolkit.gui.swing.render2d.decoration.InformationDecoration.LEVEL; import org.geotoolkit.gui.swing.render2d.decoration.MapDecoration; /** * Listener to handle mouse drag, move zoom. * * @author Johann Sorel (Puzzle-GIS) * @module */ public class MouseNavigatonListener implements MouseInputListener, MouseWheelListener { private final ZoomDecoration decorationPane = new ZoomDecoration(); private double zoomFactor = 2; private JMap2D map; private int startX; private int startY; private int lastX; private int lastY; private int mousebutton = 0; private int panButton = MouseEvent.BUTTON3; public MouseNavigatonListener(final JMap2D map) { this.map = map; } protected boolean isStateFull(){ if(map == null) return false; return map.getCanvas() instanceof J2DCanvasSwing; } public void setMap(final JMap2D map) { this.map = map; } public JMap2D getMap() { return map; } public void setPanButton(final int panButton) { this.panButton = panButton; } public int getPanButton() { return panButton; } protected MapDecoration getDecoration(){ return decorationPane; } public void install(final Component component){ map.addDecoration(0,decorationPane); component.addMouseListener(this); component.addMouseMotionListener(this); component.addMouseWheelListener(this); } public void uninstall(final Component component){ component.removeMouseListener(this); component.removeMouseMotionListener(this); component.removeMouseWheelListener(this); map.removeDecoration(decorationPane); } /** * Make a zoom on the map at the given point */ protected void scale(final Point2D center, final double zoom){ try { map.getCanvas().scale(zoom, center); } catch (NoninvertibleTransformException ex) { map.getInformationDecoration().displayMessage(ex.getLocalizedMessage(), 3000, LEVEL.ERROR); } } /** * Zoom on the given rectangle coordinates. */ protected void zoom(int startx,int starty, int endx, int endy){ if(startx > endx){ final int n = endx; endx = startx; startx = n; } if(starty > endy){ final int n = endy; endy = starty; starty = n; } final Rectangle2D rect = new Rectangle(startx,starty,endx-startx,endy-starty); map.getCanvas().setDisplayVisibleArea(rect); } /** * Draw a rectangle on the ZoomPan decoration. */ protected void drawRectangle(final int startX, final int startY, final int lastX, final int lastY, final boolean view, final boolean fill) { final int left = Math.min(startX, lastX); final int right = Math.max(startX, lastX); final int top = Math.max(startY, lastY); final int bottom = Math.min(startY, lastY); final int width = right - left; final int height = top - bottom; decorationPane.setFill(fill); decorationPane.setCoord(left, bottom, width, height, view); } /** * Drag the map from coordinate 1 to coordinate 2. */ protected void processDrag(final int x1, final int y1, final int x2, final int y2) { try { map.getCanvas().translateDisplay(x2 - x1, y2 - y1); } catch (NoninvertibleTransformException ex) { map.getInformationDecoration().displayMessage(ex.getLocalizedMessage(), 3000, LEVEL.ERROR); } } @Override public void mouseClicked(final MouseEvent e) { startX = e.getX(); startY = e.getY(); lastX = startX; lastY = startY; } @Override public void mousePressed(final MouseEvent e) { startX = e.getX(); startY = e.getY(); lastX = 0; lastY = 0; mousebutton = e.getButton(); if (mousebutton == panButton) { //pan action on right mouse button if(!isStateFull()){ decorationPane.setBuffer(map.getCanvas().getSnapShot()); decorationPane.setCoord(0, 0, map.getComponent().getWidth(), map.getComponent().getHeight(), true); } } } @Override public void mouseReleased(final MouseEvent e) { int endX = e.getX(); int endY = e.getY(); decorationPane.setBuffer(null); if (mousebutton == panButton) { //right mouse button : pan action if(!isStateFull()){ decorationPane.setBuffer(null); decorationPane.setFill(false); decorationPane.setCoord(-10, -10,-10, -10, false); processDrag(startX, startY, endX, endY); } } lastX = 0; lastY = 0; } @Override public void mouseEntered(final MouseEvent e) { } @Override public void mouseExited(final MouseEvent e) { decorationPane.setFill(false); decorationPane.setCoord(-10, -10,-10, -10, true); } @Override public void mouseDragged(final MouseEvent e) { int x = e.getX(); int y = e.getY(); if (mousebutton == panButton) { if ((lastX > 0) && (lastY > 0)) { int dx = lastX - startX; int dy = lastY - startY; if(isStateFull()){ processDrag(lastX, lastY, x, y); }else{ decorationPane.setFill(true); decorationPane.setCoord(dx, dy, map.getComponent().getWidth(), map.getComponent().getHeight(), true); } } lastX = x; lastY = y; }else{ lastX = x; lastY = y; } } @Override public void mouseMoved(final MouseEvent e) { Rectangle rect = new Rectangle(e.getPoint()); rect.x -= 10; rect.y -= 10; rect.width = 10; rect.height = 10; } @Override public void mouseWheelMoved(final MouseWheelEvent e) { int rotate = e.getWheelRotation(); if (rotate < 0) { scale(e.getPoint(), zoomFactor); } else if (rotate > 0) { scale(e.getPoint(), 1d / zoomFactor); } } }