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

Last change on this file since 6989 was 6989, checked in by bastiK, 10 years ago

see #josm9897 - Move map no longer works on OSX

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