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

Last change on this file since 12851 was 12846, checked in by bastiK, 7 years ago

see #15229 - use Config.getPref() wherever possible

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