]> git.argeo.org Git - lgpl/argeo-commons.git/blob - gis/plugins/org.argeo.gis.ui.rcp.swing/src/main/java/org/argeo/gis/ui/rcp/swing/VersatileZoomTool.java
Improve GIS
[lgpl/argeo-commons.git] / gis / plugins / org.argeo.gis.ui.rcp.swing / src / main / java / org / argeo / gis / ui / rcp / swing / VersatileZoomTool.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.gis.ui.rcp.swing;
18
19 import java.awt.Color;
20 import java.awt.Cursor;
21 import java.awt.Graphics2D;
22 import java.awt.Point;
23 import java.awt.Rectangle;
24 import java.awt.event.MouseEvent;
25 import java.awt.event.MouseWheelEvent;
26 import java.awt.event.MouseWheelListener;
27 import java.awt.geom.Point2D;
28
29 import javax.swing.SwingUtilities;
30 import javax.swing.event.MouseInputAdapter;
31
32 import org.geotools.geometry.DirectPosition2D;
33 import org.geotools.geometry.Envelope2D;
34 import org.geotools.geometry.jts.ReferencedEnvelope;
35 import org.geotools.swing.JMapPane;
36 import org.geotools.swing.event.MapMouseEvent;
37 import org.geotools.swing.tool.AbstractZoomTool;
38
39 public class VersatileZoomTool extends AbstractZoomTool {
40 // private Log log = LogFactory.getLog(VersatileZoomTool.class);
41
42 // private static final ResourceBundle stringRes = ResourceBundle
43 // .getBundle("org/geotools/swing/Text");
44
45 // Cursors
46 private Cursor zoomInCursor;
47 private Cursor panCursor;
48 private Cursor defaultCursor;
49
50 // Variable values
51 private Point2D startDragPos;
52 private Point panePos;
53 private boolean computingZoomBox;
54 private boolean panning;
55
56 private Point2D fieldPosition;
57
58 /**
59 * Constructor
60 */
61 public VersatileZoomTool() {
62 // Toolkit tk = Toolkit.getDefaultToolkit();
63 // zoomInCursor = tk.createCustomCursor(new ImageIcon(getClass()
64 // .getResource("/org/geotools/swing/icons/mActionZoomIn.png"))
65 // .getImage(), new Point(14, 9), stringRes
66 // .getString("tool_name_zoom_in"));
67 zoomInCursor = new Cursor(Cursor.SE_RESIZE_CURSOR);
68 // panCursor = tk.createCustomCursor(new
69 // ImageIcon(getClass().getResource(
70 // "/org/geotools/swing/icons/mActionPan.png")).getImage(),
71 // new Point(15, 15), stringRes.getString("tool_name_pan"));
72 panCursor = new Cursor(Cursor.HAND_CURSOR);
73 defaultCursor = new Cursor(Cursor.CROSSHAIR_CURSOR);
74
75 startDragPos = new DirectPosition2D();
76 computingZoomBox = false;
77 panning = false;
78
79 }
80
81 /**
82 * Zoom in by the currently set increment, with the map centred at the
83 * location (in world coords) of the mouse click
84 *
85 * @param e
86 * map mapPane mouse event
87 */
88 @Override
89 public void onMouseClicked(MapMouseEvent e) {
90 if (SwingUtilities.isLeftMouseButton(e))
91 centerMapToEvent(e, getZoom());
92 else if (SwingUtilities.isRightMouseButton(e))
93 centerMapToEvent(e, 1 / getZoom());
94 else if (SwingUtilities.isMiddleMouseButton(e)) {
95 if (fieldPosition != null) {
96 Envelope2D env = new Envelope2D();
97 final double increment = 0.1d;
98 env.setFrameFromDiagonal(fieldPosition.getX() - increment,
99 fieldPosition.getY() - increment, fieldPosition.getX()
100 + increment, fieldPosition.getY() + increment);
101 getMapPane().setDisplayArea(env);
102 }
103 }
104 }
105
106 protected void centerMapToEvent(MapMouseEvent e, Double zoomArg) {
107 Rectangle paneArea = getMapPane().getVisibleRect();
108 DirectPosition2D mapPos = e.getMapPosition();
109
110 double scale = getMapPane().getWorldToScreenTransform().getScaleX();
111 double newScale = scale * zoomArg;
112
113 DirectPosition2D corner = new DirectPosition2D(mapPos.getX() - 0.5d
114 * paneArea.getWidth() / newScale, mapPos.getY() + 0.5d
115 * paneArea.getHeight() / newScale);
116
117 Envelope2D newMapArea = new Envelope2D();
118 newMapArea.setFrameFromCenter(mapPos, corner);
119 getMapPane().setDisplayArea(newMapArea);
120 }
121
122 /**
123 * Records the map position of the mouse event in case this button press is
124 * the beginning of a mouse drag
125 *
126 * @param ev
127 * the mouse event
128 */
129 @Override
130 public void onMousePressed(MapMouseEvent ev) {
131 if (SwingUtilities.isLeftMouseButton(ev)) {
132 startDragPos = new DirectPosition2D();
133 startDragPos.setLocation(ev.getMapPosition());
134 } else if (SwingUtilities.isMiddleMouseButton(ev)
135 || SwingUtilities.isRightMouseButton(ev)) {
136 panePos = ev.getPoint();
137 panning = true;
138 }
139 }
140
141 /**
142 * Records that the mouse is being dragged
143 *
144 * @param ev
145 * the mouse event
146 */
147 @Override
148 public void onMouseDragged(MapMouseEvent ev) {
149 if (SwingUtilities.isLeftMouseButton(ev)) {
150 computingZoomBox = true;
151 } else if (panning) {
152 Point pos = ev.getPoint();
153 if (!pos.equals(panePos)) {
154 getMapPane().moveImage(pos.x - panePos.x, pos.y - panePos.y);
155 panePos = pos;
156 }
157 }
158 getMapPane().setCursor(getCursor());
159 }
160
161 /**
162 * If the mouse was dragged, determines the bounds of the box that the user
163 * defined and passes this to the mapPane's
164 * {@link org.geotools.swing.JMapPane#setDisplayArea(org.opengis.geometry.Envelope) }
165 * method
166 *
167 * @param ev
168 * the mouse event
169 */
170 @Override
171 public void onMouseReleased(MapMouseEvent ev) {
172 if (computingZoomBox && !ev.getPoint().equals(startDragPos)) {
173 Envelope2D env = new Envelope2D();
174 env.setFrameFromDiagonal(startDragPos, ev.getMapPosition());
175 computingZoomBox = false;
176 getMapPane().setDisplayArea(env);
177 } else if (panning) {
178 panning = false;
179 getMapPane().repaint();
180 }
181 getMapPane().setCursor(getCursor());
182 }
183
184 /**
185 * Get the mouse cursor for this tool
186 */
187 @Override
188 public Cursor getCursor() {
189 if (computingZoomBox)
190 return zoomInCursor;
191 else if (panning)
192 return panCursor;
193 else
194 return defaultCursor;
195 }
196
197 /**
198 * We use a custom drag box
199 */
200 @Override
201 public boolean drawDragBox() {
202 return false;
203 }
204
205 @Override
206 public void setMapPane(JMapPane pane) {
207 super.setMapPane(pane);
208 VariableDragBox dragBox = new VariableDragBox();
209 getMapPane().addMouseListener(dragBox);
210 getMapPane().addMouseMotionListener(dragBox);
211 getMapPane().addMouseWheelListener(new MouseWheelListener() {
212 private double clickToZoom = 0.1; // 1 wheel click is 10% zoom
213
214 public void mouseWheelMoved(MouseWheelEvent ev) {
215 int clicks = ev.getWheelRotation();
216 // -ve means wheel moved up, +ve means down
217 int sign = (clicks < 0 ? -1 : 1);
218
219 ReferencedEnvelope env = getMapPane().getDisplayArea();
220 if (env == null)
221 return;
222 double width = env.getWidth();
223 double delta = width * clickToZoom * sign;
224
225 env.expandBy(delta);
226 getMapPane().setDisplayArea(env);
227 getMapPane().repaint();
228 }
229 });
230 }
231
232 public void setFieldPosition(Point2D fieldPosition) {
233 this.fieldPosition = fieldPosition;
234 }
235
236 /**
237 * Custom drag box (hacked from JMapPane) so that we can change the behavior
238 * depending on whether we pan or zoom.
239 */
240 private class VariableDragBox extends MouseInputAdapter {
241
242 private Point startPos;
243 private Rectangle rect;
244 private boolean dragged;
245
246 VariableDragBox() {
247 rect = new Rectangle();
248 dragged = false;
249 }
250
251 @Override
252 public void mousePressed(MouseEvent e) {
253 startPos = new Point(e.getPoint());
254 }
255
256 @Override
257 public void mouseDragged(MouseEvent e) {
258 if (computingZoomBox) {
259 Graphics2D g2D = (Graphics2D) getMapPane().getGraphics();
260 g2D.setColor(Color.WHITE);
261 g2D.setXORMode(Color.RED);
262 if (dragged) {
263 g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
264 }
265
266 rect.setFrameFromDiagonal(startPos, e.getPoint());
267 g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
268
269 dragged = true;
270 }
271 }
272
273 @Override
274 public void mouseReleased(MouseEvent e) {
275 if (dragged) {
276 Graphics2D g2D = (Graphics2D) getMapPane().getGraphics();
277 g2D.setColor(Color.WHITE);
278 g2D.setXORMode(Color.RED);
279 g2D.drawRect(rect.x, rect.y, rect.width, rect.height);
280 dragged = false;
281 }
282 }
283 }
284
285 }