Changeset 2521 in josm


Ignore:
Timestamp:
Nov 27, 2009 9:46:49 PM (4 years ago)
Author:
jttt
Message:

Fixed #3704 Relation memberships are not handled at all when a way is splitted or deleted by deleting a segment, rewritten DeleteAction a bit (delete commands are no longer build in updateCursor())

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java

    r2412 r2521  
    2828import org.openstreetmap.josm.data.osm.Node; 
    2929import org.openstreetmap.josm.data.osm.OsmPrimitive; 
     30import org.openstreetmap.josm.data.osm.PrimitiveId; 
    3031import org.openstreetmap.josm.data.osm.Relation; 
    3132import org.openstreetmap.josm.data.osm.RelationMember; 
     
    4748    private Way selectedWay; 
    4849    private List<Node> selectedNodes; 
     50 
     51    public static class SplitWayResult { 
     52        private final Command command; 
     53        private final List<? extends PrimitiveId> newSelection; 
     54 
     55        public SplitWayResult(Command command, List<? extends PrimitiveId> newSelection) { 
     56            this.command = command; 
     57            this.newSelection = newSelection; 
     58        } 
     59 
     60        public Command getCommand() { 
     61            return command; 
     62        } 
     63 
     64        public List<? extends PrimitiveId> getNewSelection() { 
     65            return newSelection; 
     66        } 
     67    } 
    4968 
    5069    /** 
     
    267286        //Main.debug("way id: " + selectedWay.id); 
    268287 
     288        SplitWayResult result = splitWay(selectedWay, wayChunks); 
     289        Main.main.undoRedo.add(result.getCommand()); 
     290        getCurrentDataSet().setSelected(result.getNewSelection()); 
     291    } 
     292 
     293    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks) { 
    269294        // build a list of commands, and also a new selection list 
    270295        Collection<Command> commandList = new ArrayList<Command>(wayChunks.size()); 
    271         Collection<Way> newSelection = new ArrayList<Way>(wayChunks.size()); 
     296        List<Way> newSelection = new ArrayList<Way>(wayChunks.size()); 
    272297 
    273298        Iterator<List<Node>> chunkIt = wayChunks.iterator(); 
    274299 
    275300        // First, change the original way 
    276         Way changedWay = new Way(selectedWay); 
     301        Way changedWay = new Way(way); 
    277302        changedWay.setNodes(chunkIt.next()); 
    278         commandList.add(new ChangeCommand(selectedWay, changedWay)); 
    279         newSelection.add(selectedWay); 
     303        commandList.add(new ChangeCommand(way, changedWay)); 
     304        newSelection.add(way); 
    280305 
    281306        Collection<Way> newWays = new ArrayList<Way>(); 
     
    283308        while (chunkIt.hasNext()) { 
    284309            Way wayToAdd = new Way(); 
    285             wayToAdd.setKeys(selectedWay.getKeys()); 
     310            wayToAdd.setKeys(way.getKeys()); 
    286311            newWays.add(wayToAdd); 
    287312            wayToAdd.setNodes(chunkIt.next()); 
     
    295320        // now copy all relations to new way also 
    296321 
    297         for (Relation r : OsmPrimitive.getFilteredList(selectedWay.getReferrers(), Relation.class)) { 
     322        for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) { 
    298323            if (!r.isUsable()) { 
    299324                continue; 
     
    308333            for (RelationMember rm : r.getMembers()) { 
    309334                if (rm.isWay()) { 
    310                     if (rm.getMember() == selectedWay) { 
     335                    if (rm.getMember() == way) { 
    311336                        if (!("route".equals(type)) && !("multipolygon".equals(type))) { 
    312337                            warnme = true; 
     
    355380        } 
    356381 
    357         Main.main.undoRedo.add( 
    358                 new SequenceCommand(tr("Split way {0} into {1} parts", 
    359                         selectedWay.getDisplayName(DefaultNameFormatter.getInstance()), 
    360                         wayChunks.size()), 
    361                         commandList)); 
    362         getCurrentDataSet().setSelected(newSelection); 
     382 
     383        return new SplitWayResult(new SequenceCommand(tr("Split way {0} into {1} parts", 
     384                way.getDisplayName(DefaultNameFormatter.getInstance()), 
     385                wayChunks.size()), 
     386                commandList), newSelection); 
    363387    } 
    364388 
  • trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r2512 r2521  
    1313import java.awt.event.KeyEvent; 
    1414import java.awt.event.MouseEvent; 
    15 import java.util.Collection; 
    1615import java.util.Collections; 
    17 import java.util.HashSet; 
    1816 
    1917import org.openstreetmap.josm.Main; 
     
    2119import org.openstreetmap.josm.command.DeleteCommand; 
    2220import org.openstreetmap.josm.data.osm.Node; 
    23 import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    2421import org.openstreetmap.josm.data.osm.Relation; 
    25 import org.openstreetmap.josm.data.osm.Way; 
    2622import org.openstreetmap.josm.data.osm.WaySegment; 
    2723import org.openstreetmap.josm.gui.MapFrame; 
     
    6359    private MouseEvent oldEvent = null; 
    6460 
    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 
     61    private enum DeleteMode { 
     62        none("delete"), 
     63        segment("delete_segment"), 
     64        node("delete_node"), 
     65        node_with_references("delete_node"), 
     66        way("delete_way_only"), 
     67        way_with_references("delete_way_normal"), 
     68        way_with_nodes("delete_way_node_only"); 
     69 
     70        private final Cursor c; 
     71 
     72        private DeleteMode(String cursorName) { 
     73            c = ImageProvider.getCursor("normal", cursorName); 
     74        } 
     75 
    7576        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             } 
    8277            return c; 
    8378        } 
    8479    } 
    85     private Cursors currCursor = Cursors.none; 
     80    private DeleteMode currentMode = DeleteMode.none; 
     81 
     82    private static class DeleteParameters { 
     83        DeleteMode mode; 
     84        Node nearestNode; 
     85        WaySegment nearestSegment; 
     86    } 
    8687 
    8788    /** 
     
    110111        try { 
    111112            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK); 
    112         } catch (SecurityException ex) {} 
    113  
    114         currCursor = Cursors.none; 
     113        } catch (SecurityException ex) { 
     114            System.out.println(ex); 
     115        } 
     116 
     117        currentMode = DeleteMode.none; 
    115118    } 
    116119 
     
    121124        try { 
    122125            Toolkit.getDefaultToolkit().removeAWTEventListener(this); 
    123         } catch (SecurityException ex) {} 
     126        } catch (SecurityException ex) { 
     127            System.out.println(ex); 
     128        } 
    124129    } 
    125130 
     
    172177     * 
    173178     * @param MouseEvent 
    174      * @parm int modifiers 
     179     * @param int modifiers 
    175180     */ 
    176181    private void updateCursor(MouseEvent e, int modifiers) { 
    177         if (!Main.isDisplayingMapView()) { 
    178             return; 
    179         } 
     182        if (!Main.isDisplayingMapView()) 
     183            return; 
    180184        if(!Main.map.mapView.isActiveLayerVisible() || e == null) 
    181185            return; 
     
    184188        //cleanOldHighlights(); 
    185189 
    186         Command c = buildDeleteCommands(e, modifiers, true); 
    187         if(c == null) { 
    188             setCursor(Cursors.none); 
    189             return; 
    190         } 
    191  
    192         Collection<OsmPrimitive> prims = new HashSet<OsmPrimitive>(); 
    193         Collection<OsmPrimitive> mods = new HashSet<OsmPrimitive>(); 
    194         c.fillModifiedData(mods, prims, prims); 
    195  
    196         if(prims.size() == 0 && mods.size() == 0) { 
    197             // Default-Cursor 
    198             setCursor(Cursors.none); 
    199             return; 
    200         } 
    201  
    202         // There are no deleted parts if solely a way segment is deleted 
    203         // This is no the case when actually deleting only a segment but that 
    204         // segment happens to be the whole way. This is an acceptable error 
    205         // though 
    206         if(prims.size() == 0) { 
    207             setCursor(Cursors.segment); 
    208         } else if(prims.size() == 1 && prims.toArray()[0] instanceof Node) { 
    209             setCursor(Cursors.node); 
    210         } else if(prims.size() == 1 && prims.toArray()[0] instanceof Way) { 
    211             setCursor(Cursors.way_only); 
    212         } else { 
    213             // Decide between non-accel click where "useless" nodes are deleted 
    214             // and ctrl-click where nodes and ways are deleted 
    215             boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 
    216             if(ctrl) { 
    217                 setCursor(Cursors.way_node_only); 
    218             } else { 
    219                 setCursor(Cursors.way_normal); 
    220             } 
    221  
    222         } 
     190        DeleteParameters parameters = getDeleteParameters(e, modifiers); 
     191        setCursor(parameters.mode); 
    223192 
    224193        // Needs to implement WaySegment highlight first 
     
    306275    } 
    307276 
     277    private DeleteParameters getDeleteParameters(MouseEvent e, int modifiers) { 
     278        // Note: CTRL is the only modifier that is checked in MouseMove, don't 
     279        // forget updating it there 
     280        boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 
     281        boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 
     282        boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 
     283 
     284        DeleteParameters result = new DeleteParameters(); 
     285 
     286        result.nearestNode = Main.map.mapView.getNearestNode(e.getPoint()); 
     287        if (result.nearestNode == null) { 
     288            result.nearestSegment = Main.map.mapView.getNearestWaySegment(e.getPoint()); 
     289            if (result.nearestSegment != null) { 
     290                if (shift) { 
     291                    result.mode = DeleteMode.segment; 
     292                } else if (ctrl) { 
     293                    result.mode = DeleteMode.way_with_references; 
     294                } else { 
     295                    result.mode = alt?DeleteMode.way:DeleteMode.way_with_nodes; 
     296                } 
     297            } else { 
     298                result.mode = DeleteMode.none; 
     299            } 
     300        } else if (ctrl) { 
     301            result.mode = DeleteMode.node_with_references; 
     302        } else { 
     303            result.mode = DeleteMode.node; 
     304        } 
     305 
     306        return result; 
     307    } 
     308 
    308309    /** 
    309310     * This function takes any mouse event argument and builds the list of elements 
     
    316317     */ 
    317318    private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean silent) { 
    318         // Note: CTRL is the only modifier that is checked in MouseMove, don't 
    319         // forget updating it there 
    320         boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 
    321         boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 
    322         boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 
    323  
    324         OsmPrimitive sel = Main.map.mapView.getNearestNode(e.getPoint()); 
    325         Command c = null; 
    326         if (sel == null) { 
    327             WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint()); 
    328             if (ws != null) { 
    329                 if (shift) { 
    330                     c = DeleteCommand.deleteWaySegment(getEditLayer(),ws); 
    331                 } else if (ctrl) { 
    332                     c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way),true); 
    333                 } else { 
    334                     c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt, silent); 
    335                 } 
    336             } 
    337         } else if (ctrl) { 
    338             c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(sel)); 
    339         } else { 
    340             c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt, silent); 
    341         } 
    342  
    343         return c; 
     319        DeleteParameters parameters = getDeleteParameters(e, modifiers); 
     320        switch (parameters.mode) { 
     321        case node: 
     322            return DeleteCommand.delete(getEditLayer(),Collections.singleton(parameters.nearestNode), false, silent); 
     323        case node_with_references: 
     324            return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestNode)); 
     325        case segment: 
     326            return DeleteCommand.deleteWaySegment(getEditLayer(), parameters.nearestSegment); 
     327        case way: 
     328            return DeleteCommand.delete(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), false, silent); 
     329        case way_with_nodes: 
     330            return DeleteCommand.delete(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), true, silent); 
     331        case way_with_references: 
     332            return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestSegment.way),true); 
     333        default: 
     334            return null; 
     335        } 
    344336    } 
    345337 
     
    351343     * @param c 
    352344     */ 
    353     private void setCursor(final Cursors c) { 
    354         if(currCursor.equals(c) || (!drawTargetCursor && currCursor.equals(Cursors.none))) 
     345    private void setCursor(final DeleteMode c) { 
     346        if(currentMode.equals(c) || (!drawTargetCursor && currentMode.equals(DeleteMode.none))) 
    355347            return; 
    356348        try { 
     
    366358                } 
    367359            }); 
    368             currCursor = c; 
     360            currentMode = c; 
    369361        } catch(Exception e) {} 
    370362    } 
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r2512 r2521  
    2323 
    2424import org.openstreetmap.josm.Main; 
     25import org.openstreetmap.josm.actions.SplitWayAction; 
    2526import org.openstreetmap.josm.data.osm.BackreferencedDataSet; 
    2627import org.openstreetmap.josm.data.osm.Node; 
     
    253254    protected static Collection<Node> computeNodesToDelete(BackreferencedDataSet backreferences, OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) { 
    254255        Collection<Node> nodesToDelete = new HashSet<Node>(); 
    255         //CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
    256256        for (Way way : OsmPrimitive.getFilteredList(primitivesToDelete, Way.class)) { 
    257257            for (Node n : way.getNodes()) { 
     
    259259                    continue; 
    260260                } 
    261                 //v.initialize(); 
    262                 //n.visit(v); 
    263261                Collection<OsmPrimitive> referringPrimitives = backreferences.getParents(n); 
    264262                referringPrimitives.removeAll(primitivesToDelete); 
     
    385383    public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) { 
    386384        if (ws.way.getNodesCount() < 3) 
    387             return new DeleteCommand(layer, Collections.singleton(ws.way)); 
     385            return delete(layer, Collections.singleton(ws.way)); 
    388386 
    389387        if (ws.way.firstNode() == ws.way.lastNode()) { 
     
    416414            return new ChangeCommand(ws.way, wnew); 
    417415        } else { 
    418             Collection<Command> cmds = new LinkedList<Command>(); 
    419  
    420             wnew.setNodes(n1); 
    421             cmds.add(new ChangeCommand(ws.way, wnew)); 
    422  
    423             Way wnew2 = new Way(); 
    424             wnew2.setKeys(wnew.getKeys()); 
    425             wnew2.setNodes(n2); 
    426             cmds.add(new AddCommand(wnew2)); 
    427  
    428             // FIXME: relation memberships are not handled 
    429  
    430             return new SequenceCommand(tr("Split way segment"), cmds); 
     416            List<List<Node>> chunks = new ArrayList<List<Node>>(2); 
     417            chunks.add(n1); 
     418            chunks.add(n2); 
     419            return SplitWayAction.splitWay(ws.way, chunks).getCommand(); 
    431420        } 
    432421    } 
  • trunk/src/org/openstreetmap/josm/data/osm/DatasetConsistencyTest.java

    r2501 r2521  
    2626    private void checkReferrers() { 
    2727        for (Way way:dataSet.getWays()) { 
    28             for (Node n:way.getNodes()) { 
    29                 if (!n.getReferrers().contains(way)) { 
    30                     writer.println(String.format("%s is part of %s but is not in referrers", n, way)); 
     28            if (!way.isDeleted()) { 
     29                for (Node n:way.getNodes()) { 
     30                    if (!n.getReferrers().contains(way)) { 
     31                        writer.println(String.format("%s is part of %s but is not in referrers", n, way)); 
     32                    } 
    3133                } 
    3234            } 
     
    3436 
    3537        for (Relation relation:dataSet.getRelations()) { 
    36             for (RelationMember m:relation.getMembers()) { 
    37                 if (!m.getMember().getReferrers().contains(relation)) { 
    38                     writer.println(String.format("%s is part of %s but is not in referrers", m.getMember(), relation)); 
     38            if (!relation.isDeleted()) { 
     39                for (RelationMember m:relation.getMembers()) { 
     40                    if (!m.getMember().getReferrers().contains(relation)) { 
     41                        writer.println(String.format("%s is part of %s but is not in referrers", m.getMember(), relation)); 
     42                    } 
    3943                } 
    4044            } 
Note: See TracChangeset for help on using the changeset viewer.