Changeset 1004 in josm


Ignore:
Timestamp:
2008-09-22T03:53:47+02:00 (16 years ago)
Author:
framm
Message:
  • display a confirmation request if user tries to delete data outside downloaded area (can be don't-show-again'd). Note this feature is not a hard measure but needs to be actively requested by the component making the deletion, so it is possible that plugins deleting data do not honour this. Also, this currently only affects deleting, not otherwise modifying stuff outside of the box.
Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r988 r1004  
    55import static org.openstreetmap.josm.tools.I18n.trn;
    66
     7import java.awt.GridBagLayout;
     8import java.awt.geom.Area;
    79import java.util.ArrayList;
    810import java.util.Collection;
     
    1618import javax.swing.JLabel;
    1719import javax.swing.JOptionPane;
     20import javax.swing.JPanel;
    1821import javax.swing.tree.DefaultMutableTreeNode;
    1922import javax.swing.tree.MutableTreeNode;
     
    2831import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    2932import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
     33import org.openstreetmap.josm.tools.DontShowAgainInfo;
     34import org.openstreetmap.josm.tools.GBC;
    3035import org.openstreetmap.josm.tools.ImageProvider;
     36import org.openstreetmap.josm.tools.UrlLabel;
    3137
    3238/**
     
    3642public class DeleteCommand extends Command {
    3743
    38         /**
    39         * The primitive that get deleted.
    40         */
    41         private final Collection<? extends OsmPrimitive> data;
    42 
    43     /** 
     44    /**
     45    * The primitive that get deleted.
     46    */
     47    private final Collection<? extends OsmPrimitive> data;
     48
     49    /**
    4450     * Constructor for a collection of data
    4551     */
    46         public DeleteCommand(Collection<? extends OsmPrimitive> data) {
    47                 this.data = data;
    48         }
    49     /**
    50      * Constructor for a single data item. Use the collection
    51      * constructor to delete multiple objects.
     52    public DeleteCommand(Collection<? extends OsmPrimitive> data) {
     53        this.data = data;
     54    }
     55
     56    /**
     57     * Constructor for a single data item. Use the collection constructor to delete multiple
     58     * objects.
    5259     */
    5360    public DeleteCommand(OsmPrimitive data) {
     
    5562    }
    5663
    57         @Override public boolean executeCommand() {
    58                 super.executeCommand();
    59                 for (OsmPrimitive osm : data) {
    60                         osm.delete(true);
    61                 }
    62                 return true;
    63         }
    64        
    65         @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    66                 deleted.addAll(data);
    67         }
    68 
    69         @Override public MutableTreeNode description() {
    70                 NameVisitor v = new NameVisitor();
    71 
    72                 if (data.size() == 1) {
    73                         data.iterator().next().visit(v);
    74                         return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", v.name, tr(v.className)), v.icon, JLabel.HORIZONTAL));
    75                 }
    76 
    77                 String cname = null;
    78                 String cnamem = null;
    79                 for (OsmPrimitive osm : data) {
    80                         osm.visit(v);
    81                         if (cname == null)
    82                         {
    83                                 cname = v.className;
    84                                 cnamem = v.classNamePlural;
    85                         }
    86                         else if (!cname.equals(v.className))
    87                         {
    88                                 cname = "object";
    89                                 cnamem = trn("object", "objects", 2);
    90                         }
    91                 }
    92                 DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(
    93                                 tr("Delete {0} {1}", data.size(), trn(cname, cnamem, data.size())), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
    94                 for (OsmPrimitive osm : data) {
    95                         osm.visit(v);
    96                         root.add(new DefaultMutableTreeNode(v.toLabel()));
    97                 }
    98                 return root;
    99         }
    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         }
     64    @Override public boolean executeCommand() {
     65        super.executeCommand();
     66        for (OsmPrimitive osm : data) {
     67            osm.delete(true);
     68        }
     69        return true;
     70    }
     71
     72    @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
     73            Collection<OsmPrimitive> added) {
     74        deleted.addAll(data);
     75    }
     76
     77    @Override public MutableTreeNode description() {
     78        NameVisitor v = new NameVisitor();
     79
     80        if (data.size() == 1) {
     81            data.iterator().next().visit(v);
     82            return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", v.name, tr(v.className)), v.icon,
     83                    JLabel.HORIZONTAL));
     84        }
     85
     86        String cname = null;
     87        String cnamem = null;
     88        for (OsmPrimitive osm : data) {
     89            osm.visit(v);
     90            if (cname == null) {
     91                cname = v.className;
     92                cnamem = v.classNamePlural;
     93            } else if (!cname.equals(v.className)) {
     94                cname = "object";
     95                cnamem = trn("object", "objects", 2);
     96            }
     97        }
     98        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(tr("Delete {0} {1}", data.size(), trn(
     99                cname, cnamem, data.size())), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
     100        for (OsmPrimitive osm : data) {
     101            osm.visit(v);
     102            root.add(new DefaultMutableTreeNode(v.toLabel()));
     103        }
     104        return root;
     105    }
     106
     107    /**
     108     * Delete the primitives and everything they reference.
     109     *
     110     * If a node is deleted, the node and all ways and relations the node is part of are deleted as
     111     * well.
     112     *
     113     * If a way is deleted, all relations the way is member of are also deleted.
     114     *
     115     * If a way is deleted, only the way and no nodes are deleted.
     116     *
     117     * @param selection The list of all object to be deleted.
     118     * @return command A command to perform the deletions, or null of there is nothing to delete.
     119     */
     120    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
     121        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
     122        for (OsmPrimitive osm : selection)
     123            osm.visit(v);
     124        v.data.addAll(selection);
     125        if (v.data.isEmpty())
     126            return null;
     127        if (!checkAndConfirmOutlyingDeletes(v.data))
     128            return null;
     129        return new DeleteCommand(v.data);
     130    }
     131
     132    /**
     133     * Try to delete all given primitives.
     134     *
     135     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
     136     * relation, inform the user and do not delete.
     137     *
     138     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
     139     * they are part of a relation, inform the user and do not delete.
     140     *
     141     * @param selection The objects to delete.
     142     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
     143     * @return command A command to perform the deletions, or null of there is nothing to delete.
     144     */
     145    private static int testRelation(Relation ref, OsmPrimitive osm) {
     146        NameVisitor n = new NameVisitor();
     147        ref.visit(n);
     148        NameVisitor s = new NameVisitor();
     149        osm.visit(s);
     150        String role = new String();
     151        for (RelationMember m : ref.members) {
     152            if (m.member == osm) {
     153                role = m.role;
     154                break;
     155            }
     156        }
     157        if (role.length() > 0) {
     158            return JOptionPane.showConfirmDialog(Main.parent, tr(
     159                    "Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name,
     160                    n.name, role), tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     161        } else {
     162            return JOptionPane.showConfirmDialog(Main.parent, tr(
     163                    "Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
     164                    tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     165        }
     166    }
     167
     168    public static Command delete(Collection<? extends OsmPrimitive> selection) {
     169        return delete(selection, true);
     170    }
     171
     172    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     173        if (selection.isEmpty())
     174            return null;
     175
     176        Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
     177        Collection<Way> waysToBeChanged = new HashSet<Way>();
     178        HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
     179
     180        if (alsoDeleteNodesInWay) {
     181            // Delete untagged nodes that are to be unreferenced.
     182            Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
     183            for (OsmPrimitive osm : del) {
     184                if (osm instanceof Way) {
     185                    for (Node n : ((Way) osm).nodes) {
     186                        if (!n.tagged) {
     187                            CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     188                            n.visit(v);
     189                            v.data.removeAll(del);
     190                            if (v.data.isEmpty()) {
     191                                delNodes.add(n);
     192                            }
     193                        }
     194                    }
     195                }
     196            }
     197            del.addAll(delNodes);
     198        }
     199
     200        if (!checkAndConfirmOutlyingDeletes(del))
     201            return null;
     202
     203        for (OsmPrimitive osm : del) {
     204            CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     205            osm.visit(v);
     206            for (OsmPrimitive ref : v.data) {
     207                if (del.contains(ref))
     208                    continue;
     209                if (ref instanceof Way) {
     210                    waysToBeChanged.add((Way) ref);
     211                } else if (ref instanceof Relation) {
     212                    if (testRelation((Relation) ref, osm) == JOptionPane.YES_OPTION) {
     213                        Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     214                        if (relset == null)
     215                            relset = new HashSet<OsmPrimitive>();
     216                        relset.add(osm);
     217                        relationsToBeChanged.put(ref, relset);
     218                    } else
     219                        return null;
     220                } else {
     221                    return null;
     222                }
     223            }
     224        }
     225
     226        Collection<Command> cmds = new LinkedList<Command>();
     227        for (Way w : waysToBeChanged) {
     228            Way wnew = new Way(w);
     229            wnew.nodes.removeAll(del);
     230            if (wnew.nodes.size() < 2) {
     231                del.add(w);
     232
     233                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     234                w.visit(v);
     235                for (OsmPrimitive ref : v.data) {
     236                    if (del.contains(ref))
     237                        continue;
     238                    if (ref instanceof Relation) {
     239                        Boolean found = false;
     240                        Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     241                        if (relset == null)
     242                            relset = new HashSet<OsmPrimitive>();
     243                        else {
     244                            for (OsmPrimitive m : relset) {
     245                                if (m == w) {
     246                                    found = true;
     247                                    break;
     248                                }
     249                            }
     250                        }
     251                        if (!found) {
     252                            if (testRelation((Relation) ref, w) == JOptionPane.YES_OPTION) {
     253                                relset.add(w);
     254                                relationsToBeChanged.put(ref, relset);
     255                            } else
     256                                return null;
     257                        }
     258                    } else {
     259                        return null;
     260                    }
     261                }
     262            } else {
     263                cmds.add(new ChangeCommand(w, wnew));
     264            }
     265        }
     266
     267        Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
     268        while (iterator.hasNext()) {
     269            Relation cur = (Relation) iterator.next();
     270            Relation rel = new Relation(cur);
     271            for (OsmPrimitive osm : relationsToBeChanged.get(cur)) {
     272                for (RelationMember rm : rel.members) {
     273                    if (rm.member == osm) {
     274                        RelationMember mem = new RelationMember();
     275                        mem.role = rm.role;
     276                        mem.member = rm.member;
     277                        rel.members.remove(mem);
     278                        break;
     279                    }
     280                }
     281            }
     282            cmds.add(new ChangeCommand(cur, rel));
     283        }
     284
     285        if (!del.isEmpty())
     286            cmds.add(new DeleteCommand(del));
     287
     288        return new SequenceCommand(tr("Delete"), cmds);
     289    }
     290
     291    public static Command deleteWaySegment(WaySegment ws) {
     292        List<Node> n1 = new ArrayList<Node>(), n2 = new ArrayList<Node>();
     293
     294        n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
     295        n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
     296
     297        if (n1.size() < 2 && n2.size() < 2) {
     298            return new DeleteCommand(Collections.singleton(ws.way));
     299        }
     300
     301        Way wnew = new Way(ws.way);
     302        wnew.nodes.clear();
     303
     304        if (n1.size() < 2) {
     305            wnew.nodes.addAll(n2);
     306            return new ChangeCommand(ws.way, wnew);
     307        } else if (n2.size() < 2) {
     308            wnew.nodes.addAll(n1);
     309            return new ChangeCommand(ws.way, wnew);
     310        } else {
     311            Collection<Command> cmds = new LinkedList<Command>();
     312
     313            wnew.nodes.addAll(n1);
     314            cmds.add(new ChangeCommand(ws.way, wnew));
     315
     316            Way wnew2 = new Way();
     317            if (wnew.keys != null) {
     318                wnew2.keys = new HashMap<String, String>(wnew.keys);
     319                wnew2.checkTagged();
     320                wnew2.checkDirectionTagged();
     321            }
     322            wnew2.nodes.addAll(n2);
     323            cmds.add(new AddCommand(wnew2));
     324
     325            return new SequenceCommand(tr("Split way segment"), cmds);
     326        }
     327    }
     328
     329    /**
     330     * Check whether user is about to delete data outside of the download area.
     331     * Request confirmation if he is.
     332     */
     333    private static boolean checkAndConfirmOutlyingDeletes(Collection<OsmPrimitive> del) {
     334        Area a = Main.ds.getDataSourceArea();
     335        if (a != null) {
     336            for (OsmPrimitive osm : del) {
     337                if (osm instanceof Node && osm.id != 0) {
     338                    Node n = (Node) osm;
     339                    if (!a.contains(n.coor)) {
     340                        JPanel msg = new JPanel(new GridBagLayout());
     341                        msg.add(new JLabel(
     342                            "<html>" +
     343                            // leave message in one tr() as there is a grammatical connection.
     344                            tr("You are about to delete nodes outside of the area you have downloaded." +
     345                            "<br>" +
     346                            "This can cause problems because other objects (that you don't see) might use them." +
     347                            "<br>" +
     348                            "Do you really want to delete?") + "</html>"));
     349                        return DontShowAgainInfo.show("delete_outside_nodes", msg, false, JOptionPane.YES_NO_OPTION, JOptionPane.YES_OPTION);
     350                    }
     351
     352                }
     353            }
     354        }
     355        return true;
     356    }
    333357}
  • trunk/src/org/openstreetmap/josm/data/coor/Coordinate.java

    r655 r1004  
    22package org.openstreetmap.josm.data.coor;
    33
    4 import java.io.Serializable;
     4import java.awt.geom.Point2D;
    55
    66/**
     
    1515 * @author imi
    1616 */
    17 abstract class Coordinate implements Serializable {
     17abstract class Coordinate extends Point2D {
    1818
    19         /**
    20          * Either easting or latitude
    21          */
    22         final double x;
    23         /**
    24          * Either northing or longitude
    25          */
    26         final double y;
    27 
     19    protected double x;
     20    protected double y;
     21   
    2822        /**
    2923         * Construct the point with latitude / longitude values.
    30          * The x/y values are left uninitialized.
    3124         *
    3225         * @param x X coordinate of the point.
     
    3427         */
    3528        Coordinate(double x, double y) {
    36                 this.x = x;
    37                 this.y = y;
     29        this.x = x; this.y = y;
    3830        }
     31   
     32    public double getX() {
     33        return x;
     34    }
     35   
     36    public double getY() {
     37        return y;
     38    }
     39   
     40    public void setLocation (double x, double y) {
     41        this.x = x;
     42        this.y = y;
     43    }
    3944
    40         /**
    41          * Return the squared distance of the northing/easting values between
    42          * this and the argument.
    43          *
    44          * This method does NOT compute a great circle distance between two
    45          * locations!
    46          *
    47          * @param other The other point to calculate the distance to.
    48          * @return The square of the distance between this and the other point,
    49          *              regarding to the x/y values.
    50          */
    51         public double distanceSq(Coordinate other) {
    52                 return (x-other.x)*(x-other.x)+(y-other.y)*(y-other.y);
    53         }
    54        
    55         /**
    56          * Return the distance of the northing/easting values between this and
    57          * the argument.
    58          *
    59          * This method does NOT compute a great circle distance between two
    60          * locations!
    61          *
    62          * @param other The other point to calculate the distance to.
    63          * @return The square of the distance between this and the other point,
    64          *              regarding to the x/y values.
    65          */
    66         public double distance(Coordinate other) {
    67                 return Math.sqrt(distanceSq(other));
    68         }
    69 
    70         @Override public boolean equals(Object obj) {
    71                 return obj instanceof Coordinate ? x == ((Coordinate)obj).x && ((Coordinate)obj).y == y : false;
    72         }
    73 
    74         @Override public int hashCode() {
    75                 return (int)(x*65536+y*4096);
    76         }
    7745}
  • trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r999 r1004  
    1515
    1616/**
    17  * DataSet is the data behind the application. It can consists of only a few
    18  * points up to the whole osm database. DataSet's can be merged together,
    19  * saved, (up/down/disk)loaded etc.
    20  *
    21  * Note that DataSet is not an osm-primitive and so has no key association
    22  * but a few members to store some information.
    23  *
     17 * DataSet is the data behind the application. It can consists of only a few points up to the whole
     18 * osm database. DataSet's can be merged together, saved, (up/down/disk)loaded etc.
     19 *
     20 * Note that DataSet is not an osm-primitive and so has no key association but a few members to
     21 * store some information.
     22 *
    2423 * @author imi
    2524 */
    2625public class DataSet implements Cloneable {
    2726
    28         /**
    29          * All nodes goes here, even when included in other data (ways etc).
    30          * This enables the instant conversion of the whole DataSet by iterating over
    31          * this data structure.
    32          */
    33         public Collection<Node> nodes = new LinkedList<Node>();
    34 
    35         /**
    36          * All ways (Streets etc.) in the DataSet.
    37          *
    38          * The way nodes are stored only in the way list.
    39          */
    40         public Collection<Way> ways = new LinkedList<Way>();
    41 
    42         /**
    43          * All relations/relationships
    44          */
    45         public Collection<Relation> relations = new LinkedList<Relation>();
    46 
    47         /**
    48          * All data sources of this DataSet.
    49          */
    50         public Collection<DataSource> dataSources = new LinkedList<DataSource>();
    51        
    52         /**
    53          * A list of listeners to selection changed events. The list is static,
    54          * as listeners register themselves for any dataset selection changes that
    55          * occur, regardless of the current active dataset. (However, the
    56          * selection does only change in the active layer)
    57          */
    58         public static Collection<SelectionChangedListener> selListeners = new LinkedList<SelectionChangedListener>();
    59 
    60         /**
    61          * @return A collection containing all primitives of the dataset. The
    62          * data is ordered after: first come nodes, then ways, then relations.
    63          * Ordering in between the categories is not guaranteed.
    64          */
    65         public List<OsmPrimitive> allPrimitives() {
    66                 List<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    67                 o.addAll(nodes);
    68                 o.addAll(ways);
    69                 o.addAll(relations);
    70                 return o;
    71         }
    72 
    73         /**
    74          * @return A collection containing all not-deleted primitives (except keys).
    75          */
    76         public Collection<OsmPrimitive> allNonDeletedPrimitives() {
    77                 Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    78                 for (OsmPrimitive osm : allPrimitives())
    79                         if (!osm.deleted)
    80                                 o.add(osm);
    81                 return o;
    82         }
    83 
    84         public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
    85                 Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    86                 for (OsmPrimitive osm : allPrimitives())
    87                         if (!osm.deleted && !osm.incomplete)
    88                                 o.add(osm);
    89                 return o;
    90         }
    91 
    92         public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
    93                 Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    94                 for (OsmPrimitive osm : allPrimitives())
    95                         if (!osm.deleted && !osm.incomplete && !(osm instanceof Relation))
    96                                 o.add(osm);
    97                 return o;
    98         }
    99 
    100         public void addPrimitive(OsmPrimitive osm) {
    101                 if (osm instanceof Node) {
    102                         nodes.add((Node) osm);
    103                 } else if (osm instanceof Way) {
    104                         ways.add((Way) osm);
    105                 } else if (osm instanceof Relation) {
    106                         relations.add((Relation) osm);
    107                 }
    108         }
    109 
    110         /**
    111          * Remove the selection of the whole dataset.
    112          * @deprecated Use {@link #setSelected(Collection) setSelected}
    113          * instead.
    114          */
    115         @Deprecated
    116         public void clearSelection() {
    117                 clearSelection(nodes);
    118                 clearSelection(ways);
    119                 clearSelection(relations);
    120                 Collection<OsmPrimitive> sel = Collections.emptyList();
    121                 fireSelectionChanged(sel);
    122         }
    123 
    124         /**
    125          * Return a list of all selected objects. Even keys are returned.
    126          * @return List of all selected objects.
    127          */
    128         public Collection<OsmPrimitive> getSelected() {
    129                 Collection<OsmPrimitive> sel = getSelected(nodes);
    130                 sel.addAll(getSelected(ways));
    131                 sel.addAll(getSelected(relations));
    132                 return sel;
    133         }
    134 
    135         /**
    136          * Return selected nodes.
    137          */
    138         public Collection<OsmPrimitive> getSelectedNodes() {
    139                 return getSelected(nodes);
    140         }
    141 
    142         /**
    143          * Return selected ways.
    144          */
    145         public Collection<OsmPrimitive> getSelectedWays() {
    146                 return getSelected(ways);
    147         }
    148 
    149         /**
    150          * Return selected relations.
    151          */
    152         public Collection<OsmPrimitive> getSelectedRelations() {
    153                 return getSelected(relations);
    154         }
    155 
    156         public void setSelected(Collection<? extends OsmPrimitive> selection) {
    157                 clearSelection(nodes);
    158                 clearSelection(ways);
    159                 clearSelection(relations);
    160                 for (OsmPrimitive osm : selection)
    161                         osm.selected = true;
    162                 fireSelectionChanged(selection);
    163         }
    164 
    165         public void setSelected(OsmPrimitive... osm) {
    166                 if (osm.length == 1 && osm[0] == null) {
    167                         setSelected();
    168                         return;
    169                 }
    170                 clearSelection(nodes);
    171                 clearSelection(ways);
    172                 clearSelection(relations);
    173                 for (OsmPrimitive o : osm)
    174                         if (o != null)
    175                                 o.selected = true;
    176                 fireSelectionChanged(Arrays.asList(osm));
    177         }
    178 
    179         /**
    180          * Remove the selection from every value in the collection.
    181          * @param list The collection to remove the selection from.
    182          */
    183         private void clearSelection(Collection<? extends OsmPrimitive> list) {
    184                 if (list == null)
    185                         return;
    186                 for (OsmPrimitive osm : list)
    187                         osm.selected = false;
    188         }
    189 
    190         /**
    191          * Return all selected items in the collection.
    192          * @param list The collection from which the selected items are returned.
    193          */
    194         private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
    195                 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
    196                 if (list == null)
    197                         return sel;
    198                 for (OsmPrimitive osm : list)
    199                         if (osm.selected && !osm.deleted)
    200                                 sel.add(osm);
    201                 return sel;
    202         }
    203 
    204         /**
    205          * Remember to fire an selection changed event. A call to this will not fire
    206          * the event immediately. For more, @see SelectionChangedListener
    207          */
    208         public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
    209                 for (SelectionChangedListener l : selListeners)
    210                         l.selectionChanged(sel);
    211         }
    212        
    213         @Override public DataSet clone() {
    214                 DataSet ds = new DataSet();
    215                 for (Node n : nodes)
    216                         ds.nodes.add(new Node(n));
    217                 for (Way w : ways)
    218                         ds.ways.add(new Way(w));
    219                 for (Relation e : relations)
    220                         ds.relations.add(new Relation(e));
    221                 for (DataSource source : dataSources)
    222                         ds.dataSources.add(new DataSource(source.bounds, source.origin));
    223             return ds;
    224     }
    225        
    226         /**
    227          * Returns the total area of downloaded data (the "yellow rectangles").
    228          * @return Area object encompassing downloaded data.
    229          */
    230         public Area getDataSourceArea()
    231         {
    232                 Area a = new Area();
    233                 for (DataSource source : dataSources) {
    234                         // create area from data bounds
    235                         a.add(new Area(source.bounds.asRect()));
    236                 }
    237                 return a;
    238                
    239         }
    240 
    241         // Search für Relation wieder erlauben.
    242         public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
    243                 OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
    244                 final HashMap<Object, String> h = new HashMap<Object, String>();
    245                 selArr = list.toArray(selArr);
    246                 Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
    247                         public int compare(OsmPrimitive a, OsmPrimitive b)
    248                         {
    249                                 if(a.getClass() == b.getClass())
    250                                 {
    251                                         String as = h.get(a);
    252                                         if(as == null)
    253                                         {
    254                                                 as = a.getName();
    255                                                 h.put(a, as);
    256                                         }
    257                                         String bs = h.get(b);
    258                                         if(bs == null)
    259                                         {
    260                                                 bs = b.getName();
    261                                                 h.put(b, bs);
    262                                         }
    263                                         int res = as.compareTo(bs);
    264                                         if(res != 0)
    265                                                 return res;
    266                                 }
    267                                 return a.compareTo(b);
    268                         }
    269                 });
    270                 return selArr;
    271         }
     27    /**
     28     * All nodes goes here, even when included in other data (ways etc). This enables the instant
     29     * conversion of the whole DataSet by iterating over this data structure.
     30     */
     31    public Collection<Node> nodes = new LinkedList<Node>();
     32
     33    /**
     34     * All ways (Streets etc.) in the DataSet.
     35     *
     36     * The way nodes are stored only in the way list.
     37     */
     38    public Collection<Way> ways = new LinkedList<Way>();
     39
     40    /**
     41     * All relations/relationships
     42     */
     43    public Collection<Relation> relations = new LinkedList<Relation>();
     44
     45    /**
     46     * All data sources of this DataSet.
     47     */
     48    public Collection<DataSource> dataSources = new LinkedList<DataSource>();
     49
     50    /**
     51     * A list of listeners to selection changed events. The list is static, as listeners register
     52     * themselves for any dataset selection changes that occur, regardless of the current active
     53     * dataset. (However, the selection does only change in the active layer)
     54     */
     55    public static Collection<SelectionChangedListener> selListeners = new LinkedList<SelectionChangedListener>();
     56
     57    /**
     58     * @return A collection containing all primitives of the dataset. The data is ordered after:
     59     * first come nodes, then ways, then relations. Ordering in between the categories is not
     60     * guaranteed.
     61     */
     62    public List<OsmPrimitive> allPrimitives() {
     63        List<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
     64        o.addAll(nodes);
     65        o.addAll(ways);
     66        o.addAll(relations);
     67        return o;
     68    }
     69
     70    /**
     71     * @return A collection containing all not-deleted primitives (except keys).
     72     */
     73    public Collection<OsmPrimitive> allNonDeletedPrimitives() {
     74        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
     75        for (OsmPrimitive osm : allPrimitives())
     76            if (!osm.deleted)
     77                o.add(osm);
     78        return o;
     79    }
     80
     81    public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
     82        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
     83        for (OsmPrimitive osm : allPrimitives())
     84            if (!osm.deleted && !osm.incomplete)
     85                o.add(osm);
     86        return o;
     87    }
     88
     89    public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
     90        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
     91        for (OsmPrimitive osm : allPrimitives())
     92            if (!osm.deleted && !osm.incomplete && !(osm instanceof Relation))
     93                o.add(osm);
     94        return o;
     95    }
     96
     97    public void addPrimitive(OsmPrimitive osm) {
     98        if (osm instanceof Node) {
     99            nodes.add((Node) osm);
     100        } else if (osm instanceof Way) {
     101            ways.add((Way) osm);
     102        } else if (osm instanceof Relation) {
     103            relations.add((Relation) osm);
     104        }
     105    }
     106
     107    /**
     108     * Remove the selection of the whole dataset.
     109     * @deprecated Use {@link #setSelected(Collection) setSelected} instead.
     110     */
     111    @Deprecated public void clearSelection() {
     112        clearSelection(nodes);
     113        clearSelection(ways);
     114        clearSelection(relations);
     115        Collection<OsmPrimitive> sel = Collections.emptyList();
     116        fireSelectionChanged(sel);
     117    }
     118
     119    /**
     120     * Return a list of all selected objects. Even keys are returned.
     121     * @return List of all selected objects.
     122     */
     123    public Collection<OsmPrimitive> getSelected() {
     124        Collection<OsmPrimitive> sel = getSelected(nodes);
     125        sel.addAll(getSelected(ways));
     126        sel.addAll(getSelected(relations));
     127        return sel;
     128    }
     129
     130    /**
     131     * Return selected nodes.
     132     */
     133    public Collection<OsmPrimitive> getSelectedNodes() {
     134        return getSelected(nodes);
     135    }
     136
     137    /**
     138     * Return selected ways.
     139     */
     140    public Collection<OsmPrimitive> getSelectedWays() {
     141        return getSelected(ways);
     142    }
     143
     144    /**
     145     * Return selected relations.
     146     */
     147    public Collection<OsmPrimitive> getSelectedRelations() {
     148        return getSelected(relations);
     149    }
     150
     151    public void setSelected(Collection<? extends OsmPrimitive> selection) {
     152        clearSelection(nodes);
     153        clearSelection(ways);
     154        clearSelection(relations);
     155        for (OsmPrimitive osm : selection)
     156            osm.selected = true;
     157        fireSelectionChanged(selection);
     158    }
     159
     160    public void setSelected(OsmPrimitive... osm) {
     161        if (osm.length == 1 && osm[0] == null) {
     162            setSelected();
     163            return;
     164        }
     165        clearSelection(nodes);
     166        clearSelection(ways);
     167        clearSelection(relations);
     168        for (OsmPrimitive o : osm)
     169            if (o != null)
     170                o.selected = true;
     171        fireSelectionChanged(Arrays.asList(osm));
     172    }
     173
     174    /**
     175     * Remove the selection from every value in the collection.
     176     * @param list The collection to remove the selection from.
     177     */
     178    private void clearSelection(Collection<? extends OsmPrimitive> list) {
     179        if (list == null)
     180            return;
     181        for (OsmPrimitive osm : list)
     182            osm.selected = false;
     183    }
     184
     185    /**
     186     * Return all selected items in the collection.
     187     * @param list The collection from which the selected items are returned.
     188     */
     189    private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
     190        Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
     191        if (list == null)
     192            return sel;
     193        for (OsmPrimitive osm : list)
     194            if (osm.selected && !osm.deleted)
     195                sel.add(osm);
     196        return sel;
     197    }
     198
     199    /**
     200     * Remember to fire an selection changed event. A call to this will not fire the event
     201     * immediately. For more,
     202     * @see SelectionChangedListener
     203     */
     204    public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
     205        for (SelectionChangedListener l : selListeners)
     206            l.selectionChanged(sel);
     207    }
     208
     209    @Override public DataSet clone() {
     210        DataSet ds = new DataSet();
     211        for (Node n : nodes)
     212            ds.nodes.add(new Node(n));
     213        for (Way w : ways)
     214            ds.ways.add(new Way(w));
     215        for (Relation e : relations)
     216            ds.relations.add(new Relation(e));
     217        for (DataSource source : dataSources)
     218            ds.dataSources.add(new DataSource(source.bounds, source.origin));
     219        return ds;
     220    }
     221
     222    /**
     223     * Returns the total area of downloaded data (the "yellow rectangles").
     224     * @return Area object encompassing downloaded data.
     225     */
     226    public Area getDataSourceArea() {
     227        if (dataSources.isEmpty()) return null;
     228        Area a = new Area();
     229        for (DataSource source : dataSources) {
     230            // create area from data bounds
     231            a.add(new Area(source.bounds.asRect()));
     232        }
     233        return a;
     234    }
     235
     236    // Provide well-defined sorting for collections of OsmPrimitives.
     237    // FIXME: probably not a good place to put this code.
     238    public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
     239        OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
     240        final HashMap<Object, String> h = new HashMap<Object, String>();
     241        selArr = list.toArray(selArr);
     242        Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
     243            public int compare(OsmPrimitive a, OsmPrimitive b) {
     244                if (a.getClass() == b.getClass()) {
     245                    String as = h.get(a);
     246                    if (as == null) {
     247                        as = a.getName();
     248                        h.put(a, as);
     249                    }
     250                    String bs = h.get(b);
     251                    if (bs == null) {
     252                        bs = b.getName();
     253                        h.put(b, bs);
     254                    }
     255                    int res = as.compareTo(bs);
     256                    if (res != 0)
     257                        return res;
     258                }
     259                return a.compareTo(b);
     260            }
     261        });
     262        return selArr;
     263    }
    272264}
  • trunk/src/org/openstreetmap/josm/tools/DontShowAgainInfo.java

    r745 r1004  
    1717
    1818        public static boolean show(String prefKey, String msg) {
    19                 return show(prefKey, new JLabel(msg), true);
     19                return show(prefKey, new JLabel(msg), true, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
    2020        }
    2121
    2222        public static boolean show(String prefKey, String msg, Boolean state) {
    23                 return show(prefKey, new JLabel(msg), state);
     23                return show(prefKey, new JLabel(msg), state, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
    2424        }
    2525
    2626        public static boolean show(String prefKey, Container msg) {
    27                 return show(prefKey, msg, true);
     27                return show(prefKey, msg, true, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
    2828        }
    2929
    30         public static boolean show(String prefKey, Container msg, Boolean state) {
     30        public static boolean show(String prefKey, Container msg, Boolean state, int options, int true_option) {
    3131                if (!Main.pref.getBoolean("message."+prefKey)) {
    3232                        JCheckBox dontshowagain = new JCheckBox(tr("Do not show again"));
     
    3535                        all.add(msg, GBC.eop());
    3636                        all.add(dontshowagain, GBC.eol());
    37                         int answer = JOptionPane.showConfirmDialog(Main.parent, all, tr("Information"), JOptionPane.OK_CANCEL_OPTION);
    38                         if (answer != JOptionPane.OK_OPTION)
     37                        int answer = JOptionPane.showConfirmDialog(Main.parent, all, tr("Information"), options);
     38                        if (answer != true_option)
    3939                                return false;
    4040                        Main.pref.put("message."+prefKey, dontshowagain.isSelected());
Note: See TracChangeset for help on using the changeset viewer.