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


Ignore:
Timestamp:
2010-07-29T08:22:51+02:00 (14 years ago)
Author:
jttt
Message:

Allow SplitWayAction to work also when some non related ways are selected.

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

Legend:

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

    r3156 r3392  
    1010import java.util.ArrayList;
    1111import java.util.Collection;
    12 import java.util.HashMap;
    1312import java.util.HashSet;
    1413import java.util.Iterator;
    1514import java.util.LinkedList;
    1615import java.util.List;
    17 import java.util.Map;
    1816import java.util.Set;
    19 import java.util.Map.Entry;
    2017
    2118import javax.swing.JOptionPane;
     
    9895        List<Node> selectedNodes = OsmPrimitive.getFilteredList(selection, Node.class);
    9996        List<Way> selectedWays = OsmPrimitive.getFilteredList(selection, Way.class);
    100 
    101         if (!checkSelection(selection)) {
     97        List<Relation> selectedRelations = OsmPrimitive.getFilteredList(selection, Relation.class);
     98        List<Way> applicableWays = getApplicableWays(selectedWays, selectedNodes);
     99
     100        if (applicableWays == null) {
    102101            JOptionPane.showMessageDialog(
    103102                    Main.parent,
    104                     tr("The current selection cannot be used for splitting."),
     103                    tr("The current selection cannot be used for splitting - no node is selected."),
    105104                    tr("Warning"),
    106                     JOptionPane.WARNING_MESSAGE
    107             );
     105                    JOptionPane.WARNING_MESSAGE);
    108106            return;
    109         }
    110 
    111 
    112         Way selectedWay = null;
    113         if (!selectedWays.isEmpty()){
    114             selectedWay = selectedWays.get(0);
    115         }
    116 
    117         // If only nodes are selected, try to guess which way to split. This works if there
    118         // is exactly one way that all nodes are part of.
    119         if (selectedWay == null && !selectedNodes.isEmpty()) {
    120             Map<Way, Integer> wayOccurenceCounter = new HashMap<Way, Integer>();
    121             for (Node n : selectedNodes) {
    122                 for (Way w : OsmPrimitive.getFilteredList(n.getReferrers(), Way.class)) {
    123                     if (!w.isUsable()) {
    124                         continue;
    125                     }
     107        } else if (applicableWays.isEmpty()) {
     108            JOptionPane.showMessageDialog(Main.parent,
     109                    tr("The selected nodes do not share the same way."),
     110                    tr("Warning"),
     111                    JOptionPane.WARNING_MESSAGE);
     112            return;
     113        }
     114
     115        { // Remove ways that doesn't have selected node in the middle
     116            Iterator<Way> it = applicableWays.iterator();
     117            WAY_LOOP:
     118                while (it.hasNext()) {
     119                    Way w = it.next();
     120                    assert w.isUsable(); // Way is referrer of selected node(s) so it must be usable
    126121                    int last = w.getNodesCount() - 1;
    127                     if (last <= 0) {
    128                         continue; // zero or one node ways
    129                     }
    130122                    boolean circular = w.isClosed();
    131                     int i = 0;
    132                     for (Node wn : w.getNodes()) {
    133                         if ((circular || (i > 0 && i < last)) && n.equals(wn)) {
    134                             Integer old = wayOccurenceCounter.get(w);
    135                             wayOccurenceCounter.put(w, (old == null) ? 1 : old + 1);
    136                             break;
     123
     124                    for (Node n : selectedNodes) {
     125                        int i = w.getNodes().indexOf(n);
     126                        if (!(circular || (i > 0 && i < last))) {
     127                            it.remove();
     128                            continue WAY_LOOP;
    137129                        }
    138                         i++;
    139130                    }
    140131                }
    141             }
    142             if (wayOccurenceCounter.isEmpty()) {
    143                 JOptionPane.showMessageDialog(Main.parent,
    144                         trn("The selected node is not in the middle of any way.",
    145                                 "The selected nodes are not in the middle of any way.",
    146                                 selectedNodes.size()),
    147                                 tr("Warning"),
    148                                 JOptionPane.WARNING_MESSAGE);
    149                 return;
    150             }
    151 
    152             for (Entry<Way, Integer> entry : wayOccurenceCounter.entrySet()) {
    153                 if (entry.getValue().equals(selectedNodes.size())) {
    154                     if (selectedWay != null) {
    155                         JOptionPane.showMessageDialog(Main.parent,
    156                                 trn("There is more than one way using the node you selected. Please select the way also.",
    157                                         "There is more than one way using the nodes you selected. Please select the way also.",
    158                                         selectedNodes.size()),
    159                                         tr("Warning"),
    160                                         JOptionPane.WARNING_MESSAGE);
    161                         return;
    162                     }
    163                     selectedWay = entry.getKey();
    164                 }
    165             }
    166 
    167             if (selectedWay == null) {
    168                 JOptionPane.showMessageDialog(Main.parent,
    169                         tr("The selected nodes do not share the same way."),
    170                         tr("Warning"),
    171                         JOptionPane.WARNING_MESSAGE);
    172                 return;
    173             }
    174 
    175             // If a way and nodes are selected, verify that the nodes are part of the way.
    176         } else if (selectedWay != null && !selectedNodes.isEmpty()) {
    177 
    178             HashSet<Node> nds = new HashSet<Node>(selectedNodes);
    179             nds.removeAll(selectedWay.getNodes());
    180             if (!nds.isEmpty()) {
    181                 JOptionPane.showMessageDialog(Main.parent,
    182                         trn("The selected way does not contain the selected node.",
    183                                 "The selected way does not contain all the selected nodes.",
    184                                 selectedNodes.size()),
    185                                 tr("Warning"),
    186                                 JOptionPane.WARNING_MESSAGE);
    187                 return;
    188             }
    189         }
     132        }
     133
     134        if (applicableWays.isEmpty()) {
     135            JOptionPane.showMessageDialog(Main.parent,
     136                    trn("The selected node is not in the middle of any way.",
     137                            "The selected nodes are not in the middle of any way.",
     138                            selectedNodes.size()),
     139                            tr("Warning"),
     140                            JOptionPane.WARNING_MESSAGE);
     141            return;
     142        } else if (applicableWays.size() > 1) {
     143            JOptionPane.showMessageDialog(Main.parent,
     144                    trn("There is more than one way using the node you selected. Please select the way also.",
     145                            "There is more than one way using the nodes you selected. Please select the way also.",
     146                            selectedNodes.size()),
     147                            tr("Warning"),
     148                            JOptionPane.WARNING_MESSAGE);
     149            return;
     150        }
     151
     152        // Finally, applicableWays contains only one perfect way
     153        Way selectedWay = applicableWays.get(0);
    190154
    191155        List<List<Node>> wayChunks = buildSplitChunks(selectedWay, selectedNodes);
    192156        if (wayChunks != null) {
    193             SplitWayResult result = splitWay(getEditLayer(),selectedWay, wayChunks);
     157            List<OsmPrimitive> sel = new ArrayList<OsmPrimitive>(selectedWays.size() + selectedRelations.size());
     158            sel.addAll(selectedWays);
     159            sel.addAll(selectedRelations);
     160            SplitWayResult result = splitWay(getEditLayer(),selectedWay, wayChunks, sel);
    194161            Main.main.undoRedo.add(result.getCommand());
    195162            getCurrentDataSet().setSelected(result.getNewSelection());
     
    197164    }
    198165
    199     /**
    200      * Checks if the selection consists of something we can work with.
    201      * Checks only if the number and type of items selected looks good;
    202      * does not check whether the selected items are really a valid
    203      * input for splitting (this would be too expensive to be carried
    204      * out from the selectionChanged listener).
    205      */
    206     private boolean checkSelection(Collection<? extends OsmPrimitive> selection) {
    207         boolean way = false;
    208         boolean node = false;
    209         for (OsmPrimitive p : selection) {
    210             if (p instanceof Way && !way) {
    211                 way = true;
    212             } else if (p instanceof Node) {
    213                 node = true;
    214             } else
    215                 return false;
    216         }
    217         return node;
     166    private List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) {
     167        if (selectedNodes.isEmpty())
     168            return null;
     169
     170        // List of ways shared by all nodes
     171        List<Way> result = new ArrayList<Way>(OsmPrimitive.getFilteredList(selectedNodes.get(0).getReferrers(), Way.class));
     172        for (int i=1; i<selectedNodes.size(); i++) {
     173            Iterator<Way> it = result.iterator();
     174            List<OsmPrimitive> ref = selectedNodes.get(i).getReferrers();
     175            while (it.hasNext()) {
     176                if (!ref.contains(it.next())) {
     177                    it.remove();
     178                }
     179            }
     180        }
     181
     182        { // Remove broken ways
     183            Iterator<Way> it = result.iterator();
     184            while (it.hasNext()) {
     185                if (it.next().getNodesCount() <= 2) {
     186                    it.remove();
     187                }
     188            }
     189        }
     190
     191        if (selectedWays.isEmpty())
     192            return result;
     193        else {
     194            // Return only selected ways
     195            Iterator<Way> it = result.iterator();
     196            while (it.hasNext()) {
     197                if (!selectedWays.contains(it.next())) {
     198                    it.remove();
     199                }
     200            }
     201            return result;
     202        }
     203
    218204    }
    219205
     
    301287     * @return
    302288     */
    303     public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks) {
     289    public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks, Collection<? extends OsmPrimitive> selection) {
    304290        // build a list of commands, and also a new selection list
    305291        Collection<Command> commandList = new ArrayList<Command>(wayChunks.size());
    306         List<Way> newSelection = new ArrayList<Way>(wayChunks.size());
     292        List<OsmPrimitive> newSelection = new ArrayList<OsmPrimitive>(selection.size() + wayChunks.size());
     293        newSelection.addAll(selection);
    307294
    308295        Iterator<List<Node>> chunkIt = wayChunks.iterator();
     
    312299        changedWay.setNodes(chunkIt.next());
    313300        commandList.add(new ChangeCommand(way, changedWay));
    314         newSelection.add(way);
     301        if (!newSelection.contains(way)) {
     302            newSelection.add(way);
     303        }
    315304
    316305        List<Way> newWays = new ArrayList<Way>();
     
    495484     * @return the result from the split operation
    496485     */
    497     static public SplitWayResult split(OsmDataLayer layer, Way way, List<Node> atNodes){
     486    static public SplitWayResult split(OsmDataLayer layer, Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection){
    498487        List<List<Node>> chunks = buildSplitChunks(way, atNodes);
    499488        if (chunks == null) return null;
    500         return splitWay(layer,way, chunks);
     489        return splitWay(layer,way, chunks, selection);
    501490    }
    502491
     
    516505            return;
    517506        }
    518         setEnabled(checkSelection(selection));
     507        for (OsmPrimitive primitive: selection) {
     508            if (primitive instanceof Node) {
     509                setEnabled(true); // Selection still can be wrong, but let SplitWayAction process and tell user what's wrong
     510                return;
     511            }
     512        }
     513        setEnabled(false);
    519514    }
    520515}
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r3336 r3392  
    2323import javax.swing.JOptionPane;
    2424import javax.swing.JPanel;
    25 import javax.swing.tree.DefaultMutableTreeNode;
    26 import javax.swing.tree.MutableTreeNode;
    2725
    2826import org.openstreetmap.josm.Main;
     
    185183
    186184    @Override public Collection<PseudoCommand> getChildren() {
    187         if (toDelete.size() == 1) {
     185        if (toDelete.size() == 1)
    188186            return null;
    189         } else {
     187        else {
    190188            List<PseudoCommand> children = new ArrayList<PseudoCommand>();
    191189            for (final OsmPrimitive osm : toDelete) {
     
    193191                    @Override public JLabel getDescription() {
    194192                        return new JLabel(
    195                             tr("Deleted ''{0}''",
    196                                 osm.getDisplayName(DefaultNameFormatter.getInstance())),
    197                             ImageProvider.get(OsmPrimitiveType.from(osm)), JLabel.HORIZONTAL);
    198                         }
     193                                tr("Deleted ''{0}''",
     194                                        osm.getDisplayName(DefaultNameFormatter.getInstance())),
     195                                        ImageProvider.get(OsmPrimitiveType.from(osm)), JLabel.HORIZONTAL);
     196                    }
    199197                    @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
    200198                        return Collections.singleton(osm);
     
    425423            chunks.add(n1);
    426424            chunks.add(n2);
    427             return SplitWayAction.splitWay(layer,ws.way, chunks).getCommand();
     425            return SplitWayAction.splitWay(layer,ws.way, chunks, Collections.<OsmPrimitive>emptyList()).getCommand();
    428426        }
    429427    }
     
    443441        if (a != null) {
    444442            for (OsmPrimitive osm : primitivesToDelete) {
    445                 if (osm.isIncomplete())
     443                if (osm.isIncomplete()) {
    446444                    incomplete = true;
    447                 else if (osm instanceof Node && !osm.isNewOrUndeleted()
    448                 && !a.contains(((Node) osm).getCoor()))
     445                } else if (osm instanceof Node && !osm.isNewOrUndeleted()
     446                        && !a.contains(((Node) osm).getCoor())) {
    449447                    outside = true;
     448                }
    450449            }
    451450        }
     
    453452        {
    454453            for (OsmPrimitive osm : primitivesToDelete)
    455                 if (osm.isIncomplete())
     454                if (osm.isIncomplete()) {
    456455                    incomplete = true;
     456                }
    457457        }
    458458        if(outside)
Note: See TracChangeset for help on using the changeset viewer.