diff --git a/src/org/openstreetmap/josm/actions/mapmode/MapMode.java b/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
index 3ad0d71e27..22ac881173 100644
a
|
b
|
import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
|
20 | 20 | import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener; |
21 | 21 | import org.openstreetmap.josm.tools.ImageProvider; |
22 | 22 | import org.openstreetmap.josm.tools.Logging; |
| 23 | import org.openstreetmap.josm.tools.PlatformHook; |
| 24 | import org.openstreetmap.josm.tools.PlatformManager; |
23 | 25 | import org.openstreetmap.josm.tools.Shortcut; |
24 | 26 | |
25 | 27 | /** |
… |
… |
public abstract class MapMode extends JosmAction implements MouseListener, Mouse
|
33 | 35 | protected boolean ctrl; |
34 | 36 | protected boolean alt; |
35 | 37 | protected boolean shift; |
| 38 | /** |
| 39 | * {@code true} if the meta key was pressed (the "Windows" key or the Mac "Command" key) |
| 40 | * @since xxx |
| 41 | */ |
| 42 | protected boolean meta; |
| 43 | /** |
| 44 | * {@code true} if the platform specific menu key was pressed ("ctrl" on Linux/Windows, "cmd" on Mac) |
| 45 | * @see PlatformHook#getMenuShortcutKeyMaskEx() |
| 46 | * @since xxx |
| 47 | */ |
| 48 | protected boolean platformMenuShortcutKeyMask; |
36 | 49 | |
37 | 50 | /** |
38 | 51 | * Constructor for mapmodes without a menu |
… |
… |
public abstract class MapMode extends JosmAction implements MouseListener, Mouse
|
154 | 167 | } |
155 | 168 | |
156 | 169 | /** |
157 | | * Update internal ctrl, alt, shift mask from given extended modifiers mask. |
| 170 | * Update internal ctrl, alt, shift, meta mask from given extended modifiers mask. |
158 | 171 | * @param modifiers event extended modifiers mask |
159 | 172 | * @since 12517 |
160 | 173 | */ |
… |
… |
public abstract class MapMode extends JosmAction implements MouseListener, Mouse
|
162 | 175 | ctrl = (modifiers & InputEvent.CTRL_DOWN_MASK) != 0; |
163 | 176 | alt = (modifiers & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK)) != 0; |
164 | 177 | shift = (modifiers & InputEvent.SHIFT_DOWN_MASK) != 0; |
| 178 | meta = (modifiers & InputEvent.META_DOWN_MASK) != 0; |
| 179 | platformMenuShortcutKeyMask = (modifiers & PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()) != 0; |
165 | 180 | } |
166 | 181 | |
167 | 182 | /** |
diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
index 6983b3d585..97a7faa2f6 100644
a
|
b
|
package org.openstreetmap.josm.actions.mapmode;
|
3 | 3 | |
4 | 4 | import static org.openstreetmap.josm.gui.help.HelpUtil.ht; |
5 | 5 | import static org.openstreetmap.josm.tools.I18n.tr; |
| 6 | import static org.openstreetmap.josm.tools.I18n.trc; |
6 | 7 | import static org.openstreetmap.josm.tools.I18n.trn; |
7 | 8 | |
8 | 9 | import java.awt.Cursor; |
9 | 10 | import java.awt.Point; |
10 | 11 | import java.awt.Rectangle; |
| 12 | import java.awt.event.InputEvent; |
11 | 13 | import java.awt.event.KeyEvent; |
12 | 14 | import java.awt.event.MouseEvent; |
13 | 15 | import java.awt.geom.Point2D; |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
287 | 289 | return repaintIfRequired(newHighlight); |
288 | 290 | |
289 | 291 | // CTRL toggles selection, but if while dragging CTRL means merge |
290 | | final boolean isToggleMode = ctrl && !dragInProgress(); |
| 292 | final boolean isToggleMode = platformMenuShortcutKeyMask && !dragInProgress(); |
291 | 293 | if (c.isPresent() && (isToggleMode || !c.get().isSelected())) { |
292 | 294 | // only highlight primitives that will change the selection |
293 | 295 | // when clicked. I.e. don't highlight selected elements unless |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
317 | 319 | if (dragInProgress()) { |
318 | 320 | // only consider merge if ctrl is pressed and there are nodes in |
319 | 321 | // the selection that could be merged |
320 | | if (!ctrl || getLayerManager().getEditDataSet().getSelectedNodes().isEmpty()) { |
| 322 | if (!platformMenuShortcutKeyMask || getLayerManager().getEditDataSet().getSelectedNodes().isEmpty()) { |
321 | 323 | c = "move"; |
322 | 324 | break; |
323 | 325 | } |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
332 | 334 | c = (osm instanceof Way) ? "way" : c; |
333 | 335 | if (shift) { |
334 | 336 | c += "_add"; |
335 | | } else if (ctrl) { |
| 337 | } else if (platformMenuShortcutKeyMask) { |
336 | 338 | c += osm == null || osm.isSelected() ? "_rm" : "_add"; |
337 | 339 | } |
338 | 340 | break; |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
346 | 348 | if (lassoMode) { |
347 | 349 | c = "lasso"; |
348 | 350 | } else { |
349 | | c = "rect" + (shift ? "_add" : (ctrl && !PlatformManager.isPlatformOsx() ? "_rm" : "")); |
| 351 | if (shift) { |
| 352 | c = "rect_add"; |
| 353 | } else if (platformMenuShortcutKeyMask) { |
| 354 | c = "rect_rm"; |
| 355 | } else { |
| 356 | c = "rect"; |
| 357 | } |
350 | 358 | } |
351 | 359 | break; |
352 | 360 | } |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
408 | 416 | |
409 | 417 | // We don't want to change to draw tool if the user tries to (de)select |
410 | 418 | // stuff but accidentally clicks in an empty area when selection is empty |
411 | | cancelDrawMode = shift || ctrl; |
| 419 | cancelDrawMode = shift || platformMenuShortcutKeyMask; |
412 | 420 | didMouseDrag = false; |
413 | 421 | initialMoveThresholdExceeded = false; |
414 | 422 | mouseDownTime = System.currentTimeMillis(); |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
513 | 521 | if (mode == Mode.MOVE) { |
514 | 522 | // If ctrl is pressed we are in merge mode. Look for a nearby node, |
515 | 523 | // highlight it and adjust the cursor accordingly. |
516 | | final boolean canMerge = ctrl && !getLayerManager().getEditDataSet().getSelectedNodes().isEmpty(); |
| 524 | final boolean canMerge = platformMenuShortcutKeyMask && !getLayerManager().getEditDataSet().getSelectedNodes().isEmpty(); |
517 | 525 | final OsmPrimitive p = canMerge ? findNodeToMergeTo(e.getPoint()) : null; |
518 | 526 | boolean needsRepaint = removeHighlighting(); |
519 | 527 | if (p != null) { |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
669 | 677 | */ |
670 | 678 | private void determineMapMode(boolean hasSelectionNearby) { |
671 | 679 | if (getLayerManager().getEditDataSet() != null) { |
672 | | if (shift && ctrl) { |
| 680 | if (shift && platformMenuShortcutKeyMask) { |
673 | 681 | mode = Mode.ROTATE; |
674 | | } else if (alt && ctrl) { |
| 682 | } else if (alt && platformMenuShortcutKeyMask) { |
675 | 683 | mode = Mode.SCALE; |
676 | 684 | } else if (hasSelectionNearby || dragInProgress()) { |
677 | 685 | mode = Mode.MOVE; |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
860 | 868 | } else { |
861 | 869 | // if small number of elements were moved, |
862 | 870 | updateKeyModifiers(e); |
863 | | if (ctrl) mergePrims(e.getPoint()); |
| 871 | if (platformMenuShortcutKeyMask) mergePrims(e.getPoint()); |
864 | 872 | } |
865 | 873 | } |
866 | 874 | |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
978 | 986 | // Virtual Ways: if non-empty the cursor is above a virtual node. So don't highlight |
979 | 987 | // anything if about to drag the virtual node (i.e. !released) but continue if the |
980 | 988 | // cursor is only released above a virtual node by accident (i.e. released). See #7018 |
981 | | if (ds == null || (shift && ctrl) || (ctrl && !released) || (virtualManager.hasVirtualWaysToBeConstructed() && !released)) |
| 989 | if (ds == null || (shift && platformMenuShortcutKeyMask) || (platformMenuShortcutKeyMask && !released) |
| 990 | || (virtualManager.hasVirtualWaysToBeConstructed() && !released)) |
982 | 991 | return; |
983 | 992 | |
984 | 993 | if (!released) { |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
988 | 997 | shift |= ds.getSelected().containsAll(prims); |
989 | 998 | } |
990 | 999 | |
991 | | if (ctrl) { |
| 1000 | if (platformMenuShortcutKeyMask) { |
992 | 1001 | // Ctrl on an item toggles its selection status, |
993 | 1002 | // but Ctrl on an *area* just clears those items |
994 | 1003 | // out of the selection. |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
1017 | 1026 | |
1018 | 1027 | @Override |
1019 | 1028 | public String getModeHelpText() { |
| 1029 | // There needs to be a better way |
| 1030 | final String menuKey; |
| 1031 | switch (PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()) { |
| 1032 | case InputEvent.CTRL_DOWN_MASK: |
| 1033 | menuKey = trc("SelectAction help", "Ctrl"); |
| 1034 | break; |
| 1035 | case InputEvent.META_DOWN_MASK: |
| 1036 | menuKey = trc("SelectAction help", "Meta"); |
| 1037 | break; |
| 1038 | default: |
| 1039 | throw new IllegalStateException("Unknown platform menu shortcut key for " + PlatformManager.getPlatform().getOSDescription()); |
| 1040 | } |
| 1041 | final String type = this.lassoMode ? trc("SelectAction help", "lasso") : trc("SelectAction help", "rectangle"); |
1020 | 1042 | if (mouseDownButton == MouseEvent.BUTTON1 && mouseReleaseTime < mouseDownTime) { |
1021 | 1043 | if (mode == Mode.SELECT) |
1022 | | return tr("Release the mouse button to select the objects in the rectangle."); |
| 1044 | return tr("Release the mouse button to select the objects in the {0}.", type); |
1023 | 1045 | else if (mode == Mode.MOVE && (System.currentTimeMillis() - mouseDownTime >= initialMoveDelay)) { |
1024 | 1046 | final DataSet ds = getLayerManager().getEditDataSet(); |
1025 | 1047 | final boolean canMerge = ds != null && !ds.getSelectedNodes().isEmpty(); |
1026 | | final String mergeHelp = canMerge ? (' ' + tr("Ctrl to merge with nearest node.")) : ""; |
| 1048 | final String mergeHelp = canMerge ? (' ' + tr("{0} to merge with nearest node.", menuKey)) : ""; |
1027 | 1049 | return tr("Release the mouse button to stop moving.") + mergeHelp; |
1028 | 1050 | } else if (mode == Mode.ROTATE) |
1029 | 1051 | return tr("Release the mouse button to stop rotating."); |
1030 | 1052 | else if (mode == Mode.SCALE) |
1031 | 1053 | return tr("Release the mouse button to stop scaling."); |
1032 | 1054 | } |
1033 | | return tr("Move objects by dragging; Shift to add to selection (Ctrl to toggle); Shift-Ctrl to rotate selected; " + |
1034 | | "Alt-Ctrl to scale selected; or change selection"); |
| 1055 | return tr("Move objects by dragging; Shift to add to selection ({0} to toggle); Shift-{0} to rotate selected; " + |
| 1056 | "Alt-{0} to scale selected; or change selection", menuKey); |
1035 | 1057 | } |
1036 | 1058 | |
1037 | 1059 | @Override |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
1106 | 1128 | // special case: for cycle groups of 2, we can toggle to the |
1107 | 1129 | // true nearest primitive on mousePressed right away |
1108 | 1130 | if (cycleList.size() == 2 && !waitForMouseUpParameter) { |
1109 | | if (!(osm.equals(old) || osm.isNew() || ctrl)) { |
| 1131 | if (!(osm.equals(old) || osm.isNew() || platformMenuShortcutKeyMask)) { |
1110 | 1132 | cyclePrims = false; |
1111 | 1133 | osm = old; |
1112 | 1134 | } // else defer toggling to mouseRelease time in those cases: |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
1154 | 1176 | if (nxt.isSelected()) { |
1155 | 1177 | foundInDS = nxt; |
1156 | 1178 | // first selected primitive in cycleList is found |
1157 | | if (cyclePrims || ctrl) { |
| 1179 | if (cyclePrims || platformMenuShortcutKeyMask) { |
1158 | 1180 | ds.clearSelection(foundInDS); // deselect it |
1159 | 1181 | nxt = i.hasNext() ? i.next() : first; |
1160 | 1182 | // return next one in cycle list (last->first) |
… |
… |
public class SelectAction extends MapMode implements ModifierExListener, KeyPres
|
1165 | 1187 | } |
1166 | 1188 | |
1167 | 1189 | // if "no-alt-cycling" is enabled, Ctrl-Click arrives here. |
1168 | | if (ctrl) { |
| 1190 | if (platformMenuShortcutKeyMask) { |
1169 | 1191 | // a member of cycleList was found in the current dataset selection |
1170 | 1192 | if (foundInDS != null) { |
1171 | 1193 | // mouse was moved to a different selection group w/ a previous sel |
diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectLassoAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectLassoAction.java
index d37a850842..df615bbcde 100644
a
|
b
|
public class SelectLassoAction extends MapMode {
|
54 | 54 | public boolean layerIsSupported(Layer l) { |
55 | 55 | return MainApplication.getMap().mapModeSelect.layerIsSupported(l); |
56 | 56 | } |
| 57 | |
| 58 | @Override |
| 59 | public String getModeHelpText() { |
| 60 | return MainApplication.getMap().mapModeSelect.getModeHelpText(); |
| 61 | } |
57 | 62 | } |
diff --git a/src/org/openstreetmap/josm/gui/SelectionManager.java b/src/org/openstreetmap/josm/gui/SelectionManager.java
index 602f4491f9..0f9e4a0e92 100644
a
|
b
|
import org.openstreetmap.josm.data.osm.Way;
|
26 | 26 | import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; |
27 | 27 | import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable; |
28 | 28 | import org.openstreetmap.josm.tools.ColorHelper; |
| 29 | import org.openstreetmap.josm.tools.PlatformManager; |
29 | 30 | |
30 | 31 | /** |
31 | 32 | * Manages the selection of a rectangle or a lasso loop. Listening to left and right mouse button |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
185 | 186 | if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() > 1 && MainApplication.getLayerManager().getActiveDataSet() != null) { |
186 | 187 | SelectByInternalPointAction.performSelection(MainApplication.getMap().mapView.getEastNorth(e.getX(), e.getY()), |
187 | 188 | (e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0, |
188 | | (e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0); |
| 189 | (e.getModifiersEx() & PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()) != 0); |
189 | 190 | } else if (e.getButton() == MouseEvent.BUTTON1) { |
190 | 191 | mousePosStart = mousePos = e.getPoint(); |
191 | 192 | |