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

Last change on this file since 17356 was 17333, checked in by Don-vip, 4 years ago

see #20129 - Fix typos and misspellings in the code (patch by gaben)

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