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

Last change on this file since 8283 was 7606, checked in by Don-vip, 10 years ago

fix #10592 - fix other shortcuts

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