001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui.zoom;
034:
035: import java.awt.Color;
036: import java.awt.Cursor;
037: import java.awt.event.MouseEvent;
038: import java.awt.event.MouseWheelEvent;
039: import java.awt.geom.NoninvertibleTransformException;
040: import java.awt.geom.Point2D;
041:
042: import javax.swing.Icon;
043: import javax.swing.SwingUtilities;
044:
045: import com.vividsolutions.jump.I18N;
046: import com.vividsolutions.jump.util.MathUtil;
047: import com.vividsolutions.jump.workbench.ui.LayerViewPanel;
048: import com.vividsolutions.jump.workbench.ui.cursortool.DragTool;
049: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
050: import com.vividsolutions.jts.geom.Coordinate;
051:
052: public class ZoomTool extends DragTool {
053: /**
054: * If the selection box has side length less than this value, the input
055: * will be considered to be a click rather than a box.
056: */
057: private static final int BOX_TOLERANCE = 4;
058: private static final double ZOOM_IN_FACTOR = 2;
059: private static final double WHEEL_ZOOM_IN_FACTOR = 1.25;
060:
061: public ZoomTool() {
062: setColor(Color.black);
063: }
064:
065: public Icon getIcon() {
066: return IconLoader.icon("Magnify.gif");
067: }
068:
069: public String getName() {
070: return I18N.get("ui.zoom.ZoomTool.zoom-in-out");
071: }
072:
073: public Cursor getCursor() {
074: return createCursor(IconLoader.icon("MagnifyCursor.gif")
075: .getImage());
076: }
077:
078: protected void gestureFinished()
079: throws NoninvertibleTransformException {
080: reportNothingToUndoYet();
081:
082: double minX = Math.min(getViewSource().getX(),
083: getViewDestination().getX());
084: double maxX = Math.max(getViewSource().getX(),
085: getViewDestination().getX());
086: double minY = Math.min(getViewSource().getY(),
087: getViewDestination().getY());
088: double maxY = Math.max(getViewSource().getY(),
089: getViewDestination().getY());
090:
091: //<<TODO:REFACTORING>> MD feels we should move this logic into
092: //Viewport, in case other classes want to use it [Jon Aquino]
093: double widthOfNewViewAsPerceivedByOldView = maxX - minX;
094: double heightOfNewViewAsPerceivedByOldView = maxY - minY;
095:
096: if ((widthOfNewViewAsPerceivedByOldView == 0)
097: && (heightOfNewViewAsPerceivedByOldView == 0)) {
098: //Handled by #mouseClicked
099: return;
100: }
101:
102: if ((widthOfNewViewAsPerceivedByOldView < BOX_TOLERANCE)
103: && (heightOfNewViewAsPerceivedByOldView < BOX_TOLERANCE)) {
104: zoomAt(new Point2D.Double(MathUtil.avg(minX, maxX),
105: MathUtil.avg(minY, maxY)), ZOOM_IN_FACTOR);
106:
107: return;
108: }
109:
110: Point2D centreOfNewViewAsPerceivedByOldView = new Point2D.Double(
111: minX + (widthOfNewViewAsPerceivedByOldView / 2), minY
112: + (heightOfNewViewAsPerceivedByOldView / 2));
113: getPanel().getViewport().zoom(
114: centreOfNewViewAsPerceivedByOldView,
115: widthOfNewViewAsPerceivedByOldView,
116: heightOfNewViewAsPerceivedByOldView);
117:
118: //<<TODO:ERGONOMICS>> If user draws a tiny square (e.g. 3 pixels), treat it as
119: //a click. [Jon Aquino]
120: }
121:
122: public void mouseClicked(MouseEvent e) {
123: try {
124: double zoomFactor = SwingUtilities.isRightMouseButton(e) ? (1 / ZOOM_IN_FACTOR)
125: : ZOOM_IN_FACTOR;
126: zoomAt(e.getPoint(), zoomFactor);
127: } catch (Throwable t) {
128: getPanel().getContext().handleThrowable(t);
129: }
130: }
131:
132: public void mousePressed(MouseEvent e) {
133: try {
134: if (SwingUtilities.isLeftMouseButton(e)) {
135: super .mousePressed(e);
136: }
137: } catch (Throwable t) {
138: getPanel().getContext().handleThrowable(t);
139: }
140: }
141:
142: private void zoomAt(Point2D p, double zoomFactor)
143: throws NoninvertibleTransformException {
144: getPanel().getViewport().zoomToViewPoint(p, zoomFactor);
145: }
146:
147: public boolean isRightMouseButtonUsed() {
148: return true;
149: }
150:
151: public void mouseDragged(MouseEvent e) {
152: super .mouseDragged(e);
153: }
154:
155: public void mouseReleased(MouseEvent e) {
156: super .mouseReleased(e);
157: }
158:
159: public void mouseWheelMoved(MouseWheelEvent e) {
160: int nclicks = e.getWheelRotation(); //negative is up/away
161: try {
162: double zoomFactor = (nclicks > 0) ? (1 / (Math.abs(nclicks) * WHEEL_ZOOM_IN_FACTOR))
163: : (Math.abs(nclicks) * WHEEL_ZOOM_IN_FACTOR);
164: //zoomAt(e.getPoint(), zoomFactor); //zoom to cursor
165: zoomAt(getPanel().getViewport().toViewPoint( //zoom to center
166: getPanel().getViewport()
167: .getEnvelopeInModelCoordinates().centre()),
168: zoomFactor);
169: } catch (Throwable t) {
170: getPanel().getContext().handleThrowable(t);
171: }
172: }
173:
174: public void activate(LayerViewPanel layerViewPanel) {
175: super .activate(layerViewPanel);
176: }
177:
178: public void deactivate() {
179: super .deactivate();
180: }
181:
182: public void mouseEntered(MouseEvent e) {
183: super .mouseEntered(e);
184: }
185:
186: public void mouseExited(MouseEvent e) {
187: super .mouseExited(e);
188: }
189:
190: public void mouseMoved(MouseEvent e) {
191: super.mouseMoved(e);
192: }
193:
194: }
|