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

Last change on this file since 8342 was 8285, checked in by Don-vip, 9 years ago

fix sonar squid:S2039 - Member variable visibility should be specified

  • Property svn:eol-style set to native
File size: 6.9 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 */
69 public MoveCommand(Node node, LatLon position) {
70 this(Collections.singleton((OsmPrimitive) node), node.getEastNorth().sub(Projections.project(position)));
71 }
72
73 /**
74 * Constructs a new {@code MoveCommand} to move a collection of primitives.
75 * @param objects The primitives to move
76 * @param offset The movement vector
77 */
78 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) {
79 this(objects, offset.getX(), offset.getY());
80 }
81
82 /**
83 * Constructs a new {@code MoveCommand} and assign the initial object set and movement vector.
84 * @param objects The primitives to move
85 * @param x X difference movement. Coordinates are in northern/eastern
86 * @param y Y difference movement. Coordinates are in northern/eastern
87 */
88 public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
89 startEN = null;
90 saveCheckpoint(); // (0,0) displacement will be saved
91 this.x = x;
92 this.y = y;
93 this.nodes = AllNodesVisitor.getAllNodes(objects);
94 for (Node n : this.nodes) {
95 oldState.add(new OldNodeState(n));
96 }
97 }
98
99 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
100 this(objects, end.getX()-start.getX(), end.getY()-start.getY());
101 startEN = start;
102 }
103
104 public MoveCommand(OsmPrimitive p, EastNorth start, EastNorth end) {
105 this(Collections.singleton(p), end.getX()-start.getX(), end.getY()-start.getY());
106 startEN = start;
107 }
108
109 /**
110 * Move the same set of objects again by the specified vector. The vectors
111 * are added together and so the resulting will be moved to the previous
112 * vector plus this one.
113 *
114 * The move is immediately executed and any undo will undo both vectors to
115 * the original position the objects had before first moving.
116 *
117 * @param x X difference movement. Coordinates are in northern/eastern
118 * @param y Y difference movement. Coordinates are in northern/eastern
119 */
120 public void moveAgain(double x, double y) {
121 for (Node n : nodes) {
122 n.setEastNorth(n.getEastNorth().add(x, y));
123 }
124 this.x += x;
125 this.y += y;
126 }
127
128 public void moveAgainTo(double x, double y) {
129 moveAgain(x - this.x, y - this.y);
130 }
131
132 /**
133 * Change the displacement vector to have endpoint @param currentEN
134 * starting point is startEN
135 */
136 public void applyVectorTo(EastNorth currentEN) {
137 if (startEN == null)
138 return;
139 x = currentEN.getX() - startEN.getX();
140 y = currentEN.getY() - startEN.getY();
141 updateCoordinates();
142 }
143
144 /**
145 * Changes base point of movement
146 * @param newDraggedStartPoint - new starting point after movement (where user clicks to start new drag)
147 */
148 public void changeStartPoint(EastNorth newDraggedStartPoint) {
149 startEN = new EastNorth(newDraggedStartPoint.getX()-x, newDraggedStartPoint.getY()-y);
150 }
151
152 /**
153 * Save curent displacement to restore in case of some problems
154 */
155 public final void saveCheckpoint() {
156 backupX = x;
157 backupY = y;
158 }
159
160 /**
161 * Restore old displacement in case of some problems
162 */
163 public void resetToCheckpoint() {
164 x = backupX;
165 y = backupY;
166 updateCoordinates();
167 }
168
169 private void updateCoordinates() {
170 Iterator<OldNodeState> it = oldState.iterator();
171 for (Node n : nodes) {
172 OldNodeState os = it.next();
173 if (os.getEastNorth() != null) {
174 n.setEastNorth(os.getEastNorth().add(x, y));
175 }
176 }
177 }
178
179 @Override
180 public boolean executeCommand() {
181 for (Node n : nodes) {
182 // in case #3892 happens again
183 if (n == null)
184 throw new AssertionError("null detected in node list");
185 EastNorth en = n.getEastNorth();
186 if (en != null) {
187 n.setEastNorth(en.add(x, y));
188 n.setModified(true);
189 }
190 }
191 return true;
192 }
193
194 @Override
195 public void undoCommand() {
196 Iterator<OldNodeState> it = oldState.iterator();
197 for (Node n : nodes) {
198 OldNodeState os = it.next();
199 n.setCoor(os.getLatlon());
200 n.setModified(os.isModified());
201 }
202 }
203
204 @Override
205 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
206 for (OsmPrimitive osm : nodes) {
207 modified.add(osm);
208 }
209 }
210
211 @Override
212 public String getDescriptionText() {
213 return trn("Move {0} node", "Move {0} nodes", nodes.size(), nodes.size());
214 }
215
216 @Override
217 public Icon getDescriptionIcon() {
218 return ImageProvider.get("data", "node");
219 }
220
221 @Override
222 public Collection<Node> getParticipatingPrimitives() {
223 return nodes;
224 }
225}
Note: See TracBrowser for help on using the repository browser.