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

Last change on this file since 5674 was 5418, checked in by akks, 12 years ago

fix #7082 (?) - CTRL-drag in selection mode problem, see #7888: SelectAction and MoveCommand rework

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