source: josm/src/org/openstreetmap/josm/actions/ZoomAction.java@ 1

Last change on this file since 1 was 1, checked in by imi, 21 years ago

wiki 19:37, 27. Sep 2005

File size: 6.8 KB
Line 
1package org.openstreetmap.josm.actions;
2
3import static java.awt.event.MouseEvent.BUTTON1;
4import static java.awt.event.MouseEvent.BUTTON3;
5
6import java.awt.Color;
7import java.awt.Cursor;
8import java.awt.Graphics;
9import java.awt.Point;
10import java.awt.Rectangle;
11import java.awt.event.KeyEvent;
12import java.awt.event.MouseEvent;
13import java.awt.event.MouseListener;
14import java.awt.event.MouseMotionListener;
15import java.awt.event.MouseWheelEvent;
16import java.awt.event.MouseWheelListener;
17
18import org.openstreetmap.josm.data.GeoPoint;
19import org.openstreetmap.josm.gui.MapFrame;
20import org.openstreetmap.josm.gui.MapView;
21
22/**
23 * Enable the zoom mode within the MapFrame.
24 *
25 * @author imi
26 */
27public class ZoomAction extends MapMode
28 implements MouseListener, MouseMotionListener, MouseWheelListener {
29
30 /**
31 * Point, the mouse was when pressing the button.
32 */
33 private Point mousePosStart;
34 /**
35 * Point to the actual mouse position.
36 */
37 private Point mousePos;
38 /**
39 * The point in the map that was the under the mouse point
40 * when moving around started.
41 */
42 private GeoPoint mousePosMove;
43 /**
44 * Shortcut to the mapview.
45 */
46 private final MapView mv;
47 /**
48 * Whether currently an zooming rectangle is visible or not
49 */
50 private boolean zoomRectVisible = false;
51
52 /**
53 * For the current state.
54 */
55 enum State {NOTHING, MOVE, ZOOM, ZOOM_POS};
56 /**
57 * The current state, the ZoomAction is in.
58 */
59 State state = State.NOTHING;
60
61
62
63 /**
64 * Construct a ZoomAction without a label.
65 * @param mapFrame The MapFrame, whose zoom mode should be enabled.
66 */
67 public ZoomAction(MapFrame mapFrame) {
68 super("Zoom", "images/zoom.png", KeyEvent.VK_Z, mapFrame);
69 mv = mapFrame.mapView;
70 }
71
72 /**
73 * Just to keep track of mouse movements.
74 */
75 public void mouseMoved(MouseEvent e) {
76 mousePos = e.getPoint();
77 }
78
79 /**
80 * Initializing the mouse moving state.
81 */
82 public void mousePressed(MouseEvent e) {
83 switch (state) {
84 case NOTHING:
85 switch (e.getButton()) {
86 case BUTTON1:
87 state = State.ZOOM;
88 mousePosStart = e.getPoint();
89 paintZoomRect(true);
90 break;
91 case BUTTON3:
92 state = State.MOVE;
93 mousePosMove = mv.getPoint(e.getX(), e.getY(), false);
94 mv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
95 break;
96 }
97 break;
98 case ZOOM:
99 if (e.getButton() == BUTTON3)
100 state = State.ZOOM_POS;
101 break;
102 case MOVE:
103 if (e.getButton() == BUTTON1) {
104 state = State.ZOOM_POS;
105 mousePosStart = e.getPoint();
106 mousePos = e.getPoint();
107 }
108 }
109 }
110
111 public void mouseReleased(MouseEvent e) {
112 switch (state) {
113 case ZOOM:
114 if (e.getButton() == BUTTON1) {
115 state = State.NOTHING;
116 paintZoomRect(false);
117 Rectangle r = calculateZoomableRectangle();
118 mousePosStart = null;
119 // zoom to the rectangle
120 if (r != null) {
121 double scale = mv.getScale() * r.getWidth()/mv.getWidth();
122 GeoPoint newCenter = mv.getPoint(r.x+r.width/2, r.y+r.height/2, false);
123 mv.zoomTo(newCenter, scale);
124 }
125 }
126 break;
127 case MOVE:
128 if (e.getButton() == BUTTON3) {
129 state = State.NOTHING;
130 mousePosMove = null;
131 mv.setCursor(Cursor.getDefaultCursor());
132 }
133 break;
134 case ZOOM_POS:
135 switch (e.getButton()) {
136 case BUTTON1:
137 state = State.MOVE;
138 paintZoomRect(false);
139 mousePosStart = null;
140 mousePos = null;
141 mousePosMove = mv.getPoint(e.getX(), e.getY(), false);
142 mv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
143 break;
144 case BUTTON3:
145 state = State.ZOOM;
146 break;
147 }
148 }
149 }
150
151 public void mouseDragged(MouseEvent e) {
152 switch (state) {
153 case MOVE:
154 if (mousePosMove == null) {
155 mousePosMove = mv.getCenter();
156 mv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
157 }
158 GeoPoint center = mv.getCenter();
159 GeoPoint mouseCenter = mv.getPoint(e.getX(), e.getY(), false);
160 GeoPoint p = new GeoPoint();
161 p.x = mousePosMove.x + center.x - mouseCenter.x;
162 p.y = mousePosMove.y + center.y - mouseCenter.y;
163 mv.zoomTo(p, mv.getScale());
164 break;
165 case ZOOM:
166 if (mousePosStart == null)
167 mousePosStart = e.getPoint();
168 if (mousePos == null)
169 mousePos = e.getPoint();
170 paintZoomRect(false);
171 mousePos = e.getPoint();
172 paintZoomRect(true);
173 break;
174 case ZOOM_POS:
175 if (mousePosStart == null)
176 mousePosStart = e.getPoint();
177 if (mousePos == null)
178 mousePos = e.getPoint();
179 paintZoomRect(false);
180 mousePosStart.x += e.getX()-mousePos.x;
181 mousePosStart.y += e.getY()-mousePos.y;
182 mousePos = e.getPoint();
183 paintZoomRect(true);
184 break;
185 }
186 }
187
188 public void mouseWheelMoved(MouseWheelEvent e) {
189 boolean zoomRect = zoomRectVisible;
190 paintZoomRect(false);
191 double zoom = Math.max(0.1, 1 + e.getWheelRotation()/5.0);
192 mv.zoomTo(mv.getCenter(), mv.getScale()*zoom);
193 paintZoomRect(zoomRect);
194 }
195
196 /**
197 * Calculate the zoomable rectangle between mousePos and mousePosStart.
198 * Zoomable is the rectangle with a fix point at mousePosStart and the
199 * correct aspect ratio that fits into the current mapView's size.
200 * @return Rectangle which should be used to zoom.
201 */
202 private Rectangle calculateZoomableRectangle() {
203 if (mousePosStart == null || mousePos == null || mousePosStart == mousePos)
204 return null;
205 Rectangle r = new Rectangle();
206 r.x = mousePosStart.x;
207 r.y = mousePosStart.y;
208 r.width = mousePos.x - mousePosStart.x;
209 r.height = mousePos.y - mousePosStart.y;
210 if (r.width < 0) {
211 r.x += r.width;
212 r.width = -r.width;
213 }
214 if (r.height < 0) {
215 r.y += r.height;
216 r.height = -r.height;
217 }
218
219 // keep the aspect ration by shrinking the rectangle
220 double aspectRatio = (double)mv.getWidth()/mv.getHeight();
221 if ((double)r.width/r.height > aspectRatio)
222 r.width = (int)(r.height*aspectRatio);
223 else
224 r.height = (int)(r.width/aspectRatio);
225
226 return r;
227 }
228
229 /**
230 * Paint the mouse selection rectangle XOR'ed over the display.
231 *
232 * @param drawVisible True, to draw the rectangle or false to erase it.
233 */
234 private void paintZoomRect(boolean drawVisible) {
235 Rectangle r = calculateZoomableRectangle();
236 if (r != null && drawVisible != zoomRectVisible) {
237 Graphics g = mv.getGraphics();
238 g.setColor(Color.BLACK);
239 g.setXORMode(Color.WHITE);
240 g.drawRect(r.x,r.y,r.width,r.height);
241 zoomRectVisible = !zoomRectVisible;
242 }
243 }
244
245 public void registerListener(MapView mapView) {
246 mapView.addMouseListener(this);
247 mapView.addMouseMotionListener(this);
248 mapView.addMouseWheelListener(this);
249 }
250
251 public void unregisterListener(MapView mapView) {
252 mapView.removeMouseListener(this);
253 mapView.removeMouseMotionListener(this);
254 mapView.removeMouseWheelListener(this);
255 }
256
257 /**
258 * Does nothing. Only to satisfy MouseListener
259 */
260 public void mouseClicked(MouseEvent e) {}
261 /**
262 * Does nothing. Only to satisfy MouseListener
263 */
264 public void mouseEntered(MouseEvent e) {}
265 /**
266 * Does nothing. Only to satisfy MouseListener
267 */
268 public void mouseExited(MouseEvent e) {}
269}
Note: See TracBrowser for help on using the repository browser.