Changeset 6959 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2014-04-05T17:52:29+02:00 (10 years ago)
Author:
Don-vip
Message:

fix #9896 - "g" shortcut (UnGlueAction) doesn't work with self-crossing way (patch by Balaitous)

File:
1 edited

Legend:

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

    r6830 r6959  
    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;
     
    7172        if (checkSelection(selection)) {
    7273            if (!checkAndConfirmOutlyingUnglue()) {
     74                // FIXME: Leaving action without clearing selectedNode, selectedWay, selectedNodes
    7375                return;
    7476            }
     
    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.
     
    95103        } else if (checkSelection2(selection)) {
    96104            if (!checkAndConfirmOutlyingUnglue()) {
     105                // FIXME: Leaving action without clearing selectedNode, selectedWay, selectedNodes
    97106                return;
    98107            }
     
    379388
    380389        fixRelations(selectedNode, cmds, newNodes);
    381 
     390        execCommands(cmds, newNodes);
     391    }
     392
     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());
    386     }
     402        getCurrentDataSet().setSelected(newNodes.get(0));
     403    }
     404
     405    /**
     406     * Duplicates a node used several times by the same way. See #9896.
     407     * @return true if action is OK false if there is nothing to do
     408     */
     409    private boolean unglueSelfCrossingWay() {
     410        // According to previous check, only one valid way through that node
     411        LinkedList<Command> cmds = new LinkedList<Command>();
     412        Way way = null;
     413        for (Way w: OsmPrimitive.getFilteredList(selectedNode.getReferrers(), Way.class))
     414            if (w.isUsable() && w.getNodesCount() >= 1) {
     415                way = w;
     416            }
     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            }
     436        }
     437        if (addNodes.isEmpty()) {
     438            // selectedNode doesn't need unglue
     439            return false;
     440        }
     441        cmds.add(new ChangeNodesCommand(way, newNodes));
     442        // Update relation
     443        fixRelations(selectedNode, cmds, addNodes);
     444        execCommands(cmds, addNodes);
     445        return true;
     446     }
    387447
    388448    /**
Note: See TracChangeset for help on using the changeset viewer.