Changeset 2026 in josm
- Timestamp:
- 2009-09-02T21:37:18+02:00 (15 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
r1935 r2026 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.AWTEvent; 7 import java.awt.Cursor; 8 import java.awt.EventQueue; 9 import java.awt.Toolkit; 10 import java.awt.event.AWTEventListener; 6 11 import java.awt.event.ActionEvent; 7 12 import java.awt.event.InputEvent; 8 13 import java.awt.event.KeyEvent; 9 14 import java.awt.event.MouseEvent; 15 import java.util.Collection; 10 16 import java.util.Collections; 17 import java.util.HashSet; 11 18 12 19 import org.openstreetmap.josm.Main; 13 20 import org.openstreetmap.josm.command.Command; 14 21 import org.openstreetmap.josm.command.DeleteCommand; 22 import org.openstreetmap.josm.data.osm.Node; 15 23 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 24 import org.openstreetmap.josm.data.osm.Relation; 25 import org.openstreetmap.josm.data.osm.Way; 17 26 import org.openstreetmap.josm.data.osm.WaySegment; 18 27 import org.openstreetmap.josm.gui.MapFrame; … … 38 47 * @author imi 39 48 */ 40 public class DeleteAction extends MapMode { 49 50 /** 51 * This class contains stubs for highlighting affected primitives when affected. 52 * However, way segments can be deleted as well, but cannot be highlighted 53 * alone. If the highlight feature for this delete action is to be implemented 54 * properly, highlighting way segments must be possible first. --xeen, 2009-09-02 55 */ 56 public class DeleteAction extends MapMode implements AWTEventListener { 57 //private boolean drawTargetHighlight; 58 private boolean drawTargetCursor; 59 //private Collection<? extends OsmPrimitive> oldPrims = null; 60 61 // Cache previous mouse event (needed when only the modifier keys are 62 // pressed but the mouse isn't moved) 63 private MouseEvent oldEvent = null; 64 65 private enum Cursors { 66 none, 67 node, 68 segment, 69 way_node_only, 70 way_normal, 71 way_only; 72 73 private Cursor c = null; 74 // This loads and caches the cursor for each 75 public Cursor cursor() { 76 if(c == null) { 77 String nm = "delete_" + this.name().toLowerCase(); 78 // "None" has no special icon 79 nm = nm.equals("delete_none") ? "delete" : nm; 80 this.c = ImageProvider.getCursor("normal", nm); 81 } 82 return c; 83 } 84 } 85 private Cursors currCursor = Cursors.none; 41 86 42 87 /** … … 57 102 if (!isEnabled()) 58 103 return; 104 //drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); 105 drawTargetCursor = Main.pref.getBoolean("draw.target-cursor", true); 106 59 107 Main.map.mapView.addMouseListener(this); 108 Main.map.mapView.addMouseMotionListener(this); 109 // This is required to update the cursors when ctrl/shift/alt is pressed 110 try { 111 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK); 112 } catch (SecurityException ex) {} 113 114 currCursor = Cursors.none; 60 115 } 61 116 … … 63 118 super.exitMode(); 64 119 Main.map.mapView.removeMouseListener(this); 120 Main.map.mapView.removeMouseMotionListener(this); 121 try { 122 Toolkit.getDefaultToolkit().removeAWTEventListener(this); 123 } catch (SecurityException ex) {} 65 124 } 66 125 … … 94 153 95 154 /** 155 * Listen to mouse move to be able to update the cursor (and highlights) 156 * @param MouseEvent The mouse event that has been captured 157 */ 158 @Override public void mouseMoved(MouseEvent e) { 159 oldEvent = e; 160 updateCursor(e, e.getModifiers()); 161 } 162 163 /** 164 * This function handles all work related to updating the cursor and 165 * highlights. For now, only the cursor is enabled because highlighting 166 * requires WaySegment to be highlightable. 167 * 168 * Normally the mouse event also contains the modifiers. However, when the 169 * mouse is not moved and only modifier keys are pressed, no mouse event 170 * occurs. We can use AWTEvent to catch those but still lack a proper 171 * mouseevent. Instead we copy the previous event and only update the 172 * modifiers. 173 * 174 * @param MouseEvent 175 * @parm int modifiers 176 */ 177 private void updateCursor(MouseEvent e, int modifiers) { 178 if(!Main.map.mapView.isActiveLayerVisible() || e == null) 179 return; 180 181 // Clean old highlights 182 //cleanOldHighlights(); 183 184 Command c = buildDeleteCommands(e, modifiers, true); 185 if(c == null) { 186 setCursor(Cursors.none); 187 return; 188 } 189 190 Collection<OsmPrimitive> prims = new HashSet<OsmPrimitive>(); 191 Collection<OsmPrimitive> mods = new HashSet<OsmPrimitive>(); 192 c.fillModifiedData(mods, prims, prims); 193 194 if(prims.size() == 0 && mods.size() == 0) { 195 // Default-Cursor 196 setCursor(Cursors.none); 197 return; 198 } 199 200 // There are no deleted parts if solely a way segment is deleted 201 // This is no the case when actually deleting only a segment but that 202 // segment happens to be the whole way. This is an acceptable error 203 // though 204 if(prims.size() == 0) { 205 setCursor(Cursors.segment); 206 } else if(prims.size() == 1 && prims.toArray()[0] instanceof Node) { 207 setCursor(Cursors.node); 208 } else if(prims.size() == 1 && prims.toArray()[0] instanceof Way) { 209 setCursor(Cursors.way_only); 210 } else { 211 // Decide between non-accel click where "useless" nodes are deleted 212 // and ctrl-click where nodes and ways are deleted 213 boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 214 if(ctrl) { 215 setCursor(Cursors.way_node_only); 216 } else { 217 setCursor(Cursors.way_normal); 218 } 219 220 } 221 222 // Needs to implement WaySegment highlight first 223 /*if(drawTargetHighlight) { 224 // Add new highlights 225 for(OsmPrimitive p : prims) { 226 p.highlighted = true; 227 } 228 oldPrims = prims; 229 }*/ 230 231 // We only need to repaint if the highlights changed 232 //Main.map.mapView.repaint(); 233 } 234 235 /** 236 * Small helper function that cleans old highlights 237 */ 238 /*private void cleanOldHighlights() { 239 if(oldPrims == null) 240 return; 241 for(OsmPrimitive p: oldPrims) { 242 p.highlighted = false; 243 } 244 }*/ 245 246 /** 96 247 * If user clicked with the left button, delete the nearest object. 97 248 * position. … … 107 258 Main.map.mapView.requestFocus(); 108 259 109 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 110 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 111 boolean alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 260 Command c = buildDeleteCommands(e, e.getModifiers(), false); 261 if (c != null) { 262 Main.main.undoRedo.add(c); 263 } 264 265 getCurrentDataSet().setSelected(); 266 Main.map.mapView.repaint(); 267 } 268 269 @Override public String getModeHelpText() { 270 return tr("Click to delete. Shift: delete way segment. Alt: don't delete unused nodes when deleting a way. Ctrl: delete referring objects."); 271 } 272 273 @Override public boolean layerIsSupported(Layer l) { 274 return l instanceof OsmDataLayer; 275 } 276 277 @Override 278 protected void updateEnabledState() { 279 setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.isActiveLayerDrawable()); 280 } 281 282 /** 283 * Deletes the relation in the context of the given layer. Also notifies 284 * {@see RelationDialogManager} and {@see OsmDataLayer#fireDataChange()} events. 285 * 286 * @param layer the layer in whose context the relation is deleted. Must not be null. 287 * @param toDelete the relation to be deleted. Must not be null. 288 * @exception IllegalArgumentException thrown if layer is null 289 * @exception IllegalArgumentException thrown if toDelete is nul 290 */ 291 public static void deleteRelation(OsmDataLayer layer, Relation toDelete) { 292 if (layer == null) 293 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "layer")); 294 if (toDelete == null) 295 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "toDelete")); 296 297 Command cmd = DeleteCommand.delete(layer, Collections.singleton(toDelete)); 298 if (cmd != null) { 299 // cmd can be null if the user cancels dialogs DialogCommand displays 300 Main.main.undoRedo.add(cmd); 301 RelationDialogManager.getRelationDialogManager().close(layer, toDelete); 302 layer.fireDataChange(); 303 } 304 } 305 306 /** 307 * This function takes any mouse event argument and builds the list of elements 308 * that should be deleted but does not actually delete them. 309 * @param e MouseEvent from which modifiers and position are taken 310 * @param int modifiers For explanation: @see updateCursor 311 * @param Simulate Set to true if the user should be bugged with additional 312 * dialogs 313 * @return 314 */ 315 private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean simulate) { 316 // Note: CTRL is the only modifier that is checked in MouseMove, don't 317 // forget updating it there 318 boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 319 boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 320 boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 112 321 113 322 OsmPrimitive sel = Main.map.mapView.getNearestNode(e.getPoint()); … … 119 328 c = DeleteCommand.deleteWaySegment(getEditLayer(),ws); 120 329 } else if (ctrl) { 121 c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way) );330 c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way),true); 122 331 } else { 123 c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt );332 c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt, simulate); 124 333 } 125 334 } … … 127 336 c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(sel)); 128 337 } else { 129 c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt); 130 } 131 if (c != null) { 132 Main.main.undoRedo.add(c); 133 } 134 135 getCurrentDataSet().setSelected(); 136 Main.map.mapView.repaint(); 137 } 138 139 @Override public String getModeHelpText() { 140 return tr("Click to delete. Shift: delete way segment. Alt: don't delete unused nodes when deleting a way. Ctrl: delete referring objects."); 141 } 142 143 @Override public boolean layerIsSupported(Layer l) { 144 return l instanceof OsmDataLayer; 145 } 146 147 @Override 148 protected void updateEnabledState() { 149 setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.isActiveLayerDrawable()); 150 } 151 152 /** 153 * Deletes the relation in the context of the given layer. Also notifies 154 * {@see RelationDialogManager} and {@see OsmDataLayer#fireDataChange()} events. 155 * 156 * @param layer the layer in whose context the relation is deleted. Must not be null. 157 * @param toDelete the relation to be deleted. Must not be null. 158 * @exception IllegalArgumentException thrown if layer is null 159 * @exception IllegalArgumentException thrown if toDelete is nul 160 */ 161 public static void deleteRelation(OsmDataLayer layer, Relation toDelete) { 162 if (layer == null) 163 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "layer")); 164 if (toDelete == null) 165 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "toDelete")); 166 if (toDelete == null) 167 return; 168 Command cmd = DeleteCommand.delete(layer, Collections.singleton(toDelete)); 169 if (cmd != null) { 170 // cmd can be null if the user cancels dialogs DialogCommand displays 171 // 172 Main.main.undoRedo.add(cmd); 173 RelationDialogManager.getRelationDialogManager().close(layer, toDelete); 174 layer.fireDataChange(); 175 } 338 c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt, simulate); 339 } 340 341 return c; 342 } 343 344 /** 345 * This function sets the given cursor in a safe way. This implementation 346 * differs from the on in DrawAction (it is favorable, too). 347 * FIXME: Update DrawAction to use this "setCursor-style" and move function 348 * to MapMode. 349 * @param c 350 */ 351 private void setCursor(final Cursors c) { 352 if(currCursor.equals(c) || (!drawTargetCursor && currCursor.equals(Cursors.none))) 353 return; 354 try { 355 // We invoke this to prevent strange things from happening 356 EventQueue.invokeLater(new Runnable() { 357 public void run() { 358 // Don't change cursor when mode has changed already 359 if(!(Main.map.mapMode instanceof DeleteAction)) 360 return; 361 362 Main.map.mapView.setCursor(c.cursor()); 363 //System.out.println("Set cursor to: " + c.name()); 364 } 365 }); 366 currCursor = c; 367 } catch(Exception e) {} 368 } 369 370 /** 371 * This is required to update the cursors when ctrl/shift/alt is pressed 372 */ 373 public void eventDispatched(AWTEvent e) { 374 // We don't have a mouse event, so we pass the old mouse event but the 375 // new modifiers. 376 updateCursor(oldEvent, ((InputEvent)e).getModifiers()); 176 377 } 177 378 } -
trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
r2025 r2026 43 43 */ 44 44 public class DeleteCommand extends Command { 45 46 45 /** 47 46 * The primitives that get deleted. … … 157 156 * If a way is deleted, only the way and no nodes are deleted. 158 157 * 158 * @param layer 159 159 * @param selection The list of all object to be deleted. 160 * @param simulate Set to true if the user should not be bugged with additional dialogs 160 161 * @return command A command to perform the deletions, or null of there is nothing to delete. 161 162 */ 162 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection ) {163 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean simulate) { 163 164 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data); 164 165 for (OsmPrimitive osm : selection) { … … 168 169 if (v.data.isEmpty()) 169 170 return null; 170 if (!checkAndConfirmOutlyingDeletes(layer,v.data) )171 if (!checkAndConfirmOutlyingDeletes(layer,v.data) && !simulate) 171 172 return null; 172 173 return new DeleteCommand(layer,v.data); 173 174 } 174 175 175 private static int testRelation(Relation ref, OsmPrimitive osm) { 176 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) { 177 return deleteWithReferences(layer, selection, false); 178 } 179 180 private static int testRelation(Relation ref, OsmPrimitive osm, boolean simulate) { 181 // If this delete action is simulated, do not bug the user with dialogs 182 // and assume the relations should be deleted 183 if(simulate) 184 return 1; 185 176 186 String role = new String(); 177 187 for (RelationMember m : ref.getMembers()) { … … 195 205 196 206 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) { 197 return delete(layer, selection, true );207 return delete(layer, selection, true, false); 198 208 } 199 209 … … 243 253 * @param selection The objects to delete. 244 254 * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well 255 * @param simulate Set to true if the user should not be bugged with additional questions 245 256 * @return command a command to perform the deletions, or null if there is nothing to delete. 246 257 */ 247 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) { 258 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, 259 boolean alsoDeleteNodesInWay) { 260 return delete(layer, selection, alsoDeleteNodesInWay, false); 261 } 262 263 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, 264 boolean alsoDeleteNodesInWay, boolean simulate) { 248 265 if (selection.isEmpty()) 249 266 return null; … … 260 277 } 261 278 262 if (!checkAndConfirmOutlyingDeletes(layer,primitivesToDelete) )279 if (!checkAndConfirmOutlyingDeletes(layer,primitivesToDelete) && !simulate) 263 280 return null; 264 281 … … 273 290 waysToBeChanged.add((Way) ref); 274 291 } else if (ref instanceof Relation) { 275 if (testRelation((Relation) ref, osm ) == 1) {292 if (testRelation((Relation) ref, osm, simulate) == 1) { 276 293 Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref); 277 294 if (relset == null) { … … 314 331 } 315 332 if (!found) { 316 if (testRelation((Relation) ref, w ) == 1) {333 if (testRelation((Relation) ref, w, simulate) == 1) { 317 334 relset.add(w); 318 335 relationsToBeChanged.put(ref, relset);
Note:
See TracChangeset
for help on using the changeset viewer.