Changeset 1856 in josm for trunk/src/org/openstreetmap/josm/command
- Timestamp:
- 2009-07-26T17:03:00+02:00 (14 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/command
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/command/Command.java
r1814 r1856 53 53 this.layer = Main.map.mapView.getEditLayer(); 54 54 } 55 56 /** 57 * Creates a new command in the context of a specific data layer 58 * 59 * @param layer the data layer 60 */ 61 public Command(OsmDataLayer layer) { 62 this.layer = layer; 63 } 64 55 65 /** 56 66 * Executes the command on the dataset. This implementation will remember all -
trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
r1838 r1856 34 34 import org.openstreetmap.josm.gui.ExtendedDialog; 35 35 import org.openstreetmap.josm.gui.PrimitiveNameFormatter; 36 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 36 37 import org.openstreetmap.josm.tools.ImageProvider; 37 38 … … 63 64 } 64 65 65 @Override public boolean executeCommand() { 66 /** 67 * Constructor for a single data item. Use the collection constructor to delete multiple 68 * objects. 69 * 70 * @param layer the layer context for deleting this primitive 71 * @param data the primitive to delete 72 */ 73 public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) { 74 super(layer); 75 this.toDelete = Collections.singleton(data); 76 } 77 78 /** 79 * Constructor for a collection of data to be deleted in the context of 80 * a specific layer 81 * 82 * @param layer the layer context for deleting these primitives 83 * @param data the primitives to delete 84 */ 85 public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) { 86 super(layer); 87 this.toDelete = data; 88 } 89 90 @Override 91 public boolean executeCommand() { 66 92 super.executeCommand(); 67 93 for (OsmPrimitive osm : toDelete) { … … 71 97 } 72 98 73 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, 99 @Override 100 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, 74 101 Collection<OsmPrimitive> added) { 75 102 deleted.addAll(toDelete); 76 103 } 77 104 78 @Override public MutableTreeNode description() { 105 @Override 106 public MutableTreeNode description() { 79 107 if (toDelete.size() == 1) { 80 108 OsmPrimitive primitive = toDelete.iterator().next(); 81 return new DefaultMutableTreeNode( 82 new JLabel( 83 tr("Delete {1} {0}", 84 new PrimitiveNameFormatter().getName(primitive), 85 OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular() 86 ), 87 ImageProvider.get(OsmPrimitiveType.from(primitive)), 88 JLabel.HORIZONTAL)); 109 return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", new PrimitiveNameFormatter() 110 .getName(primitive), OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular()), 111 ImageProvider.get(OsmPrimitiveType.from(primitive)), JLabel.HORIZONTAL)); 89 112 } 90 113 … … 106 129 cname, cnamem, toDelete.size())), ImageProvider.get("data", apiname), JLabel.HORIZONTAL)); 107 130 for (OsmPrimitive osm : toDelete) { 108 root.add(new DefaultMutableTreeNode( 109 new JLabel( 110 new PrimitiveNameFormatter().getName(osm), 111 ImageProvider.get(OsmPrimitiveType.from(osm)), 112 JLabel.HORIZONTAL) 113 ) 114 ); 131 root.add(new DefaultMutableTreeNode(new JLabel(new PrimitiveNameFormatter().getName(osm), ImageProvider 132 .get(OsmPrimitiveType.from(osm)), JLabel.HORIZONTAL))); 115 133 } 116 134 return root; … … 119 137 /** 120 138 * Delete the primitives and everything they reference. 121 * 139 * 122 140 * If a node is deleted, the node and all ways and relations the node is part of are deleted as 123 141 * well. 124 * 142 * 125 143 * If a way is deleted, all relations the way is member of are also deleted. 126 * 144 * 127 145 * If a way is deleted, only the way and no nodes are deleted. 128 * 146 * 129 147 * @param selection The list of all object to be deleted. 130 148 * @return command A command to perform the deletions, or null of there is nothing to delete. 131 149 */ 132 public static Command deleteWithReferences( Collection<? extends OsmPrimitive> selection) {133 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor( Main.main.getCurrentDataSet());150 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) { 151 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data); 134 152 for (OsmPrimitive osm : selection) { 135 153 osm.visit(v); … … 138 156 if (v.data.isEmpty()) 139 157 return null; 140 if (!checkAndConfirmOutlyingDeletes( v.data))158 if (!checkAndConfirmOutlyingDeletes(layer,v.data)) 141 159 return null; 142 return new DeleteCommand( v.data);160 return new DeleteCommand(layer,v.data); 143 161 } 144 162 … … 153 171 } 154 172 if (role.length() > 0) 155 return new ExtendedDialog( 156 Main.parent, 157 tr("Conflicting relation"), 158 tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", 159 formatter.getName(osm), formatter.getName(ref), role), 160 new String[] {tr("Delete from relation"), tr("Cancel")}, 161 new String[] {"dialogs/delete.png", "cancel.png"}).getValue(); 173 return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr( 174 "Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", formatter 175 .getName(osm), formatter.getName(ref), role), new String[] { tr("Delete from relation"), 176 tr("Cancel") }, new String[] { "dialogs/delete.png", "cancel.png" }).getValue(); 162 177 else 163 return new ExtendedDialog(Main.parent, 164 tr("Conflicting relation"), 165 tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", 166 formatter.getName(osm), formatter.getName(ref)), 167 new String[] {tr("Delete from relation"), tr("Cancel")}, 168 new String[] {"dialogs/delete.png", "cancel.png"}).getValue(); 169 } 170 171 public static Command delete(Collection<? extends OsmPrimitive> selection) { 172 return delete(selection, true); 178 return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr( 179 "Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", formatter.getName(osm), 180 formatter.getName(ref)), new String[] { tr("Delete from relation"), tr("Cancel") }, new String[] { 181 "dialogs/delete.png", "cancel.png" }).getValue(); 182 } 183 184 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) { 185 return delete(layer, selection, true); 186 } 187 188 /** 189 * Replies the collection of nodes referred to by primitives in <code>primitivesToDelete</code> which 190 * can be deleted too. A node can be deleted if 191 * <ul> 192 * <li>it is untagged (see {@see Node#isTagged()}</li> 193 * <li>it is not referred to by other primitives outside of <code>primitivesToDelete</code></li> 194 * <ul> 195 * @param layer the layer in whose context primitives are deleted 196 * @param primitivesToDelete the primitives to delete 197 * @return the collection of nodes referred to by primitives in <code>primitivesToDelete</code> which 198 * can be deleted too 199 */ 200 protected static Collection<Node> computeNodesToDelete(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) { 201 Collection<Node> nodesToDelete = new HashSet<Node>(); 202 for (OsmPrimitive osm : primitivesToDelete) { 203 if (! (osm instanceof Way) ) { 204 continue; 205 } 206 for (Node n : ((Way) osm).nodes) { 207 if (n.isTagged()) { 208 continue; 209 } 210 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 211 n.visit(v); 212 v.data.removeAll(primitivesToDelete); 213 if (v.data.isEmpty()) { 214 nodesToDelete.add(n); 215 } 216 } 217 } 218 return nodesToDelete; 173 219 } 174 220 175 221 /** 176 222 * Try to delete all given primitives. 177 * 223 * 178 224 * If a node is used by a way, it's removed from that way. If a node or a way is used by a 179 225 * relation, inform the user and do not delete. 180 * 226 * 181 227 * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If 182 228 * they are part of a relation, inform the user and do not delete. 183 * 229 * 230 * @param layer the {@see OsmDataLayer} in whose context a primitive the primitives are deleted 184 231 * @param selection The objects to delete. 185 232 * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well 186 * @return command A command to perform the deletions, or null of there is nothing to delete.187 */ 188 public static Command delete( Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {233 * @return command a command to perform the deletions, or null if there is nothing to delete. 234 */ 235 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) { 189 236 if (selection.isEmpty()) 190 237 return null; 191 238 192 Collection<OsmPrimitive> del= new HashSet<OsmPrimitive>(selection);239 Collection<OsmPrimitive> primitivesToDelete = new HashSet<OsmPrimitive>(selection); 193 240 Collection<Way> waysToBeChanged = new HashSet<Way>(); 194 241 HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>(); 195 242 196 243 if (alsoDeleteNodesInWay) { 197 // Delete untagged nodes that are to be unreferenced. 198 Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>(); 199 for (OsmPrimitive osm : del) { 200 if (osm instanceof Way) { 201 for (Node n : ((Way) osm).nodes) { 202 if (!n.isTagged()) { 203 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet(), false); 204 n.visit(v); 205 v.data.removeAll(del); 206 if (v.data.isEmpty()) { 207 delNodes.add(n); 208 } 209 } 210 } 211 } 212 } 213 del.addAll(delNodes); 214 } 215 216 if (!checkAndConfirmOutlyingDeletes(del)) 244 // delete untagged nodes only referenced by primitives in primitivesToDelete, 245 // too 246 Collection<Node> nodesToDelete = computeNodesToDelete(layer, primitivesToDelete); 247 primitivesToDelete.addAll(nodesToDelete); 248 } 249 250 if (!checkAndConfirmOutlyingDeletes(layer,primitivesToDelete)) 217 251 return null; 218 252 219 for (OsmPrimitive osm : del) {220 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor( Main.main.getCurrentDataSet(), false);253 for (OsmPrimitive osm : primitivesToDelete) { 254 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 221 255 osm.visit(v); 222 256 for (OsmPrimitive ref : v.data) { 223 if ( del.contains(ref)) {257 if (primitivesToDelete.contains(ref)) { 224 258 continue; 225 259 } … … 244 278 for (Way w : waysToBeChanged) { 245 279 Way wnew = new Way(w); 246 wnew.removeNodes( del);280 wnew.removeNodes(primitivesToDelete); 247 281 if (wnew.nodes.size() < 2) { 248 del.add(w);249 250 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor( Main.main.getCurrentDataSet(), false);282 primitivesToDelete.add(w); 283 284 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 251 285 w.visit(v); 252 286 for (OsmPrimitive ref : v.data) { 253 if ( del.contains(ref)) {287 if (primitivesToDelete.contains(ref)) { 254 288 continue; 255 289 } … … 296 330 // deleted way is saved (or sent to the API) with a dangling reference to a node 297 331 // Example: 298 // 299 // 300 // 301 // 302 // 303 // <nd ref='-1' /><!-- heres the problem -->304 // 305 // 306 for (OsmPrimitive primitive : del) {307 if (! 332 // <node id='2' action='delete' visible='true' version='1' ... /> 333 // <node id='1' action='delete' visible='true' version='1' ... /> 334 // <!-- missing node with id -1 because new deleted nodes are not persisted --> 335 // <way id='3' action='delete' visible='true' version='1'> 336 // <nd ref='1' /> 337 // <nd ref='-1' /> <!-- heres the problem --> 338 // <nd ref='2' /> 339 // </way> 340 for (OsmPrimitive primitive : primitivesToDelete) { 341 if (!(primitive instanceof Way)) { 308 342 continue; 309 343 } 310 Way w = (Way) primitive;344 Way w = (Way) primitive; 311 345 if (w.id == 0) { // new ways with id == 0 are fine, 312 continue; 346 continue; // process existing ways only 313 347 } 314 348 Way wnew = new Way(w); … … 317 351 // nodes ... 318 352 for (Node n : wnew.nodes) { 319 if (n.id == 0 && del.contains(n)) {353 if (n.id == 0 && primitivesToDelete.contains(n)) { 320 354 nodesToStrip.add(n); 321 355 } … … 325 359 wnew.nodes.removeAll(nodesToStrip); 326 360 if (!nodesToStrip.isEmpty()) { 327 cmds.add(new ChangeCommand(w, wnew));328 } 329 } 330 331 if (! del.isEmpty()) {332 cmds.add(new DeleteCommand( del));361 cmds.add(new ChangeCommand(w, wnew)); 362 } 363 } 364 365 if (!primitivesToDelete.isEmpty()) { 366 cmds.add(new DeleteCommand(layer,primitivesToDelete)); 333 367 } 334 368 … … 336 370 } 337 371 338 public static Command deleteWaySegment( WaySegment ws) {372 public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) { 339 373 List<Node> n1 = new ArrayList<Node>(), n2 = new ArrayList<Node>(); 340 374 … … 343 377 344 378 if (n1.size() < 2 && n2.size() < 2) 345 return new DeleteCommand( Collections.singleton(ws.way));379 return new DeleteCommand(layer, Collections.singleton(ws.way)); 346 380 347 381 Way wnew = new Way(ws.way); … … 372 406 373 407 /** 374 * Check whether user is about to delete data outside of the download area. 375 * Request confirmation if he is. 376 */ 377 private static boolean checkAndConfirmOutlyingDeletes(Collection<OsmPrimitive> del) { 378 Area a = Main.main.getCurrentDataSet().getDataSourceArea(); 408 * Check whether user is about to delete data outside of the download area. Request confirmation 409 * if he is. 410 * 411 * @param layer the layer in whose context data is deleted 412 * @param primitivesToDelete the primitives to delete 413 * @return true, if deleting outlying primitives is OK; false, otherwise 414 */ 415 private static boolean checkAndConfirmOutlyingDeletes(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) { 416 Area a = layer.data.getDataSourceArea(); 379 417 if (a != null) { 380 for (OsmPrimitive osm : del) {418 for (OsmPrimitive osm : primitivesToDelete) { 381 419 if (osm instanceof Node && osm.id != 0) { 382 420 Node n = (Node) osm; … … 385 423 msg.add(new JLabel( 386 424 "<html>" + 387 // leave message in one tr() as there is a grammatical connection.388 tr("You are about to delete nodes outside of the area you have downloaded." +389 "<br>" +390 "This can cause problems because other objects (that you don't see) might use them." +391 "<br>" +392 "Do you really want to delete?") + "</html>"));425 // leave message in one tr() as there is a grammatical 426 // connection. 427 tr("You are about to delete nodes outside of the area you have downloaded." 428 + "<br>" 429 + "This can cause problems because other objects (that you don't see) might use them." 430 + "<br>" + "Do you really want to delete?") + "</html>")); 393 431 return ConditionalOptionPaneUtil.showConfirmationDialog( 394 432 "delete_outside_nodes",
Note: See TracChangeset
for help on using the changeset viewer.