source: josm/trunk/src/org/openstreetmap/josm/gui/MapMover.java@ 10308

Last change on this file since 10308 was 10217, checked in by Don-vip, 8 years ago

findbugs - SF_SWITCH_NO_DEFAULT + various sonar fixes

  • Property svn:eol-style set to native
File size: 11.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Cursor;
7import java.awt.Point;
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
12import java.awt.event.MouseWheelEvent;
13
14import javax.swing.AbstractAction;
15import javax.swing.ActionMap;
16import javax.swing.InputMap;
17import javax.swing.JComponent;
18import javax.swing.JPanel;
19import javax.swing.KeyStroke;
20
21import org.openstreetmap.gui.jmapviewer.JMapViewer;
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.actions.mapmode.SelectAction;
24import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
25import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
26import org.openstreetmap.josm.data.coor.EastNorth;
27import org.openstreetmap.josm.data.preferences.BooleanProperty;
28import org.openstreetmap.josm.tools.Destroyable;
29import org.openstreetmap.josm.tools.Shortcut;
30
31/**
32 * Enables moving of the map by holding down the right mouse button and drag
33 * the mouse. Also, enables zooming by the mouse wheel.
34 *
35 * @author imi
36 */
37public class MapMover extends MouseAdapter implements Destroyable {
38
39 public static final BooleanProperty PROP_ZOOM_REVERSE_WHEEL = new BooleanProperty("zoom.reverse-wheel", false);
40
41 private static final JMapViewerUpdater jMapViewerUpdater = new JMapViewerUpdater();
42
43 private static class JMapViewerUpdater implements PreferenceChangedListener {
44
45 JMapViewerUpdater() {
46 Main.pref.addPreferenceChangeListener(this);
47 updateJMapViewer();
48 }
49
50 @Override
51 public void preferenceChanged(PreferenceChangeEvent e) {
52 if (MapMover.PROP_ZOOM_REVERSE_WHEEL.getKey().equals(e.getKey())) {
53 updateJMapViewer();
54 }
55 }
56
57 private static void updateJMapViewer() {
58 JMapViewer.zoomReverseWheel = MapMover.PROP_ZOOM_REVERSE_WHEEL.get();
59 }
60 }
61
62 private final class ZoomerAction extends AbstractAction {
63 private final String action;
64
65 ZoomerAction(String action) {
66 this.action = action;
67 }
68
69 @Override
70 public void actionPerformed(ActionEvent e) {
71 if (".".equals(action) || ",".equals(action)) {
72 Point mouse = nc.getMousePosition();
73 if (mouse == null)
74 mouse = new Point((int) nc.getBounds().getCenterX(), (int) nc.getBounds().getCenterY());
75 MouseWheelEvent we = new MouseWheelEvent(nc, e.getID(), e.getWhen(), e.getModifiers(), mouse.x, mouse.y, 0, false,
76 MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, ",".equals(action) ? -1 : 1);
77 mouseWheelMoved(we);
78 } else {
79 EastNorth center = nc.getCenter();
80 EastNorth newcenter = nc.getEastNorth(nc.getWidth()/2+nc.getWidth()/5, nc.getHeight()/2+nc.getHeight()/5);
81 switch(action) {
82 case "left":
83 nc.zoomTo(new EastNorth(2*center.east()-newcenter.east(), center.north()));
84 break;
85 case "right":
86 nc.zoomTo(new EastNorth(newcenter.east(), center.north()));
87 break;
88 case "up":
89 nc.zoomTo(new EastNorth(center.east(), 2*center.north()-newcenter.north()));
90 break;
91 case "down":
92 nc.zoomTo(new EastNorth(center.east(), newcenter.north()));
93 break;
94 default: // Do nothing
95 }
96 }
97 }
98 }
99
100 /**
101 * The point in the map that was the under the mouse point
102 * when moving around started.
103 */
104 private EastNorth mousePosMove;
105 /**
106 * The map to move around.
107 */
108 private final NavigatableComponent nc;
109 private final JPanel contentPane;
110
111 private boolean movementInPlace;
112
113 /**
114 * Constructs a new {@code MapMover}.
115 * @param navComp the navigatable component
116 * @param contentPane the content pane
117 */
118 public MapMover(NavigatableComponent navComp, JPanel contentPane) {
119 this.nc = navComp;
120 this.contentPane = contentPane;
121 nc.addMouseListener(this);
122 nc.addMouseMotionListener(this);
123 nc.addMouseWheelListener(this);
124
125 if (contentPane != null) {
126 // CHECKSTYLE.OFF: LineLength
127 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
128 Shortcut.registerShortcut("system:movefocusright", tr("Map: {0}", tr("Move right")), KeyEvent.VK_RIGHT, Shortcut.CTRL).getKeyStroke(),
129 "MapMover.Zoomer.right");
130 contentPane.getActionMap().put("MapMover.Zoomer.right", new ZoomerAction("right"));
131
132 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
133 Shortcut.registerShortcut("system:movefocusleft", tr("Map: {0}", tr("Move left")), KeyEvent.VK_LEFT, Shortcut.CTRL).getKeyStroke(),
134 "MapMover.Zoomer.left");
135 contentPane.getActionMap().put("MapMover.Zoomer.left", new ZoomerAction("left"));
136
137 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
138 Shortcut.registerShortcut("system:movefocusup", tr("Map: {0}", tr("Move up")), KeyEvent.VK_UP, Shortcut.CTRL).getKeyStroke(),
139 "MapMover.Zoomer.up");
140 contentPane.getActionMap().put("MapMover.Zoomer.up", new ZoomerAction("up"));
141
142 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
143 Shortcut.registerShortcut("system:movefocusdown", tr("Map: {0}", tr("Move down")), KeyEvent.VK_DOWN, Shortcut.CTRL).getKeyStroke(),
144 "MapMover.Zoomer.down");
145 contentPane.getActionMap().put("MapMover.Zoomer.down", new ZoomerAction("down"));
146 // CHECKSTYLE.ON: LineLength
147
148 // see #10592 - Disable these alternate shortcuts on OS X because of conflict with system shortcut
149 if (!Main.isPlatformOsx()) {
150 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
151 Shortcut.registerShortcut("view:zoominalternate",
152 tr("Map: {0}", tr("Zoom in")), KeyEvent.VK_COMMA, Shortcut.CTRL).getKeyStroke(),
153 "MapMover.Zoomer.in");
154 contentPane.getActionMap().put("MapMover.Zoomer.in", new ZoomerAction(","));
155
156 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
157 Shortcut.registerShortcut("view:zoomoutalternate",
158 tr("Map: {0}", tr("Zoom out")), KeyEvent.VK_PERIOD, Shortcut.CTRL).getKeyStroke(),
159 "MapMover.Zoomer.out");
160 contentPane.getActionMap().put("MapMover.Zoomer.out", new ZoomerAction("."));
161 }
162 }
163 }
164
165 /**
166 * If the right (and only the right) mouse button is pressed, move the map.
167 */
168 @Override
169 public void mouseDragged(MouseEvent e) {
170 int offMask = MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
171 int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
172 boolean stdMovement = (e.getModifiersEx() & (MouseEvent.BUTTON3_DOWN_MASK | offMask)) == MouseEvent.BUTTON3_DOWN_MASK;
173 boolean macMovement = Main.isPlatformOsx() && e.getModifiersEx() == macMouseMask;
174 boolean allowedMode = !Main.map.mapModeSelect.equals(Main.map.mapMode)
175 || SelectAction.Mode.SELECT.equals(Main.map.mapModeSelect.getMode());
176 if (stdMovement || (macMovement && allowedMode)) {
177 if (mousePosMove == null)
178 startMovement(e);
179 EastNorth center = nc.getCenter();
180 EastNorth mouseCenter = nc.getEastNorth(e.getX(), e.getY());
181 nc.zoomTo(new EastNorth(
182 mousePosMove.east() + center.east() - mouseCenter.east(),
183 mousePosMove.north() + center.north() - mouseCenter.north()));
184 } else {
185 endMovement();
186 }
187 }
188
189 /**
190 * Start the movement, if it was the 3rd button (right button).
191 */
192 @Override
193 public void mousePressed(MouseEvent e) {
194 int offMask = MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
195 int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
196 if (e.getButton() == MouseEvent.BUTTON3 && (e.getModifiersEx() & offMask) == 0 ||
197 Main.isPlatformOsx() && e.getModifiersEx() == macMouseMask) {
198 startMovement(e);
199 }
200 }
201
202 /**
203 * Change the cursor back to it's pre-move cursor.
204 */
205 @Override
206 public void mouseReleased(MouseEvent e) {
207 if (e.getButton() == MouseEvent.BUTTON3 || Main.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1) {
208 endMovement();
209 }
210 }
211
212 /**
213 * Start movement by setting a new cursor and remember the current mouse
214 * position.
215 * @param e The mouse event that leat to the movement from.
216 */
217 private void startMovement(MouseEvent e) {
218 if (movementInPlace)
219 return;
220 movementInPlace = true;
221 mousePosMove = nc.getEastNorth(e.getX(), e.getY());
222 nc.setNewCursor(Cursor.MOVE_CURSOR, this);
223 }
224
225 /**
226 * End the movement. Setting back the cursor and clear the movement variables
227 */
228 private void endMovement() {
229 if (!movementInPlace)
230 return;
231 movementInPlace = false;
232 nc.resetCursor(this);
233 mousePosMove = null;
234 }
235
236 /**
237 * Zoom the map by 1/5th of current zoom per wheel-delta.
238 * @param e The wheel event.
239 */
240 @Override
241 public void mouseWheelMoved(MouseWheelEvent e) {
242 int rotation = PROP_ZOOM_REVERSE_WHEEL.get() ? -e.getWheelRotation() : e.getWheelRotation();
243 nc.zoomManyTimes(e.getX(), e.getY(), rotation);
244 }
245
246 /**
247 * Emulates dragging on Mac OSX.
248 */
249 @Override
250 public void mouseMoved(MouseEvent e) {
251 if (!movementInPlace)
252 return;
253 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired.
254 // Is only the selected mouse button pressed?
255 if (Main.isPlatformOsx()) {
256 if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) {
257 if (mousePosMove == null) {
258 startMovement(e);
259 }
260 EastNorth center = nc.getCenter();
261 EastNorth mouseCenter = nc.getEastNorth(e.getX(), e.getY());
262 nc.zoomTo(new EastNorth(mousePosMove.east() + center.east() - mouseCenter.east(), mousePosMove.north()
263 + center.north() - mouseCenter.north()));
264 } else {
265 endMovement();
266 }
267 }
268 }
269
270 @Override
271 public void destroy() {
272 if (this.contentPane != null) {
273 InputMap inputMap = contentPane.getInputMap();
274 KeyStroke[] inputKeys = inputMap.keys();
275 if (inputKeys != null) {
276 for (KeyStroke key : inputKeys) {
277 Object binding = inputMap.get(key);
278 if (binding instanceof String && ((String) binding).startsWith("MapMover.")) {
279 inputMap.remove(key);
280 }
281 }
282 }
283 ActionMap actionMap = contentPane.getActionMap();
284 Object[] actionsKeys = actionMap.keys();
285 if (actionsKeys != null) {
286 for (Object key : actionsKeys) {
287 if (key instanceof String && ((String) key).startsWith("MapMover.")) {
288 actionMap.remove(key);
289 }
290 }
291 }
292 }
293 }
294}
Note: See TracBrowser for help on using the repository browser.