Ticket #9896: bug9896.patch

File bug9896.patch, 4.7 KB (added by Balaitous, 10 years ago)
  • src/org/openstreetmap/josm/actions/UnGlueAction.java

    import javax.swing.JPanel;  
    2121import org.openstreetmap.josm.Main;
    2222import org.openstreetmap.josm.command.AddCommand;
    2323import org.openstreetmap.josm.command.ChangeCommand;
     24import org.openstreetmap.josm.command.ChangeNodesCommand;
    2425import org.openstreetmap.josm.command.Command;
    2526import org.openstreetmap.josm.command.SequenceCommand;
    2627import org.openstreetmap.josm.data.osm.Node;
    public class UnGlueAction extends JosmAction {  
    7071        int errorTime = Notification.TIME_DEFAULT;
    7172        if (checkSelection(selection)) {
    7273            if (!checkAndConfirmOutlyingUnglue()) {
     74                // FIXME: Leaving action without clearing selectedNode, selectedWay, selectedNodes
    7375                return;
    7476            }
    7577            int count = 0;
    public class UnGlueAction extends JosmAction {  
    8082                count++;
    8183            }
    8284            if (count < 2) {
     85                boolean selfCrossing = false;
     86                if (count == 1) {
     87                    // First try unglue self-crossing way
     88                    selfCrossing = unglueSelfCrossingWay();
     89                }
    8390                // If there aren't enough ways, maybe the user wanted to unglue the nodes
    8491                // (= copy tags to a new node)
    85                 if (checkForUnglueNode(selection)) {
    86                     unglueNode(e);
    87                 } else {
    88                     errorTime = Notification.TIME_SHORT;
    89                     errMsg = tr("This node is not glued to anything else.");
    90                 }
     92                if (!selfCrossing)
     93                    if (checkForUnglueNode(selection)) {
     94                        unglueNode(e);
     95                    } else {
     96                        errorTime = Notification.TIME_SHORT;
     97                        errMsg = tr("This node is not glued to anything else.");
     98                    }
    9199            } else {
    92100                // and then do the work.
    93101                unglueWays();
    94102            }
    95103        } else if (checkSelection2(selection)) {
    96104            if (!checkAndConfirmOutlyingUnglue()) {
     105                // FIXME: Leaving action without clearing selectedNode, selectedWay, selectedNodes
    97106                return;
    98107            }
    99108            Set<Node> tmpNodes = new HashSet<Node>();
    public class UnGlueAction extends JosmAction {  
    378387        }
    379388
    380389        fixRelations(selectedNode, cmds, newNodes);
     390        execCommands(cmds, newNodes);
     391    }
    381392
     393    /**
     394     * Add commands to undo-redo system.
     395     * @param cmds Commands to execute
     396     * @param newNodes New created nodes by this set of command
     397     */
     398    private void execCommands(List<Command> cmds, List<Node> newNodes) {
    382399        Main.main.undoRedo.add(new SequenceCommand(/* for correct i18n of plural forms - see #9110 */
    383400                trn("Dupe into {0} node", "Dupe into {0} nodes", newNodes.size() + 1, newNodes.size() + 1), cmds));
    384401        // select one of the new nodes
    385         getCurrentDataSet().setSelected(newNodes.getFirst());
     402        getCurrentDataSet().setSelected(newNodes.get(0));
     403    }
     404
     405    /**
     406     * Duplicates a node used several times by the same way.
     407     * See #9896
     408     * @return true if action is OK false if there is nothing to do
     409     */
     410    private boolean unglueSelfCrossingWay() {
     411        // According to previous check, only one valid way through that node
     412        LinkedList<Command> cmds = new LinkedList<Command>();
     413        Way way = null;
     414        for(Way w: OsmPrimitive.getFilteredList(selectedNode.getReferrers(), Way.class))
     415            if(w.isUsable() && w.getNodesCount() >= 1)
     416                way = w;
     417        List<Node> oldNodes = way.getNodes();
     418        ArrayList<Node> newNodes = new ArrayList<Node>(oldNodes.size());
     419        ArrayList<Node> addNodes = new ArrayList<Node>();
     420        boolean seen = false;
     421        for(Node n: oldNodes)
     422            if(n == selectedNode) {
     423                if(seen) {
     424                    Node newNode = new Node(n, true /* clear OSM ID */);
     425                    newNodes.add(newNode);
     426                    cmds.add(new AddCommand(newNode));
     427                    newNodes.add(newNode);
     428                    addNodes.add(newNode);
     429                } else {
     430                    newNodes.add(n);
     431                    seen = true;
     432                }
     433            } else
     434                newNodes.add(n);
     435        if(addNodes.isEmpty())
     436            // selectedNode doesn't need unglue
     437            return false;
     438        cmds.add(new ChangeNodesCommand(way, newNodes));
     439        // Update relation
     440        fixRelations(selectedNode, cmds, addNodes);
     441        execCommands(cmds, addNodes);
     442        return true;
    386443    }
    387444
    388445    /**