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

Last change on this file since 12074 was 11713, checked in by Don-vip, 7 years ago

add Ant target to run PMD (only few rules for now), fix violations

  • Property svn:eol-style set to native
File size: 10.0 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[3]2package org.openstreetmap.josm.gui;
3
[1939]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[3]6import java.awt.Cursor;
[102]7import java.awt.Point;
[101]8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
[3]10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
12import java.awt.event.MouseWheelEvent;
[10432]13import java.util.ArrayList;
[11553]14import java.util.Optional;
[3]15
[101]16import javax.swing.AbstractAction;
17
[9824]18import org.openstreetmap.gui.jmapviewer.JMapViewer;
[1939]19import org.openstreetmap.josm.Main;
[7543]20import org.openstreetmap.josm.actions.mapmode.SelectAction;
[10000]21import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
22import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
[71]23import org.openstreetmap.josm.data.coor.EastNorth;
[9824]24import org.openstreetmap.josm.data.preferences.BooleanProperty;
[5472]25import org.openstreetmap.josm.tools.Destroyable;
[10432]26import org.openstreetmap.josm.tools.Pair;
[1939]27import org.openstreetmap.josm.tools.Shortcut;
[3]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 */
[10152]35public class MapMover extends MouseAdapter implements Destroyable {
[3]36
[9824]37 public static final BooleanProperty PROP_ZOOM_REVERSE_WHEEL = new BooleanProperty("zoom.reverse-wheel", false);
38
[11713]39 static {
40 new JMapViewerUpdater();
41 }
[9824]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
[10000]57 private static void updateJMapViewer() {
[9824]58 JMapViewer.zoomReverseWheel = MapMover.PROP_ZOOM_REVERSE_WHEEL.get();
59 }
60 }
61
[1169]62 private final class ZoomerAction extends AbstractAction {
63 private final String action;
[8510]64
[8836]65 ZoomerAction(String action) {
[10432]66 this(action, "MapMover.Zoomer." + action);
67 }
68
[10433]69 ZoomerAction(String action, String name) {
[1169]70 this.action = action;
[10432]71 putValue(NAME, name);
[101]72 }
[8510]73
[6084]74 @Override
[1169]75 public void actionPerformed(ActionEvent e) {
[6990]76 if (".".equals(action) || ",".equals(action)) {
[11553]77 Point mouse = Optional.ofNullable(nc.getMousePosition()).orElseGet(
78 () -> new Point((int) nc.getBounds().getCenterX(), (int) nc.getBounds().getCenterY()));
79 mouseWheelMoved(new MouseWheelEvent(nc, e.getID(), e.getWhen(), e.getModifiers(), mouse.x, mouse.y, 0, false,
80 MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, ",".equals(action) ? -1 : 1));
[1169]81 } else {
82 EastNorth center = nc.getCenter();
83 EastNorth newcenter = nc.getEastNorth(nc.getWidth()/2+nc.getWidth()/5, nc.getHeight()/2+nc.getHeight()/5);
[7012]84 switch(action) {
85 case "left":
[1722]86 nc.zoomTo(new EastNorth(2*center.east()-newcenter.east(), center.north()));
[7012]87 break;
88 case "right":
[1722]89 nc.zoomTo(new EastNorth(newcenter.east(), center.north()));
[7012]90 break;
91 case "up":
[1722]92 nc.zoomTo(new EastNorth(center.east(), 2*center.north()-newcenter.north()));
[7012]93 break;
94 case "down":
[1722]95 nc.zoomTo(new EastNorth(center.east(), newcenter.north()));
[7012]96 break;
[10217]97 default: // Do nothing
[7012]98 }
[1169]99 }
100 }
[101]101 }
102
[1169]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;
[3]112
[8840]113 private boolean movementInPlace;
[101]114
[10432]115 private final ArrayList<Pair<ZoomerAction, Shortcut>> registeredShortcuts = new ArrayList<>();
116
[1169]117 /**
[7543]118 * Constructs a new {@code MapMover}.
119 * @param navComp the navigatable component
[11713]120 * @since 11713
[1169]121 */
[11713]122 public MapMover(NavigatableComponent navComp) {
[1169]123 this.nc = navComp;
124 nc.addMouseListener(this);
125 nc.addMouseMotionListener(this);
126 nc.addMouseWheelListener(this);
[101]127
[10432]128 registerActionShortcut(new ZoomerAction("right"),
129 Shortcut.registerShortcut("system:movefocusright", tr("Map: {0}", tr("Move right")), KeyEvent.VK_RIGHT, Shortcut.CTRL));
[1023]130
[10432]131 registerActionShortcut(new ZoomerAction("left"),
132 Shortcut.registerShortcut("system:movefocusleft", tr("Map: {0}", tr("Move left")), KeyEvent.VK_LEFT, Shortcut.CTRL));
[1023]133
[10432]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));
[1023]138
[10432]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));
[1023]143
[10432]144 registerActionShortcut(new ZoomerAction(".", "MapMover.Zoomer.out"),
145 Shortcut.registerShortcut("view:zoomoutalternate", tr("Map: {0}", tr("Zoom out")), KeyEvent.VK_PERIOD, Shortcut.CTRL));
[1169]146 }
147 }
[101]148
[10432]149 private void registerActionShortcut(ZoomerAction action, Shortcut shortcut) {
150 Main.registerActionShortcut(action, shortcut);
151 registeredShortcuts.add(new Pair<>(action, shortcut));
152 }
153
[1169]154 /**
[7543]155 * If the right (and only the right) mouse button is pressed, move the map.
[1169]156 */
[6084]157 @Override
[1169]158 public void mouseDragged(MouseEvent e) {
159 int offMask = MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
[6989]160 int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
[7543]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)
[7590]164 || SelectAction.Mode.SELECT.equals(Main.map.mapModeSelect.getMode());
[7543]165 if (stdMovement || (macMovement && allowedMode)) {
[1169]166 if (mousePosMove == null)
167 startMovement(e);
168 EastNorth center = nc.getCenter();
169 EastNorth mouseCenter = nc.getEastNorth(e.getX(), e.getY());
[1722]170 nc.zoomTo(new EastNorth(
[1169]171 mousePosMove.east() + center.east() - mouseCenter.east(),
[1722]172 mousePosMove.north() + center.north() - mouseCenter.north()));
[6957]173 } else {
[1169]174 endMovement();
[6957]175 }
[1169]176 }
[3]177
[1169]178 /**
179 * Start the movement, if it was the 3rd button (right button).
180 */
[6957]181 @Override
182 public void mousePressed(MouseEvent e) {
[1169]183 int offMask = MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
[1939]184 int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
[10670]185 if ((e.getButton() == MouseEvent.BUTTON3 && (e.getModifiersEx() & offMask) == 0) ||
186 (Main.isPlatformOsx() && e.getModifiersEx() == macMouseMask)) {
[1169]187 startMovement(e);
[1939]188 }
[1169]189 }
[3]190
[1169]191 /**
192 * Change the cursor back to it's pre-move cursor.
193 */
[6957]194 @Override
195 public void mouseReleased(MouseEvent e) {
[10659]196 if (e.getButton() == MouseEvent.BUTTON3 || (Main.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1)) {
[1169]197 endMovement();
[1939]198 }
[1169]199 }
[3]200
[1169]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());
[3919]211 nc.setNewCursor(Cursor.MOVE_CURSOR, this);
[1169]212 }
[101]213
[1169]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;
[3919]221 nc.resetCursor(this);
[1169]222 mousePosMove = null;
223 }
[3]224
[1169]225 /**
226 * Zoom the map by 1/5th of current zoom per wheel-delta.
227 * @param e The wheel event.
228 */
[6084]229 @Override
[1169]230 public void mouseWheelMoved(MouseWheelEvent e) {
[9824]231 int rotation = PROP_ZOOM_REVERSE_WHEEL.get() ? -e.getWheelRotation() : e.getWheelRotation();
232 nc.zoomManyTimes(e.getX(), e.getY(), rotation);
[1169]233 }
[3]234
[1169]235 /**
[6957]236 * Emulates dragging on Mac OSX.
[1169]237 */
[6084]238 @Override
[1939]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?
[6957]244 if (Main.isPlatformOsx()) {
[1939]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
[5472]259 @Override
260 public void destroy() {
[10432]261 for (Pair<ZoomerAction, Shortcut> shortcut : registeredShortcuts) {
262 Main.unregisterActionShortcut(shortcut.a, shortcut.b);
[5472]263 }
264 }
[3]265}
Note: See TracBrowser for help on using the repository browser.