source: josm/trunk/src/org/openstreetmap/josm/command/MoveCommand.java@ 8855

Last change on this file since 8855 was 8549, checked in by bastiK, 9 years ago

applied #11628 - Added documentation to EastNorth, changed x - y = y.sub(x) to x.subtract(y) and minor code style improvements. (patch by michael2402, partially applied)

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.command;
3
4import static org.openstreetmap.josm.tools.I18n.trn;
5
6import java.util.Collection;
7import java.util.Collections;
8import java.util.Iterator;
9import java.util.LinkedList;
10import java.util.List;
11
12import javax.swing.Icon;
13
14import org.openstreetmap.josm.data.coor.EastNorth;
15import org.openstreetmap.josm.data.coor.LatLon;
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.OsmPrimitive;
18import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
19import org.openstreetmap.josm.data.projection.Projections;
20import org.openstreetmap.josm.tools.ImageProvider;
21
22/**
23 * MoveCommand moves a set of OsmPrimitives along the map. It can be moved again
24 * to collect several MoveCommands into one command.
25 *
26 * @author imi
27 */
28public class MoveCommand extends Command {
29 /**
30 * The objects that should be moved.
31 */
32 private Collection<Node> nodes = new LinkedList<>();
33 /**
34 * Starting position, base command point, current (mouse-drag) position = startEN + (x,y) =
35 */
36 private EastNorth startEN;
37
38 /**
39 * x difference movement. Coordinates are in northern/eastern
40 */
41 private double x;
42 /**
43 * y difference movement. Coordinates are in northern/eastern
44 */
45 private double y;
46
47 private double backupX;
48 private double backupY;
49
50 /**
51 * List of all old states of the objects.
52 */
53 private List<OldNodeState> oldState = new LinkedList<>();
54
55 /**
56 * Constructs a new {@code MoveCommand} to move a primitive.
57 * @param osm The primitive to move
58 * @param x X difference movement. Coordinates are in northern/eastern
59 * @param y Y difference movement. Coordinates are in northern/eastern
60 */
61 public MoveCommand(OsmPrimitive osm, double x, double y) {
62 this(Collections.singleton(osm), x, y);
63 }
64
65 /**
66 * Constructs a new {@code MoveCommand} to move a node.
67 * @param node The node to move
68 * @param position The new location (lat/lon)
69 */
70 public MoveCommand(Node node, LatLon position) {
71 this(Collections.singleton((OsmPrimitive) node), Projections.project(position).subtract(node.getEastNorth()));
72 }
73
74 /**
75 * Constructs a new {@code MoveCommand} to move a collection of primitives.
76 * @param objects The primitives to move
77 * @param offset The movement vector
78 */
79 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) {
80 this(objects, offset.getX(), offset.getY());
81 }
82
83 /**
84 * Constructs a new {@code MoveCommand} and assign the initial object set and movement vector.
85 * @param objects The primitives to move
86 * @param x X difference movement. Coordinates are in northern/eastern
87 * @param y Y difference movement. Coordinates are in northern/eastern
88 */
89 public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
90 startEN = null;
91 saveCheckpoint(); // (0,0) displacement will be saved
92 this.x = x;
93 this.y = y;
94 this.nodes = AllNodesVisitor.getAllNodes(objects);
95 for (Node n : this.nodes) {
96 oldState.add(new OldNodeState(n));
97 }
98 }
99
100 /**
101 * Constructs a new {@code MoveCommand} to move a collection of primitives.
102 * @param objects The primitives to move
103 * @param start The starting position (northern/eastern)
104 * @param end The ending position (northern/eastern)
105 */
106 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
107 this(objects, end.getX()-start.getX(), end.getY()-start.getY());
108 startEN = start;
109 }
110
111 /**
112 * Constructs a new {@code MoveCommand} to move a primitive.
113 * @param p The primitive to move
114 * @param start The starting position (northern/eastern)
115 * @param end The ending position (northern/eastern)
116 */
117 public MoveCommand(OsmPrimitive p, EastNorth start, EastNorth end) {
118 this(Collections.singleton(p), end.getX()-start.getX(), end.getY()-start.getY());
119 startEN = start;
120 }
121
122 /**
123 * Move the same set of objects again by the specified vector. The vectors
124 * are added together and so the resulting will be moved to the previous
125 * vector plus this one.
126 *
127 * The move is immediately executed and any undo will undo both vectors to
128 * the original position the objects had before first moving.
129 *
130 * @param x X difference movement. Coordinates are in northern/eastern
131 * @param y Y difference movement. Coordinates are in northern/eastern
132 */
133 public void moveAgain(double x, double y) {
134 for (Node n : nodes) {
135 n.setEastNorth(n.getEastNorth().add(x, y));
136 }
137 this.x += x;
138 this.y += y;
139 }
140
141 public void moveAgainTo(double x, double y) {
142 moveAgain(x - this.x, y - this.y);
143 }
144
145 /**
146 * Change the displacement vector to have endpoint @param currentEN
147 * starting point is startEN
148 */
149 public void applyVectorTo(EastNorth currentEN) {
150 if (startEN == null)
151 return;
152 x = currentEN.getX() - startEN.getX();
153 y = currentEN.getY() - startEN.getY();
154 updateCoordinates();
155 }
156
157 /**
158 * Changes base point of movement
159 * @param newDraggedStartPoint - new starting point after movement (where user clicks to start new drag)
160 */
161 public void changeStartPoint(EastNorth newDraggedStartPoint) {
162 startEN = new EastNorth(newDraggedStartPoint.getX()-x, newDraggedStartPoint.getY()-y);
163 }
164
165 /**
166 * Save curent displacement to restore in case of some problems
167 */
168 public final void saveCheckpoint() {
169 backupX = x;
170 backupY = y;
171 }
172
173 /**
174 * Restore old displacement in case of some problems
175 */
176 public void resetToCheckpoint() {
177 x = backupX;
178 y = backupY;
179 updateCoordinates();
180 }
181
182 private void updateCoordinates() {
183 Iterator<OldNodeState> it = oldState.iterator();
184 for (Node n : nodes) {
185 OldNodeState os = it.next();
186 if (os.getEastNorth() != null) {
187 n.setEastNorth(os.getEastNorth().add(x, y));
188 }
189 }
190 }
191
192 @Override
193 public boolean executeCommand() {
194 for (Node n : nodes) {
195 // in case #3892 happens again
196 if (n == null)
197 throw new AssertionError("null detected in node list");
198 EastNorth en = n.getEastNorth();
199 if (en != null) {
200 n.setEastNorth(en.add(x, y));
201 n.setModified(true);
202 }
203 }
204 return true;
205 }
206
207 @Override
208 public void undoCommand() {
209 Iterator<OldNodeState> it = oldState.iterator();
210 for (Node n : nodes) {
211 OldNodeState os = it.next();
212 n.setCoor(os.getLatlon());
213 n.setModified(os.isModified());
214 }
215 }
216
217 @Override
218 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
219 for (OsmPrimitive osm : nodes) {
220 modified.add(osm);
221 }
222 }
223
224 @Override
225 public String getDescriptionText() {
226 return trn("Move {0} node", "Move {0} nodes", nodes.size(), nodes.size());
227 }
228
229 @Override
230 public Icon getDescriptionIcon() {
231 return ImageProvider.get("data", "node");
232 }
233
234 @Override
235 public Collection<Node> getParticipatingPrimitives() {
236 return nodes;
237 }
238
239 @Override
240 public int hashCode() {
241 final int prime = 31;
242 int result = super.hashCode();
243 long temp;
244 temp = Double.doubleToLongBits(backupX);
245 result = prime * result + (int) (temp ^ (temp >>> 32));
246 temp = Double.doubleToLongBits(backupY);
247 result = prime * result + (int) (temp ^ (temp >>> 32));
248 result = prime * result + ((nodes == null) ? 0 : nodes.hashCode());
249 result = prime * result + ((oldState == null) ? 0 : oldState.hashCode());
250 result = prime * result + ((startEN == null) ? 0 : startEN.hashCode());
251 temp = Double.doubleToLongBits(x);
252 result = prime * result + (int) (temp ^ (temp >>> 32));
253 temp = Double.doubleToLongBits(y);
254 result = prime * result + (int) (temp ^ (temp >>> 32));
255 return result;
256 }
257
258 @Override
259 public boolean equals(Object obj) {
260 if (this == obj)
261 return true;
262 if (!super.equals(obj))
263 return false;
264 if (getClass() != obj.getClass())
265 return false;
266 MoveCommand other = (MoveCommand) obj;
267 if (Double.doubleToLongBits(backupX) != Double.doubleToLongBits(other.backupX))
268 return false;
269 if (Double.doubleToLongBits(backupY) != Double.doubleToLongBits(other.backupY))
270 return false;
271 if (nodes == null) {
272 if (other.nodes != null)
273 return false;
274 } else if (!nodes.equals(other.nodes))
275 return false;
276 if (oldState == null) {
277 if (other.oldState != null)
278 return false;
279 } else if (!oldState.equals(other.oldState))
280 return false;
281 if (startEN == null) {
282 if (other.startEN != null)
283 return false;
284 } else if (!startEN.equals(other.startEN))
285 return false;
286 if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
287 return false;
288 if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
289 return false;
290 return true;
291 }
292}
Note: See TracBrowser for help on using the repository browser.