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

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

see #12472 - fix "OperatorPrecedence" warnings

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