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

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

sonar - fix various issues

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