Changeset 988 in josm


Ignore:
Timestamp:
2008-09-18T15:19:00+02:00 (16 years ago)
Author:
stoecker
Message:

make advanced object deletion available for outside, so validator can use it

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

Legend:

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

    r850 r988  
    77import java.awt.event.KeyEvent;
    88import java.awt.event.MouseEvent;
    9 import java.util.ArrayList;
    10 import java.util.Collection;
    119import java.util.Collections;
    12 import java.util.HashSet;
    13 import java.util.HashMap;
    14 import java.util.Iterator;
    15 import java.util.LinkedList;
    16 import java.util.List;
    17 
    18 import javax.swing.JOptionPane;
    1910
    2011import org.openstreetmap.josm.Main;
    21 import org.openstreetmap.josm.command.*;
    22 import org.openstreetmap.josm.data.osm.Node;
     12import org.openstreetmap.josm.command.Command;
     13import org.openstreetmap.josm.command.DeleteCommand;
    2314import org.openstreetmap.josm.data.osm.OsmPrimitive;
    24 import org.openstreetmap.josm.data.osm.Way;
    2515import org.openstreetmap.josm.data.osm.WaySegment;
    26 import org.openstreetmap.josm.data.osm.Relation;
    27 import org.openstreetmap.josm.data.osm.RelationMember;
    28 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    29 import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
    3016import org.openstreetmap.josm.gui.MapFrame;
    31 import org.openstreetmap.josm.tools.*;
     17import org.openstreetmap.josm.tools.ImageProvider;
    3218
    3319/**
     
    8874                Command c;
    8975                if (ctrl) {
    90                         c = deleteWithReferences(Main.ds.getSelected());
     76                        c = DeleteCommand.deleteWithReferences(Main.ds.getSelected());
    9177                } else {
    92                         c = delete(Main.ds.getSelected(), !alt);
     78                        c = DeleteCommand.delete(Main.ds.getSelected(), !alt);
    9379                }
    9480                if (c != null) {
     
    9783
    9884                Main.map.repaint();
    99     }
     85        }
    10086
    10187        /**
     
    118104                        if (ws != null) {
    119105                                if (shift) {
    120                                         c = deleteWaySegment(ws);
     106                                        c = DeleteCommand.deleteWaySegment(ws);
    121107                                } else if (ctrl) {
    122                                         c = deleteWithReferences(Collections.singleton((OsmPrimitive)ws.way));
     108                                        c = DeleteCommand.deleteWithReferences(Collections.singleton((OsmPrimitive)ws.way));
    123109                                } else {
    124                                         c = delete(Collections.singleton((OsmPrimitive)ws.way), !alt);
     110                                        c = DeleteCommand.delete(Collections.singleton((OsmPrimitive)ws.way), !alt);
    125111                                }
    126112                        }
    127113                } else if (ctrl) {
    128                         c = deleteWithReferences(Collections.singleton(sel));
     114                        c = DeleteCommand.deleteWithReferences(Collections.singleton(sel));
    129115                } else {
    130                         c = delete(Collections.singleton(sel), !alt);
     116                        c = DeleteCommand.delete(Collections.singleton(sel), !alt);
    131117                }
    132118                if (c != null) {
     
    136122                Main.map.mapView.repaint();
    137123        }
    138 
    139         /**
    140          * Delete the primitives and everything they reference.
    141          *
    142          * If a node is deleted, the node and all ways and relations
    143          * the node is part of are deleted as well.
    144          *
    145          * If a way is deleted, all relations the way is member of are also deleted.
    146          *
    147          * If a way is deleted, only the way and no nodes are deleted.
    148          *
    149          * @param selection The list of all object to be deleted.
    150          * @return command A command to perform the deletions, or null of there is
    151          * nothing to delete.
    152          */
    153         private Command deleteWithReferences(Collection<OsmPrimitive> selection) {
    154                 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
    155                 for (OsmPrimitive osm : selection)
    156                         osm.visit(v);
    157                 v.data.addAll(selection);
    158                 if (v.data.isEmpty())
    159                         return null;
    160                 return new DeleteCommand(v.data);
    161         }
    162 
    163         /**
    164          * Try to delete all given primitives.
    165          *
    166          * If a node is used by a way, it's removed from that way.  If a node or a
    167          * way is used by a relation, inform the user and do not delete.
    168          *
    169          * If this would cause ways with less than 2 nodes to be created, delete
    170          * these ways instead.  If they are part of a relation, inform the user
    171          * and do not delete.
    172          *
    173          * @param selection The objects to delete.
    174          * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
    175          * @return command A command to perform the deletions, or null of there is
    176          * nothing to delete.
    177          */
    178         private int testRelation(Relation ref, OsmPrimitive osm)
    179         {
    180                 NameVisitor n = new NameVisitor();
    181                 ref.visit(n);
    182                 NameVisitor s = new NameVisitor();
    183                 osm.visit(s);
    184                 String role = new String();
    185                 for (RelationMember m : ref.members)
    186                 {
    187                         if (m.member == osm)
    188                         {
    189                                 role = m.role;
    190                                 break;
    191                         }
    192                 }
    193                 if (role.length() > 0)
    194                 {
    195                         return JOptionPane.showConfirmDialog(Main.parent,
    196                         tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name, n.name, role),
    197                         tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
    198                 }
    199                 else
    200                 {
    201                         return JOptionPane.showConfirmDialog(Main.parent,
    202                         tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
    203                         tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
    204                 }
    205         }
    206 
    207         private Command delete(Collection<OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
    208                 if (selection.isEmpty()) return null;
    209 
    210                 Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
    211                 Collection<Way> waysToBeChanged = new HashSet<Way>();
    212                 HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
    213 
    214                 if (alsoDeleteNodesInWay) {
    215                         // Delete untagged nodes that are to be unreferenced.
    216                         Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
    217                         for (OsmPrimitive osm : del) {
    218                                 if (osm instanceof Way) {
    219                                         for (Node n : ((Way)osm).nodes) {
    220                                                 if (!n.tagged) {
    221                                                         CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
    222                                                         n.visit(v);
    223                                                         v.data.removeAll(del);
    224                                                         if (v.data.isEmpty()) {
    225                                                                 delNodes.add(n);
    226                                                         }
    227                                                 }
    228                                         }
    229                                 }
    230                         }
    231                         del.addAll(delNodes);
    232                 }
    233                
    234                 for (OsmPrimitive osm : del) {
    235                         CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
    236                         osm.visit(v);
    237                         for (OsmPrimitive ref : v.data) {
    238                                 if (del.contains(ref)) continue;
    239                                 if (ref instanceof Way) {
    240                                         waysToBeChanged.add((Way) ref);
    241                                 } else if (ref instanceof Relation) {
    242                                         if (testRelation((Relation)ref, osm) == JOptionPane.YES_OPTION)
    243                                         {
    244                                                 Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
    245                                                 if(relset == null) relset = new HashSet<OsmPrimitive>();
    246                                                 relset.add(osm);
    247                                                 relationsToBeChanged.put(ref, relset);
    248                                         }
    249                                         else
    250                                                 return null;
    251                                 } else {
    252                                         return null;
    253                                 }
    254                         }
    255                 }
    256 
    257                 Collection<Command> cmds = new LinkedList<Command>();
    258                 for (Way w : waysToBeChanged) {
    259                         Way wnew = new Way(w);
    260                         wnew.nodes.removeAll(del);
    261                         if (wnew.nodes.size() < 2) {
    262                                 del.add(w);
    263 
    264                                 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
    265                                 w.visit(v);
    266                                 for (OsmPrimitive ref : v.data) {
    267                                         if (del.contains(ref)) continue;
    268                                         if (ref instanceof Relation) {
    269                                                 Boolean found = false;
    270                                                 Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
    271                                                 if (relset == null)
    272                                                         relset = new HashSet<OsmPrimitive>();
    273                                                 else
    274                                                 {
    275                                                         for (OsmPrimitive m : relset) {
    276                                                                 if(m == w)
    277                                                                 {
    278                                                                         found = true;
    279                                                                         break;
    280                                                                 }
    281                                                         }
    282                                                 }
    283                                                 if (!found)
    284                                                 {
    285                                                         if (testRelation((Relation)ref, w) == JOptionPane.YES_OPTION)
    286                                                         {
    287                                                                 relset.add(w);
    288                                                                 relationsToBeChanged.put(ref, relset);
    289                                                         }
    290                                                         else
    291                                                                 return null;
    292                                                 }
    293                                         } else {
    294                                                 return null;
    295                                         }
    296                                 }
    297                         } else {
    298                                 cmds.add(new ChangeCommand(w, wnew));
    299                         }
    300                 }
    301 
    302                 Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
    303                 while(iterator.hasNext())
    304                 {
    305                         Relation cur = (Relation)iterator.next();
    306                         Relation rel = new Relation(cur);
    307                         for(OsmPrimitive osm : relationsToBeChanged.get(cur))
    308                         {
    309                                 for (RelationMember rm : rel.members) {
    310                                         if (rm.member == osm)
    311                                         {
    312                                                 RelationMember mem = new RelationMember();
    313                                                 mem.role = rm.role;
    314                                                 mem.member = rm.member;
    315                                                 rel.members.remove(mem);
    316                                                 break;
    317                                         }
    318                                 }
    319                         }
    320                         cmds.add(new ChangeCommand(cur, rel));
    321                 }
    322 
    323                 if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
    324 
    325                 return new SequenceCommand(tr("Delete"), cmds);
    326         }
    327 
    328         private Command deleteWaySegment(WaySegment ws) {
    329                 List<Node> n1 = new ArrayList<Node>(),
    330                         n2 = new ArrayList<Node>();
    331 
    332                 n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
    333                 n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
    334 
    335                 if (n1.size() < 2 && n2.size() < 2) {
    336                         return new DeleteCommand(Collections.singleton(ws.way));
    337                 }
    338                
    339                 Way wnew = new Way(ws.way);
    340                 wnew.nodes.clear();
    341 
    342                 if (n1.size() < 2) {
    343                         wnew.nodes.addAll(n2);
    344                         return new ChangeCommand(ws.way, wnew);
    345                 } else if (n2.size() < 2) {
    346                         wnew.nodes.addAll(n1);
    347                         return new ChangeCommand(ws.way, wnew);
    348                 } else {
    349                         Collection<Command> cmds = new LinkedList<Command>();
    350 
    351                         wnew.nodes.addAll(n1);
    352                         cmds.add(new ChangeCommand(ws.way, wnew));
    353 
    354                         Way wnew2 = new Way();
    355                         if (wnew.keys != null) {
    356                                 wnew2.keys = new HashMap<String, String>(wnew.keys);
    357                                 wnew2.checkTagged();
    358                                 wnew2.checkDirectionTagged();
    359                         }
    360                         wnew2.nodes.addAll(n2);
    361                         cmds.add(new AddCommand(wnew2));
    362 
    363                         return new SequenceCommand(tr("Split way segment"), cmds);
    364                 }
    365         }
    366124       
    367125        @Override public String getModeHelpText() {
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r755 r988  
    55import static org.openstreetmap.josm.tools.I18n.trn;
    66
     7import java.util.ArrayList;
    78import java.util.Collection;
    89import java.util.Collections;
     10import java.util.HashMap;
     11import java.util.HashSet;
     12import java.util.Iterator;
     13import java.util.LinkedList;
     14import java.util.List;
    915
    1016import javax.swing.JLabel;
     17import javax.swing.JOptionPane;
    1118import javax.swing.tree.DefaultMutableTreeNode;
    1219import javax.swing.tree.MutableTreeNode;
    1320
     21import org.openstreetmap.josm.Main;
     22import org.openstreetmap.josm.data.osm.Node;
    1423import org.openstreetmap.josm.data.osm.OsmPrimitive;
     24import org.openstreetmap.josm.data.osm.Relation;
     25import org.openstreetmap.josm.data.osm.RelationMember;
     26import org.openstreetmap.josm.data.osm.Way;
     27import org.openstreetmap.josm.data.osm.WaySegment;
     28import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    1529import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
    1630import org.openstreetmap.josm.tools.ImageProvider;
     
    8498                return root;
    8599        }
     100
     101        /**
     102         * Delete the primitives and everything they reference.
     103         *
     104         * If a node is deleted, the node and all ways and relations
     105         * the node is part of are deleted as well.
     106         *
     107         * If a way is deleted, all relations the way is member of are also deleted.
     108         *
     109         * If a way is deleted, only the way and no nodes are deleted.
     110         *
     111         * @param selection The list of all object to be deleted.
     112         * @return command A command to perform the deletions, or null of there is
     113         * nothing to delete.
     114         */
     115        public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
     116                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
     117                for (OsmPrimitive osm : selection)
     118                        osm.visit(v);
     119                v.data.addAll(selection);
     120                if (v.data.isEmpty())
     121                        return null;
     122                return new DeleteCommand(v.data);
     123        }
     124
     125        /**
     126         * Try to delete all given primitives.
     127         *
     128         * If a node is used by a way, it's removed from that way.  If a node or a
     129         * way is used by a relation, inform the user and do not delete.
     130         *
     131         * If this would cause ways with less than 2 nodes to be created, delete
     132         * these ways instead.  If they are part of a relation, inform the user
     133         * and do not delete.
     134         *
     135         * @param selection The objects to delete.
     136         * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
     137         * @return command A command to perform the deletions, or null of there is
     138         * nothing to delete.
     139         */
     140        private static int testRelation(Relation ref, OsmPrimitive osm)
     141        {
     142                NameVisitor n = new NameVisitor();
     143                ref.visit(n);
     144                NameVisitor s = new NameVisitor();
     145                osm.visit(s);
     146                String role = new String();
     147                for (RelationMember m : ref.members)
     148                {
     149                        if (m.member == osm)
     150                        {
     151                                role = m.role;
     152                                break;
     153                        }
     154                }
     155                if (role.length() > 0)
     156                {
     157                        return JOptionPane.showConfirmDialog(Main.parent,
     158                        tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name, n.name, role),
     159                        tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     160                }
     161                else
     162                {
     163                        return JOptionPane.showConfirmDialog(Main.parent,
     164                        tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
     165                        tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     166                }
     167        }
     168
     169        public static Command delete(Collection<? extends OsmPrimitive> selection)
     170        {
     171                return delete(selection, true);
     172        }
     173
     174        public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     175                if (selection.isEmpty()) return null;
     176
     177                Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
     178                Collection<Way> waysToBeChanged = new HashSet<Way>();
     179                HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
     180
     181                if (alsoDeleteNodesInWay) {
     182                        // Delete untagged nodes that are to be unreferenced.
     183                        Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
     184                        for (OsmPrimitive osm : del) {
     185                                if (osm instanceof Way) {
     186                                        for (Node n : ((Way)osm).nodes) {
     187                                                if (!n.tagged) {
     188                                                        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     189                                                        n.visit(v);
     190                                                        v.data.removeAll(del);
     191                                                        if (v.data.isEmpty()) {
     192                                                                delNodes.add(n);
     193                                                        }
     194                                                }
     195                                        }
     196                                }
     197                        }
     198                        del.addAll(delNodes);
     199                }
     200               
     201                for (OsmPrimitive osm : del) {
     202                        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     203                        osm.visit(v);
     204                        for (OsmPrimitive ref : v.data) {
     205                                if (del.contains(ref)) continue;
     206                                if (ref instanceof Way) {
     207                                        waysToBeChanged.add((Way) ref);
     208                                } else if (ref instanceof Relation) {
     209                                        if (testRelation((Relation)ref, osm) == JOptionPane.YES_OPTION)
     210                                        {
     211                                                Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     212                                                if(relset == null) relset = new HashSet<OsmPrimitive>();
     213                                                relset.add(osm);
     214                                                relationsToBeChanged.put(ref, relset);
     215                                        }
     216                                        else
     217                                                return null;
     218                                } else {
     219                                        return null;
     220                                }
     221                        }
     222                }
     223
     224                Collection<Command> cmds = new LinkedList<Command>();
     225                for (Way w : waysToBeChanged) {
     226                        Way wnew = new Way(w);
     227                        wnew.nodes.removeAll(del);
     228                        if (wnew.nodes.size() < 2) {
     229                                del.add(w);
     230
     231                                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     232                                w.visit(v);
     233                                for (OsmPrimitive ref : v.data) {
     234                                        if (del.contains(ref)) continue;
     235                                        if (ref instanceof Relation) {
     236                                                Boolean found = false;
     237                                                Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     238                                                if (relset == null)
     239                                                        relset = new HashSet<OsmPrimitive>();
     240                                                else
     241                                                {
     242                                                        for (OsmPrimitive m : relset) {
     243                                                                if(m == w)
     244                                                                {
     245                                                                        found = true;
     246                                                                        break;
     247                                                                }
     248                                                        }
     249                                                }
     250                                                if (!found)
     251                                                {
     252                                                        if (testRelation((Relation)ref, w) == JOptionPane.YES_OPTION)
     253                                                        {
     254                                                                relset.add(w);
     255                                                                relationsToBeChanged.put(ref, relset);
     256                                                        }
     257                                                        else
     258                                                                return null;
     259                                                }
     260                                        } else {
     261                                                return null;
     262                                        }
     263                                }
     264                        } else {
     265                                cmds.add(new ChangeCommand(w, wnew));
     266                        }
     267                }
     268
     269                Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
     270                while(iterator.hasNext())
     271                {
     272                        Relation cur = (Relation)iterator.next();
     273                        Relation rel = new Relation(cur);
     274                        for(OsmPrimitive osm : relationsToBeChanged.get(cur))
     275                        {
     276                                for (RelationMember rm : rel.members) {
     277                                        if (rm.member == osm)
     278                                        {
     279                                                RelationMember mem = new RelationMember();
     280                                                mem.role = rm.role;
     281                                                mem.member = rm.member;
     282                                                rel.members.remove(mem);
     283                                                break;
     284                                        }
     285                                }
     286                        }
     287                        cmds.add(new ChangeCommand(cur, rel));
     288                }
     289
     290                if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
     291
     292                return new SequenceCommand(tr("Delete"), cmds);
     293        }
     294
     295        public static Command deleteWaySegment(WaySegment ws) {
     296                List<Node> n1 = new ArrayList<Node>(),
     297                        n2 = new ArrayList<Node>();
     298
     299                n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
     300                n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
     301
     302                if (n1.size() < 2 && n2.size() < 2) {
     303                        return new DeleteCommand(Collections.singleton(ws.way));
     304                }
     305               
     306                Way wnew = new Way(ws.way);
     307                wnew.nodes.clear();
     308
     309                if (n1.size() < 2) {
     310                        wnew.nodes.addAll(n2);
     311                        return new ChangeCommand(ws.way, wnew);
     312                } else if (n2.size() < 2) {
     313                        wnew.nodes.addAll(n1);
     314                        return new ChangeCommand(ws.way, wnew);
     315                } else {
     316                        Collection<Command> cmds = new LinkedList<Command>();
     317
     318                        wnew.nodes.addAll(n1);
     319                        cmds.add(new ChangeCommand(ws.way, wnew));
     320
     321                        Way wnew2 = new Way();
     322                        if (wnew.keys != null) {
     323                                wnew2.keys = new HashMap<String, String>(wnew.keys);
     324                                wnew2.checkTagged();
     325                                wnew2.checkDirectionTagged();
     326                        }
     327                        wnew2.nodes.addAll(n2);
     328                        cmds.add(new AddCommand(wnew2));
     329
     330                        return new SequenceCommand(tr("Split way segment"), cmds);
     331                }
     332        }
    86333}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationEditor.java

    r810 r988  
    320320                tr("Highlight the member from the current table row as JOSM's selection"), KeyEvent.VK_S, new ActionListener() {
    321321                        public void actionPerformed(ActionEvent e) {
    322                                 int[] rows = memberTable.getSelectedRows();
    323                                 ArrayList<OsmPrimitive> sel = new ArrayList<OsmPrimitive>(rows.length);
    324                                 for (int i : rows) { sel.add((OsmPrimitive)memberTable.getValueAt(i, 1)); }
     322                                ArrayList<OsmPrimitive> sel;
     323                                int cnt = memberTable.getSelectedRowCount();
     324                                if(cnt > 0)
     325                                {
     326                                        sel = new ArrayList<OsmPrimitive>(cnt);
     327                                        for (int i : memberTable.getSelectedRows())
     328                                                sel.add((OsmPrimitive)memberTable.getValueAt(i, 1));
     329                                }
     330                                else
     331                                {
     332                                        cnt = memberTable.getRowCount();
     333                                        sel = new ArrayList<OsmPrimitive>(cnt);
     334                                        for (int i = 0; i < cnt; ++i)
     335                                                sel.add((OsmPrimitive)memberTable.getValueAt(i, 1));
     336                                }
    325337                                Main.ds.setSelected(sel);
    326338                        }
Note: See TracChangeset for help on using the changeset viewer.