Ticket #1633: Add Unglue Node.patch

File Add Unglue Node.patch, 6.7 KB (added by xeen, 16 years ago)

This differs from the rest of unglue in that it takes the mouse position into account. This should be no problem though for a single node and also solves the selection-order problem that always seems to select the old node

  • src/org/openstreetmap/josm/actions/UnGlueAction.java

     
    77import java.awt.event.KeyEvent;
    88import java.util.ArrayList;
    99import java.util.Collection;
     10import java.util.Collections;
    1011import java.util.HashSet;
    1112import java.util.LinkedList;
    1213import java.util.List;
    1314
    1415import javax.swing.JOptionPane;
     16import javax.swing.JPanel;
    1517
    1618import org.openstreetmap.josm.Main;
    1719import org.openstreetmap.josm.command.AddCommand;
    1820import org.openstreetmap.josm.command.ChangeCommand;
    1921import org.openstreetmap.josm.command.Command;
    2022import org.openstreetmap.josm.command.SequenceCommand;
     23import org.openstreetmap.josm.data.coor.EastNorth;
    2124import org.openstreetmap.josm.data.osm.Node;
    2225import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2326import org.openstreetmap.josm.data.osm.Relation;
    2427import org.openstreetmap.josm.data.osm.RelationMember;
    2528import org.openstreetmap.josm.data.osm.Way;
     29import org.openstreetmap.josm.gui.MapView;
    2630import org.openstreetmap.josm.tools.Shortcut;
    2731
    2832/**
     
    3135 * Resulting nodes are identical, up to their position.
    3236 *
    3337 * This is the opposite of the MergeNodesAction.
     38 *
     39 * If a single node is selected, it will copy that node and remove all tags from the old one
    3440 */
    3541
    3642public class UnGlueAction extends JosmAction { //implements SelectionChangedListener {
     
    5662    public void actionPerformed(ActionEvent e) {
    5763
    5864        Collection<OsmPrimitive> selection = Main.ds.getSelected();
    59 
     65       
     66        String errMsg = null;
    6067        if (checkSelection(selection)) {
    6168            int count = 0;
    6269            for (Way w : Main.ds.ways) {
     
    6572                count++;
    6673            }
    6774            if (count < 2) {
    68                 JOptionPane.showMessageDialog(Main.parent, tr("This node is not glued to anything else."));
     75                // If there aren't enough ways, maybe the user wanted to unglue the nodes
     76                // (= copy tags to a new node)
     77                if(checkForUnglueNode(selection))
     78                    unglueNode(e);
     79                else
     80                    errMsg = tr("This node is not glued to anything else.");
    6981            } else {
    7082                // and then do the work.
    7183                unglueWays();
     
    8597            }
    8698            if (tmpNodes.size() < 1) {
    8799                if (selection.size() > 1) {
    88                     JOptionPane.showMessageDialog(Main.parent, tr("None of these nodes are glued to anything else."));
     100                    errMsg =  tr("None of these nodes are glued to anything else.");
    89101                } else {
    90                     JOptionPane.showMessageDialog(Main.parent, tr("None of this way's nodes are glued to anything else."));
     102                    errMsg = tr("None of this way's nodes are glued to anything else.");
    91103                }
    92104            } else {
    93105                // and then do the work.
     
    95107                unglueWays2();
    96108            }
    97109        } else {
    98             JOptionPane.showMessageDialog(Main.parent,
     110            errMsg =
    99111                tr("The current selection cannot be used for unglueing.")+"\n"+
    100112                "\n"+
    101113                tr("Select either:")+"\n"+
     114                tr("* One tagged node, or")+"\n"+
    102115                tr("* One node that is used by more than one way, or")+"\n"+
    103116                tr("* One node that is used by more than one way and one of those ways, or")+"\n"+
    104117                tr("* One way that has one or more nodes that are used by more than one way, or")+"\n"+
     
    106119                "\n"+
    107120                tr("Note: If a way is selected, this way will get fresh copies of the unglued\n"+
    108121                   "nodes and the new nodes will be selected. Otherwise, all ways will get their\n"+
    109                    "own copy and all nodes will be selected.")
    110             );
     122                   "own copy and all nodes will be selected.");
    111123        }
     124       
     125        if(errMsg != null)
     126            JOptionPane.showMessageDialog(Main.parent, errMsg);
     127       
    112128        selectedNode = null;
    113129        selectedWay = null;
    114130        selectedNodes = null;
    115131    }
     132   
     133    /**
     134     * Assumes there is one tagged Node stored in selectedNode that it will try to unglue
     135     * (= copy node and remove all tags from the old one. Relations will not be removed)
     136     */
     137    private void unglueNode(ActionEvent e) {
     138        LinkedList<Command> cmds = new LinkedList<Command>();
    116139
     140        Node c = new Node(selectedNode);
     141        c.keys = null;
     142        c.tagged = false;
     143        c.selected = false;
     144        cmds.add(new ChangeCommand(selectedNode, c));
     145       
     146        Node n = new Node(selectedNode);
     147        n.id = 0;
     148       
     149        // If this wasn't called from menu, place it where the cursor is/was
     150        if(e.getSource() instanceof JPanel) {
     151            MapView mv = Main.map.mapView;
     152            n.eastNorth = mv.getEastNorth(mv.lastMEvent.getX(), mv.lastMEvent.getY());
     153            n.coor = Main.proj.eastNorth2latlon(n.eastNorth);
     154        }
     155       
     156        cmds.add(new AddCommand(n));
     157       
     158        fixRelations(selectedNode, cmds, Collections.singletonList(n));
     159       
     160        Main.main.undoRedo.add(new SequenceCommand(tr("Unglued Node"), cmds));
     161        Main.ds.setSelected(n);
     162        Main.map.mapView.repaint();
     163    }
     164   
    117165    /**
     166     * Checks if selection is suitable for ungluing. This is the case when there's a single,
     167     * tagged node selected that's part of at least one way (ungluing an unconnected node does
     168     * not make sense. Due to the call order in actionPerformed, this is only called when the
     169     * node is only part of one or less ways.
     170     *
     171     * @param The selection to check against
     172     * @return Selection is suitable
     173     */
     174    private boolean checkForUnglueNode(Collection<? extends OsmPrimitive> selection) {
     175        if(selection.size() != 1)
     176            return false;
     177        OsmPrimitive n = (OsmPrimitive) selection.toArray()[0];
     178        if(!(n instanceof Node))
     179            return false;
     180        boolean isPartOfWay = false;
     181        for(Way w : Main.ds.ways) {
     182            if(w.nodes.contains(n)) {
     183                isPartOfWay = true;
     184                break;
     185            }
     186        }
     187        if(!isPartOfWay)
     188            return false;
     189       
     190        selectedNode = (Node)n;
     191        return  selectedNode.tagged;
     192    }
     193
     194    /**
    118195     * Checks if the selection consists of something we can work with.
    119196     * Checks only if the number and type of items selected looks good;
    120197     * does not check whether the selected items are really a valid