source: josm/trunk/src/org/openstreetmap/josm/gui/download/OsmMapControl.java@ 2331

Last change on this file since 2331 was 1677, checked in by stoecker, 15 years ago

remove all these ugly tab stops introduced in the last half year

File size: 10.8 KB
Line 
1// This code has been adapted and copied from code that has been written by Immanuel Scholz and others for JOSM.
2// License: GPL. Copyright 2007 by Tim Haussmann
3package org.openstreetmap.josm.gui.download;
4
5import java.awt.Point;
6import java.awt.event.ActionEvent;
7import java.awt.event.InputEvent;
8import java.awt.event.KeyEvent;
9import java.awt.event.MouseAdapter;
10import java.awt.event.MouseEvent;
11import java.awt.event.MouseListener;
12import java.awt.event.MouseMotionListener;
13import java.util.Timer;
14import java.util.TimerTask;
15
16import javax.swing.AbstractAction;
17import javax.swing.ActionMap;
18import javax.swing.InputMap;
19import javax.swing.JComponent;
20import javax.swing.JPanel;
21import javax.swing.KeyStroke;
22
23/**
24 * This class controls the user input by listening to mouse and key events.
25 * Currently implemented is: - zooming in and out with scrollwheel - zooming in
26 * and centering by double clicking - selecting an area by clicking and dragging
27 * the mouse
28 *
29 * @author Tim Haussmann
30 */
31public class OsmMapControl extends MouseAdapter implements MouseMotionListener, MouseListener {
32
33 /** A Timer for smoothly moving the map area */
34 private static final Timer timer = new Timer(true);
35
36 /** Does the moving */
37 private MoveTask moveTask = new MoveTask();
38
39 /** How often to do the moving (milliseconds) */
40 private static long timerInterval = 20;
41
42 /** The maximum speed (pixels per timer interval) */
43 private static final double MAX_SPEED = 20;
44
45 /** The speed increase per timer interval when a cursor button is clicked */
46 private static final double ACCELERATION = 0.10;
47
48 // start and end point of selection rectangle
49 private Point iStartSelectionPoint;
50 private Point iEndSelectionPoint;
51
52 // the SlippyMapChooserComponent
53 private final SlippyMapChooser iSlippyMapChooser;
54
55 private SizeButton iSizeButton = null;
56 private SourceButton iSourceButton = null;
57
58 /**
59 * Create a new OsmMapControl
60 */
61 public OsmMapControl(SlippyMapChooser navComp, JPanel contentPane, SizeButton sizeButton, SourceButton sourceButton) {
62 this.iSlippyMapChooser = navComp;
63 iSlippyMapChooser.addMouseListener(this);
64 iSlippyMapChooser.addMouseMotionListener(this);
65
66 String[] n = { ",", ".", "up", "right", "down", "left" };
67 int[] k = { KeyEvent.VK_COMMA, KeyEvent.VK_PERIOD, KeyEvent.VK_UP, KeyEvent.VK_RIGHT, KeyEvent.VK_DOWN,
68 KeyEvent.VK_LEFT };
69
70 if (contentPane != null) {
71 for (int i = 0; i < n.length; ++i) {
72 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
73 KeyStroke.getKeyStroke(k[i], KeyEvent.CTRL_DOWN_MASK), "MapMover.Zoomer." + n[i]);
74 }
75 }
76 iSizeButton = sizeButton;
77 iSourceButton = sourceButton;
78
79 InputMap inputMap = navComp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
80 ActionMap actionMap = navComp.getActionMap();
81
82 // map moving
83 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "MOVE_RIGHT");
84 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "MOVE_LEFT");
85 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "MOVE_UP");
86 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "MOVE_DOWN");
87 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "STOP_MOVE_HORIZONTALLY");
88 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "STOP_MOVE_HORIZONTALLY");
89 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "STOP_MOVE_VERTICALLY");
90 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "STOP_MOVE_VERTICALLY");
91
92 // zooming. To avoid confusion about which modifier key to use,
93 // we just add all keys left of the space bar
94 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK, false), "ZOOM_IN");
95 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.META_DOWN_MASK, false), "ZOOM_IN");
96 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK, false), "ZOOM_IN");
97 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK, false), "ZOOM_OUT");
98 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.META_DOWN_MASK, false), "ZOOM_OUT");
99 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK, false), "ZOOM_OUT");
100
101 // action mapping
102 actionMap.put("MOVE_RIGHT", new MoveXAction(1));
103 actionMap.put("MOVE_LEFT", new MoveXAction(-1));
104 actionMap.put("MOVE_UP", new MoveYAction(-1));
105 actionMap.put("MOVE_DOWN", new MoveYAction(1));
106 actionMap.put("STOP_MOVE_HORIZONTALLY", new MoveXAction(0));
107 actionMap.put("STOP_MOVE_VERTICALLY", new MoveYAction(0));
108 actionMap.put("ZOOM_IN", new ZoomInAction());
109 actionMap.put("ZOOM_OUT", new ZoomOutAction());
110 }
111
112 /**
113 * Start drawing the selection rectangle if it was the 1st button (left
114 * button)
115 */
116 @Override
117 public void mousePressed(MouseEvent e) {
118 if (e.getButton() == MouseEvent.BUTTON1) {
119 if (!iSizeButton.hit(e.getPoint())) {
120 iStartSelectionPoint = e.getPoint();
121 iEndSelectionPoint = e.getPoint();
122 }
123 }
124
125 }
126
127 public void mouseDragged(MouseEvent e) {
128 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK) {
129 if (iStartSelectionPoint != null) {
130 iEndSelectionPoint = e.getPoint();
131 iSlippyMapChooser.setSelection(iStartSelectionPoint, iEndSelectionPoint);
132 }
133 }
134 }
135
136 /**
137 * When dragging the map change the cursor back to it's pre-move cursor. If
138 * a double-click occurs center and zoom the map on the clicked location.
139 */
140 @Override
141 public void mouseReleased(MouseEvent e) {
142 if (e.getButton() == MouseEvent.BUTTON1) {
143
144 int sourceButton = iSourceButton.hit(e.getPoint());
145
146 if (iSizeButton.hit(e.getPoint())) {
147 iSizeButton.toggle();
148 iSlippyMapChooser.resizeSlippyMap();
149 } else if (sourceButton == SourceButton.HIDE_OR_SHOW) {
150 iSourceButton.toggle();
151 iSlippyMapChooser.repaint();
152
153 } else if (sourceButton == SourceButton.MAPNIK || sourceButton == SourceButton.OSMARENDER
154 || sourceButton == SourceButton.CYCLEMAP) {
155 iSlippyMapChooser.toggleMapSource(sourceButton);
156 } else {
157 if (e.getClickCount() == 1) {
158 iSlippyMapChooser.setSelection(iStartSelectionPoint, e.getPoint());
159
160 // reset the selections start and end
161 iEndSelectionPoint = null;
162 iStartSelectionPoint = null;
163 }
164 }
165
166 }
167 }
168
169 public void mouseMoved(MouseEvent e) {
170 }
171
172 private class MoveXAction extends AbstractAction {
173
174 int direction;
175
176 public MoveXAction(int direction) {
177 this.direction = direction;
178 }
179
180 public void actionPerformed(ActionEvent e) {
181 moveTask.setDirectionX(direction);
182 }
183 }
184
185 private class MoveYAction extends AbstractAction {
186
187 int direction;
188
189 public MoveYAction(int direction) {
190 this.direction = direction;
191 }
192
193 public void actionPerformed(ActionEvent e) {
194 moveTask.setDirectionY(direction);
195 }
196 }
197
198 /** Moves the map depending on which cursor keys are pressed (or not) */
199 private class MoveTask extends TimerTask {
200 /** The current x speed (pixels per timer interval) */
201 private double speedX = 1;
202
203 /** The current y speed (pixels per timer interval) */
204 private double speedY = 1;
205
206 /** The horizontal direction of movement, -1:left, 0:stop, 1:right */
207 private int directionX = 0;
208
209 /** The vertical direction of movement, -1:up, 0:stop, 1:down */
210 private int directionY = 0;
211
212 /**
213 * Indicated if <code>moveTask</code> is currently enabled (periodically
214 * executed via timer) or disabled
215 */
216 protected boolean scheduled = false;
217
218 protected void setDirectionX(int directionX) {
219 this.directionX = directionX;
220 updateScheduleStatus();
221 }
222
223 protected void setDirectionY(int directionY) {
224 this.directionY = directionY;
225 updateScheduleStatus();
226 }
227
228 private void updateScheduleStatus() {
229 boolean newMoveTaskState = !(directionX == 0 && directionY == 0);
230
231 if (newMoveTaskState != scheduled) {
232 scheduled = newMoveTaskState;
233 if (newMoveTaskState)
234 timer.schedule(this, 0, timerInterval);
235 else {
236 // We have to create a new instance because rescheduling a
237 // once canceled TimerTask is not possible
238 moveTask = new MoveTask();
239 cancel(); // Stop this TimerTask
240 }
241 }
242 }
243
244 @Override
245 public void run() {
246 // update the x speed
247 switch (directionX) {
248 case -1:
249 if (speedX > -1)
250 speedX = -1;
251 if (speedX > -1 * MAX_SPEED)
252 speedX -= ACCELERATION;
253 break;
254 case 0:
255 speedX = 0;
256 break;
257 case 1:
258 if (speedX < 1)
259 speedX = 1;
260 if (speedX < MAX_SPEED)
261 speedX += ACCELERATION;
262 break;
263 }
264
265 // update the y speed
266 switch (directionY) {
267 case -1:
268 if (speedY > -1)
269 speedY = -1;
270 if (speedY > -1 * MAX_SPEED)
271 speedY -= ACCELERATION;
272 break;
273 case 0:
274 speedY = 0;
275 break;
276 case 1:
277 if (speedY < 1)
278 speedY = 1;
279 if (speedY < MAX_SPEED)
280 speedY += ACCELERATION;
281 break;
282 }
283
284 // move the map
285 int moveX = (int) Math.floor(speedX);
286 int moveY = (int) Math.floor(speedY);
287 if (moveX != 0 || moveY != 0)
288 iSlippyMapChooser.moveMap(moveX, moveY);
289 }
290 }
291
292 private class ZoomInAction extends AbstractAction {
293
294 public void actionPerformed(ActionEvent e) {
295 iSlippyMapChooser.zoomIn();
296 }
297 }
298
299 private class ZoomOutAction extends AbstractAction {
300
301 public void actionPerformed(ActionEvent e) {
302 iSlippyMapChooser.zoomOut();
303 }
304 }
305
306}
Note: See TracBrowser for help on using the repository browser.