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

Last change on this file since 9827 was 9371, checked in by simon04, 8 years ago

Java 7: use Objects.equals and Objects.hash

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