source: josm/trunk/src/org/openstreetmap/josm/actions/MoveAction.java@ 17534

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

fix #18962 - introduce DataSet.update to avoid repetitive begin/endUpdate statements

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.util.Collection;
10import java.util.Locale;
11
12import javax.swing.JOptionPane;
13
14import org.openstreetmap.josm.command.MoveCommand;
15import org.openstreetmap.josm.data.UndoRedoHandler;
16import org.openstreetmap.josm.data.coor.EastNorth;
17import org.openstreetmap.josm.data.osm.DataSet;
18import org.openstreetmap.josm.data.osm.Node;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
21import org.openstreetmap.josm.gui.MainApplication;
22import org.openstreetmap.josm.gui.MapView;
23import org.openstreetmap.josm.tools.Shortcut;
24
25/**
26 * Moves the selection
27 *
28 * @author Frederik Ramm
29 */
30public class MoveAction extends JosmAction {
31
32 /**
33 * Move direction.
34 */
35 public enum Direction {
36 /** Move up */
37 UP(tr("up"), "up", KeyEvent.VK_UP),
38 /* SHORTCUT(Move objects up, core:moveup, SHIFT, UP) */
39 /** Move left */
40 LEFT(tr("left"), "previous", KeyEvent.VK_LEFT),
41 /* SHORTCUT(Move objects left, core:moveleft, SHIFT, LEFT) */
42 /** Move right */
43 RIGHT(tr("right"), "next", KeyEvent.VK_RIGHT),
44 /* SHORTCUT(Move objects right, core:moveright, SHIFT, RIGHT) */
45 /** Move down */
46 DOWN(tr("down"), "down", KeyEvent.VK_DOWN);
47 /* SHORTCUT(Move objects down, core:movedown, SHIFT, DOWN) */
48
49 private final String localizedName;
50 private final String icon;
51 private final int shortcutKey;
52
53 Direction(String localizedName, String icon, int shortcutKey) {
54 this.localizedName = localizedName;
55 this.icon = icon;
56 this.shortcutKey = shortcutKey;
57 }
58
59 String getId() {
60 return name().toLowerCase(Locale.ENGLISH);
61 }
62
63 String getLocalizedName() {
64 return localizedName;
65 }
66
67 String getIcon() {
68 return "dialogs/" + icon;
69 }
70
71 String getToolbarName() {
72 return "action/move/" + getId();
73 }
74
75 int getShortcutKey() {
76 return shortcutKey;
77 }
78
79 Shortcut getShortcut() {
80 return Shortcut.registerShortcut(/* NO-SHORTCUT - adapt definition above when modified */
81 "core:move" + getId(), tr("Move objects {0}", getLocalizedName()), getShortcutKey(), Shortcut.SHIFT);
82 }
83 }
84
85 private final Direction myDirection;
86
87 /**
88 * Constructs a new {@code MoveAction}.
89 * @param dir direction
90 */
91 public MoveAction(Direction dir) {
92 super(tr("Move {0}", dir.getLocalizedName()), dir.getIcon(),
93 tr("Moves Objects {0}", dir.getLocalizedName()),
94 dir.getShortcut(), true, dir.getToolbarName(), true);
95 myDirection = dir;
96 setHelpId(ht("/Action/Move"));
97 }
98
99 /**
100 * Find out how many "real" units the objects have to be moved in order to achieve an 1-pixel movement
101 * @param mapView map view
102 * @return move offset
103 */
104 private EastNorth getOffset(MapView mapView) {
105 EastNorth en1 = mapView.getEastNorth(100, 100);
106 EastNorth en2 = mapView.getEastNorth(101, 101);
107
108 double distx = en2.east() - en1.east();
109 double disty = en2.north() - en1.north();
110
111 switch (myDirection) {
112 case UP:
113 distx = 0;
114 disty = -disty;
115 break;
116 case DOWN:
117 distx = 0;
118 break;
119 case LEFT:
120 disty = 0;
121 distx = -distx;
122 break;
123 default:
124 disty = 0;
125 }
126
127 return new EastNorth(distx, disty);
128 }
129
130 @Override
131 public void actionPerformed(ActionEvent event) {
132 DataSet ds = getLayerManager().getEditDataSet();
133
134 if (!MainApplication.isDisplayingMapView() || ds == null)
135 return;
136
137 MapView mapView = MainApplication.getMap().mapView;
138 final EastNorth dist = getOffset(mapView);
139
140 Collection<OsmPrimitive> selection = ds.getSelected();
141 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
142
143 MoveCommand cmd = ds.update(c -> {
144 MoveCommand moveCmd;
145 if (c instanceof MoveCommand && ds.equals(c.getAffectedDataSet())
146 && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
147 moveCmd = (MoveCommand) c;
148 moveCmd.moveAgain(dist.east(), dist.north());
149 } else {
150 moveCmd = new MoveCommand(ds, selection, dist.east(), dist.north());
151 UndoRedoHandler.getInstance().add(moveCmd);
152 }
153 return moveCmd;
154 }, UndoRedoHandler.getInstance().getLastCommand());
155
156 for (Node n : affectedNodes) {
157 if (n.isLatLonKnown() && n.isOutSideWorld()) {
158 // Revert move
159 cmd.moveAgain(-dist.east(), -dist.north());
160 JOptionPane.showMessageDialog(
161 MainApplication.getMainFrame(),
162 tr("Cannot move objects outside of the world."),
163 tr("Warning"),
164 JOptionPane.WARNING_MESSAGE
165 );
166 return;
167 }
168 }
169
170 mapView.repaint();
171 }
172
173 @Override
174 protected void updateEnabledState() {
175 updateEnabledStateOnCurrentSelection();
176 }
177
178 @Override
179 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
180 updateEnabledStateOnModifiableSelection(selection);
181 }
182}
Note: See TracBrowser for help on using the repository browser.