-/*
- * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.argeo.gis.ui.rcp.swing;
-
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.awt.geom.Point2D;
-
-import javax.swing.SwingUtilities;
-import javax.swing.event.MouseInputAdapter;
-
-import org.geotools.geometry.DirectPosition2D;
-import org.geotools.geometry.Envelope2D;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.swing.JMapPane;
-import org.geotools.swing.event.MapMouseEvent;
-import org.geotools.swing.tool.AbstractZoomTool;
-
-public class VersatileZoomTool extends AbstractZoomTool {
- // private Log log = LogFactory.getLog(VersatileZoomTool.class);
-
- // private static final ResourceBundle stringRes = ResourceBundle
- // .getBundle("org/geotools/swing/Text");
-
- // Cursors
- private Cursor zoomInCursor;
- private Cursor panCursor;
- private Cursor defaultCursor;
-
- // Variable values
- private Point2D startDragPos;
- private Point panePos;
- private boolean computingZoomBox;
- private boolean panning;
-
- private Point2D fieldPosition;
-
- /**
- * Constructor
- */
- public VersatileZoomTool() {
- // Toolkit tk = Toolkit.getDefaultToolkit();
- // zoomInCursor = tk.createCustomCursor(new ImageIcon(getClass()
- // .getResource("/org/geotools/swing/icons/mActionZoomIn.png"))
- // .getImage(), new Point(14, 9), stringRes
- // .getString("tool_name_zoom_in"));
- zoomInCursor = new Cursor(Cursor.SE_RESIZE_CURSOR);
- // panCursor = tk.createCustomCursor(new
- // ImageIcon(getClass().getResource(
- // "/org/geotools/swing/icons/mActionPan.png")).getImage(),
- // new Point(15, 15), stringRes.getString("tool_name_pan"));
- panCursor = new Cursor(Cursor.HAND_CURSOR);
- defaultCursor = new Cursor(Cursor.CROSSHAIR_CURSOR);
-
- startDragPos = new DirectPosition2D();
- computingZoomBox = false;
- panning = false;
-
- }
-
- /**
- * Zoom in by the currently set increment, with the map centred at the
- * location (in world coords) of the mouse click
- *
- * @param e
- * map mapPane mouse event
- */
- @Override
- public void onMouseClicked(MapMouseEvent e) {
- if (SwingUtilities.isLeftMouseButton(e))
- centerMapToEvent(e, getZoom());
- else if (SwingUtilities.isRightMouseButton(e))
- centerMapToEvent(e, 1 / getZoom());
- else if (SwingUtilities.isMiddleMouseButton(e)) {
- if (fieldPosition != null) {
- Envelope2D env = new Envelope2D();
- final double increment = 0.1d;
- env.setFrameFromDiagonal(fieldPosition.getX() - increment,
- fieldPosition.getY() - increment, fieldPosition.getX()
- + increment, fieldPosition.getY() + increment);
- getMapPane().setDisplayArea(env);
- }
- }
- }
-
- protected void centerMapToEvent(MapMouseEvent e, Double zoomArg) {
- Rectangle paneArea = getMapPane().getVisibleRect();
- DirectPosition2D mapPos = e.getMapPosition();
-
- double scale = getMapPane().getWorldToScreenTransform().getScaleX();
- double newScale = scale * zoomArg;
-
- DirectPosition2D corner = new DirectPosition2D(mapPos.getX() - 0.5d
- * paneArea.getWidth() / newScale, mapPos.getY() + 0.5d
- * paneArea.getHeight() / newScale);
-
- Envelope2D newMapArea = new Envelope2D();
- newMapArea.setFrameFromCenter(mapPos, corner);
- getMapPane().setDisplayArea(newMapArea);
- }
-
- /**
- * Records the map position of the mouse event in case this button press is
- * the beginning of a mouse drag
- *
- * @param ev
- * the mouse event
- */
- @Override
- public void onMousePressed(MapMouseEvent ev) {
- if (SwingUtilities.isLeftMouseButton(ev)) {
- startDragPos = new DirectPosition2D();
- startDragPos.setLocation(ev.getMapPosition());
- } else if (SwingUtilities.isMiddleMouseButton(ev)
- || SwingUtilities.isRightMouseButton(ev)) {
- panePos = ev.getPoint();
- panning = true;
- }
- }
-
- /**
- * Records that the mouse is being dragged
- *
- * @param ev
- * the mouse event
- */
- @Override
- public void onMouseDragged(MapMouseEvent ev) {
- if (SwingUtilities.isLeftMouseButton(ev)) {
- computingZoomBox = true;
- } else if (panning) {
- Point pos = ev.getPoint();
- if (!pos.equals(panePos)) {
- getMapPane().moveImage(pos.x - panePos.x, pos.y - panePos.y);
- panePos = pos;
- }
- }
- getMapPane().setCursor(getCursor());
- }
-
- /**
- * If the mouse was dragged, determines the bounds of the box that the user
- * defined and passes this to the mapPane's
- * {@link org.geotools.swing.JMapPane#setDisplayArea(org.opengis.geometry.Envelope) }
- * method
- *
- * @param ev
- * the mouse event
- */
- @Override
- public void onMouseReleased(MapMouseEvent ev) {
- if (computingZoomBox && !ev.getPoint().equals(startDragPos)) {
- Envelope2D env = new Envelope2D();
- env.setFrameFromDiagonal(startDragPos, ev.getMapPosition());
- computingZoomBox = false;
- getMapPane().setDisplayArea(env);
- } else if (panning) {
- panning = false;
- getMapPane().repaint();
- }
- getMapPane().setCursor(getCursor());
- }
-
- /**
- * Get the mouse cursor for this tool
- */
- @Override
- public Cursor getCursor() {
- if (computingZoomBox)
- return zoomInCursor;
- else if (panning)
- return panCursor;
- else
- return defaultCursor;
- }
-
- /**
- * We use a custom drag box
- */
- @Override
- public boolean drawDragBox() {
- return false;
- }
-
- @Override
- public void setMapPane(JMapPane pane) {
- super.setMapPane(pane);
- VariableDragBox dragBox = new VariableDragBox();
- getMapPane().addMouseListener(dragBox);
- getMapPane().addMouseMotionListener(dragBox);
- getMapPane().addMouseWheelListener(new MouseWheelListener() {
- private double clickToZoom = 0.1; // 1 wheel click is 10% zoom
-
- public void mouseWheelMoved(MouseWheelEvent ev) {
- int clicks = ev.getWheelRotation();
- // -ve means wheel moved up, +ve means down
- int sign = (clicks < 0 ? -1 : 1);
-
- ReferencedEnvelope env = getMapPane().getDisplayArea();
- if (env == null)
- return;
- double width = env.getWidth();
- double delta = width * clickToZoom * sign;
-
- env.expandBy(delta);
- getMapPane().setDisplayArea(env);
- getMapPane().repaint();
- }
- });
- }
-
- public void setFieldPosition(Point2D fieldPosition) {
- this.fieldPosition = fieldPosition;
- }
-
- /**
- * Custom drag box (hacked from JMapPane) so that we can change the behavior
- * depending on whether we pan or zoom.
- */
- private class VariableDragBox extends MouseInputAdapter {
-
- private Point startPos;
- private Rectangle rect;
- private boolean dragged;
-
- VariableDragBox() {
- rect = new Rectangle();
- dragged = false;
- }
-
- @Override
- public void mousePressed(MouseEvent e) {
- startPos = new Point(e.getPoint());
- }
-
- @Override
- public void mouseDragged(MouseEvent e) {
- if (computingZoomBox) {
- Graphics2D g2D = (Graphics2D) getMapPane().getGraphics();
- g2D.setColor(Color.WHITE);
- g2D.setXORMode(Color.RED);
- if (dragged) {
- g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
- }
-
- rect.setFrameFromDiagonal(startPos, e.getPoint());
- g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
-
- dragged = true;
- }
- }
-
- @Override
- public void mouseReleased(MouseEvent e) {
- if (dragged) {
- Graphics2D g2D = (Graphics2D) getMapPane().getGraphics();
- g2D.setColor(Color.WHITE);
- g2D.setXORMode(Color.RED);
- g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
- dragged = false;
- }
- }
- }
-
-}