Ticket #5133: 0001-Action-to-disconnect-nodes-from-ways.2.patch

File 0001-Action-to-disconnect-nodes-from-ways.2.patch, 9.0 KB (added by gbilotta <giuseppe.bilotta@…>, 6 years ago)

Feature implementation, v2

  • new file 2001

    From 03e9aed1bfbefae55e465540055ed716d6de071e Mon Sep 17 00:00:00 2001
    From: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
    Date: Mon, 29 Jul 2013 08:29:30 +0200
    Subject: [PATCH] Action to disconnect nodes from ways
    
    ---
     images/unjoinnodeway.png                           | Bin 0 -> 385 bytes
     .../josm/actions/UnJoinNodeWayAction.java          | 143 +++++++++++++++++++++
     src/org/openstreetmap/josm/gui/MainMenu.java       |   3 +
     3 files changed, 146 insertions(+)
     create mode 100644 images/unjoinnodeway.png
     create mode 100644 src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java
    
    diff --git a/images/unjoinnodeway.png b/images/unjoinnodeway.png
    new file mode 100644
    index 0000000000000000000000000000000000000000..4179e6902577640d66deab6f78cab43c8b0a4786
    GIT binary patch
    literal 385
    zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b
    z3=G`DAk4@xYYs>cdx@v7EBjq`Ssnvp>D3WU3=E8Xo-U3d9>?Ea-s{H{D8Tx_-@z~{
    zQbL-=Y@@jL+J&1w&#Y0FW4M3d$h{-1Nl7Lf4FegKvp1VZhPx;oS@AHWxc=Ns<Kp)p
    zOv7|H9x+*?<D`-oHu;T})$8@iElW0NEdT1~zxOitX|8JvOqjPf<X$oGu;iWdKtc5M
    zVwqjRvx1(<nF%};*nPvjr+7<Ym-UxjYj1rq@0fj6Wy+1*t1jt(rArDLPw$A#ea<8E
    zkjq~qN!|FXb4;?uTG!(h9;|K)&mVNy^}pkJPlmx9mUFvVb{fSO&gW7Q=Ha<y?WuN<
    zeM(XM>PdD13OpY_bvE99@ag*bi}z>$`QKZlmY48ZeUjL|S_|fFVharAyNW+4_gt>9
    cd3i{>Jl~Te!YJi0Ft8XrUHx3vIVCg!02-y3CIA2c
  • new file src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java

    literal 0
    HcmV?d00001
    
    diff --git a/src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java b/src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java
    new file mode 100644
    index 0000000..6ee837c
    - +  
     1//License: GPL. Copyright 2007 by Immanuel Scholz and others
     2package org.openstreetmap.josm.actions;
     3
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6import static org.openstreetmap.josm.tools.I18n.trn;
     7
     8import java.awt.event.ActionEvent;
     9import java.awt.event.KeyEvent;
     10import java.util.ArrayList;
     11import java.util.Collection;
     12import java.util.Collections;
     13import java.util.HashSet;
     14import java.util.Iterator;
     15import java.util.List;
     16
     17import javax.swing.JOptionPane;
     18
     19import org.openstreetmap.josm.Main;
     20import org.openstreetmap.josm.command.ChangeNodesCommand;
     21import org.openstreetmap.josm.command.Command;
     22import org.openstreetmap.josm.data.osm.Node;
     23import org.openstreetmap.josm.data.osm.OsmPrimitive;
     24import org.openstreetmap.josm.data.osm.Way;
     25import org.openstreetmap.josm.tools.Shortcut;
     26
     27public class UnJoinNodeWayAction extends JosmAction {
     28    public UnJoinNodeWayAction() {
     29        super(tr("Disconnect Node from Way"), "unjoinnodeway",
     30                tr("Disconnect nodes from a way they currently belong to"),
     31                Shortcut.registerShortcut("tools:unjoinnodeway",
     32                    tr("Tool: {0}", tr("Disconnect Node from Way")), KeyEvent.VK_J, Shortcut.ALT), true);
     33        putValue("help", ht("/Action/UnJoinNodeWay"));
     34    }
     35
     36    @Override
     37    public void actionPerformed(ActionEvent e) {
     38
     39        Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
     40
     41        List<Node> selectedNodes = OsmPrimitive.getFilteredList(selection, Node.class);
     42        List<Way> selectedWays = OsmPrimitive.getFilteredList(selection, Way.class);
     43        List<Way> applicableWays = getApplicableWays(selectedWays, selectedNodes);
     44
     45        if (applicableWays == null) {
     46            JOptionPane.showMessageDialog(
     47                    Main.parent,
     48                    tr("Select at least one node to be disconnected."),
     49                    tr("Warning"),
     50                    JOptionPane.WARNING_MESSAGE);
     51            return;
     52        } else if (applicableWays.isEmpty()) {
     53            JOptionPane.showMessageDialog(Main.parent,
     54                    trn("Selected node cannot be disconnected from anything.",
     55                        "Selected nodes cannot be disconnected from anything.",
     56                        selectedNodes.size()),
     57                    tr("Warning"),
     58                    JOptionPane.WARNING_MESSAGE);
     59            return;
     60        } else if (applicableWays.size() > 1) {
     61            JOptionPane.showMessageDialog(Main.parent,
     62                    trn("There is more than one way using the node you selected. Please select the way also.",
     63                        "There is more than one way using the nodes you selected. Please select the way also.",
     64                        selectedNodes.size()),
     65                    tr("Warning"),
     66                    JOptionPane.WARNING_MESSAGE);
     67            return;
     68        } else if (applicableWays.get(0).getRealNodesCount() < selectedNodes.size() + 2) {
     69            // there is only one affected way, but removing the selected nodes would only leave it
     70            // with less than 2 nodes
     71            JOptionPane.showMessageDialog(Main.parent,
     72                    trn("The affected way would disappear after disconnecting the selected node.",
     73                        "The affected way would disappear after disconnecting the selected nodes.",
     74                        selectedNodes.size()),
     75                    tr("Warning"),
     76                    JOptionPane.WARNING_MESSAGE);
     77            return;
     78        }
     79
     80
     81        // Finally, applicableWays contains only one perfect way
     82        Way selectedWay = applicableWays.get(0);
     83
     84        // I'm sure there's a better way to handle this
     85        List<Node> orgNodes = selectedWay.getNodes();
     86        selectedWay.removeNodes(new HashSet<Node>(selectedNodes));
     87        List<Node> newNodes = selectedWay.getNodes();
     88        selectedWay.setNodes(orgNodes);
     89        Main.main.undoRedo.add(new ChangeNodesCommand(selectedWay, newNodes));
     90        Main.map.repaint();
     91    }
     92
     93    // Find ways to which the disconnect can be applied. This is the list of ways with more
     94    // than two nodes which pass through all the given nodes, intersected with the selected ways (if any)
     95    private List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) {
     96        if (selectedNodes.isEmpty())
     97            return null;
     98
     99        // List of ways shared by all nodes
     100        List<Way> result = new ArrayList<Way>(OsmPrimitive.getFilteredList(selectedNodes.get(0).getReferrers(), Way.class));
     101        for (int i=1; i<selectedNodes.size(); i++) {
     102            List<OsmPrimitive> ref = selectedNodes.get(i).getReferrers();
     103            for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     104                if (!ref.contains(it.next())) {
     105                    it.remove();
     106                }
     107            }
     108        }
     109
     110        // Remove broken ways
     111        for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     112            if (it.next().getNodesCount() <= 2) {
     113                it.remove();
     114            }
     115        }
     116
     117        if (selectedWays.isEmpty())
     118            return result;
     119        else {
     120            // Return only selected ways
     121            for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     122                if (!selectedWays.contains(it.next())) {
     123                    it.remove();
     124                }
     125            }
     126            return result;
     127        }
     128    }
     129
     130    @Override
     131    protected void updateEnabledState() {
     132        if (getCurrentDataSet() == null) {
     133            setEnabled(false);
     134        } else {
     135            updateEnabledState(getCurrentDataSet().getSelected());
     136        }
     137    }
     138
     139    @Override
     140    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
     141        setEnabled(selection != null && !selection.isEmpty());
     142    }
     143}
  • src/org/openstreetmap/josm/gui/MainMenu.java

    diff --git a/src/org/openstreetmap/josm/gui/MainMenu.java b/src/org/openstreetmap/josm/gui/MainMenu.java
    index 196e16e..dc75be8 100644
    a b import org.openstreetmap.josm.actions.SimplifyWayAction; 
    8484import org.openstreetmap.josm.actions.SplitWayAction;
    8585import org.openstreetmap.josm.actions.ToggleGPXLinesAction;
    8686import org.openstreetmap.josm.actions.UnGlueAction;
     87import org.openstreetmap.josm.actions.UnJoinNodeWayAction;
    8788import org.openstreetmap.josm.actions.UndoAction;
    8889import org.openstreetmap.josm.actions.UnselectAllAction;
    8990import org.openstreetmap.josm.actions.UpdateDataAction;
    public class MainMenu extends JMenuBar { 
    185186    public final JosmAction createCircle = new CreateCircleAction();
    186187    public final JosmAction mergeNodes = new MergeNodesAction();
    187188    public final JosmAction joinNodeWay = new JoinNodeWayAction();
     189    public final JosmAction unJoinNodeWay = new UnJoinNodeWayAction();
    188190    public final JosmAction unglueNodes = new UnGlueAction();
    189191    public final JosmAction simplifyWay = new SimplifyWayAction();
    190192    public final JosmAction joinAreas = new JoinAreasAction();
    public class MainMenu extends JMenuBar { 
    603605        toolsMenu.addSeparator();
    604606        add(toolsMenu, mergeNodes);
    605607        add(toolsMenu, joinNodeWay);
     608        add(toolsMenu, unJoinNodeWay);
    606609        add(toolsMenu, unglueNodes);
    607610        toolsMenu.addSeparator();
    608611        add(toolsMenu, joinAreas);