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

Last change on this file since 5694 was 5694, checked in by Don-vip, 11 years ago

fix #8394 - improve javadoc + remove deprecated debug method

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
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 javax.swing.Icon;
12
13import org.openstreetmap.josm.data.coor.EastNorth;
14import org.openstreetmap.josm.data.coor.LatLon;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
18import org.openstreetmap.josm.data.projection.Projections;
19import org.openstreetmap.josm.tools.ImageProvider;
20
21/**
22 * MoveCommand moves a set of OsmPrimitives along the map. It can be moved again
23 * to collect several MoveCommands into one command.
24 *
25 * @author imi
26 */
27public class MoveCommand extends Command {
28 /**
29 * The objects that should be moved.
30 */
31 private Collection<Node> nodes = new LinkedList<Node>();
32 /**
33 * Starting position, base command point, current (mouse-drag) position = startEN + (x,y) =
34 */
35 private EastNorth startEN;
36
37 /**
38 * x difference movement. Coordinates are in northern/eastern
39 */
40 private double x;
41 /**
42 * y difference movement. Coordinates are in northern/eastern
43 */
44 private double y;
45
46 private double backupX;
47 private double backupY;
48
49 /**
50 * Small helper for holding the interesting part of the old data state of the
51 * objects.
52 */
53 public static class OldState {
54 LatLon latlon;
55 EastNorth en; // cached EastNorth to be used for applying exact displacenment
56 boolean modified;
57 }
58
59 /**
60 * List of all old states of the objects.
61 */
62 private List<OldState> oldState = new LinkedList<OldState>();
63
64 public MoveCommand(OsmPrimitive osm, double x, double y) {
65 this(Collections.singleton(osm), x, y);
66 }
67
68 public MoveCommand(Node node, LatLon position) {
69 this(Collections.singleton((OsmPrimitive) node), node.getEastNorth().sub(Projections.project(position)));
70 }
71
72 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) {
73 this(objects, offset.getX(), offset.getY());
74 }
75
76 /**
77 * Create a MoveCommand and assign the initial object set and movement vector.
78 */
79 public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
80 super();
81 startEN = null;
82 saveCheckpoint(); // (0,0) displacement will be saved
83 this.x = x;
84 this.y = y;
85 this.nodes = AllNodesVisitor.getAllNodes(objects);
86 for (Node n : this.nodes) {
87 OldState os = new OldState();
88 os.latlon = new LatLon(n.getCoor());
89 os.en = n.getEastNorth();
90 os.modified = n.isModified();
91 oldState.add(os);
92 }
93 }
94
95 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
96 this(objects, end.getX()-start.getX(), end.getY()-start.getY());
97 startEN = start;
98 }
99
100 public MoveCommand(OsmPrimitive p, EastNorth start, EastNorth end) {
101 this(Collections.singleton(p), end.getX()-start.getX(), end.getY()-start.getY());
102 startEN = start;
103 }
104
105 /**
106 * Move the same set of objects again by the specified vector. The vectors
107 * are added together and so the resulting will be moved to the previous
108 * vector plus this one.
109 *
110 * The move is immediately executed and any undo will undo both vectors to
111 * the original position the objects had before first moving.
112 */
113 public void moveAgain(double x, double y) {
114 for (Node n : nodes) {
115 n.setEastNorth(n.getEastNorth().add(x, y));
116 }
117 this.x += x;
118 this.y += y;
119 }
120
121 public void moveAgainTo(double x, double y) {
122 moveAgain(x - this.x, y - this.y);
123 }
124
125 /**
126 * Change the displacement vector to have endpoint @param currentEN
127 * starting point is startEN
128 */
129 public void applyVectorTo(EastNorth currentEN) {
130 if (startEN == null)
131 return;
132 x = currentEN.getX() - startEN.getX();
133 y = currentEN.getY() - startEN.getY();
134 updateCoordinates();
135 }
136
137 /**
138 * Changes base point of movement
139 * @param newDraggedStartPoint - new starting point after movement (where user clicks to start new drag)
140 */
141 public void changeStartPoint(EastNorth newDraggedStartPoint) {
142 startEN = new EastNorth(newDraggedStartPoint.getX()-x, newDraggedStartPoint.getY()-y);
143 }
144
145 /**
146 * Save curent displacement to restore in case of some problems
147 */
148 public void saveCheckpoint() {
149 backupX = x;
150 backupY = y;
151 }
152
153 /**
154 * Restore old displacement in case of some problems
155 */
156 public void resetToCheckpoint() {
157 x = backupX;
158 y = backupY;
159 updateCoordinates();
160 }
161
162 private void updateCoordinates() {
163 Iterator<OldState> it = oldState.iterator();
164 for (Node n : nodes) {
165 OldState os = it.next();
166 n.setEastNorth(os.en.add(x, y));
167 }
168 }
169
170 @Override public boolean executeCommand() {
171 for (Node n : nodes) {
172 // in case #3892 happens again
173 if (n == null)
174 throw new AssertionError("null detected in node list");
175 if (n.getEastNorth() == null)
176 throw new AssertionError("null coordinates detected in node list");
177
178 n.setEastNorth(n.getEastNorth().add(x, y));
179 n.setModified(true);
180 }
181 return true;
182 }
183
184 @Override public void undoCommand() {
185 Iterator<OldState> it = oldState.iterator();
186 for (Node n : nodes) {
187 OldState os = it.next();
188 n.setCoor(os.latlon);
189 n.setModified(os.modified);
190 }
191 }
192
193 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
194 for (OsmPrimitive osm : nodes) {
195 modified.add(osm);
196 }
197 }
198
199 @Override
200 public String getDescriptionText() {
201 return trn("Move {0} node", "Move {0} nodes", nodes.size(), nodes.size());
202 }
203
204 @Override
205 public Icon getDescriptionIcon() {
206 return ImageProvider.get("data", "node");
207 }
208
209 @Override
210 public Collection<Node> getParticipatingPrimitives() {
211 return nodes;
212 }
213}
Note: See TracBrowser for help on using the repository browser.