Index: trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 1003)
+++ trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 1004)
@@ -5,4 +5,6 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
+import java.awt.GridBagLayout;
+import java.awt.geom.Area;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -16,4 +18,5 @@
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
+import javax.swing.JPanel;
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.MutableTreeNode;
@@ -28,5 +31,8 @@
 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
 import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
+import org.openstreetmap.josm.tools.DontShowAgainInfo;
+import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.UrlLabel;
 
 /**
@@ -36,18 +42,19 @@
 public class DeleteCommand extends Command {
 
-	/**
-	 * The primitive that get deleted.
-	 */
-	private final Collection<? extends OsmPrimitive> data;
-
-    /** 
+    /**
+     * The primitive that get deleted.
+     */
+    private final Collection<? extends OsmPrimitive> data;
+
+    /**
      * Constructor for a collection of data
      */
-	public DeleteCommand(Collection<? extends OsmPrimitive> data) {
-		this.data = data;
-	}
-    /** 
-     * Constructor for a single data item. Use the collection 
-     * constructor to delete multiple objects.
+    public DeleteCommand(Collection<? extends OsmPrimitive> data) {
+        this.data = data;
+    }
+
+    /**
+     * Constructor for a single data item. Use the collection constructor to delete multiple
+     * objects.
      */
     public DeleteCommand(OsmPrimitive data) {
@@ -55,279 +62,296 @@
     }
 
-	@Override public boolean executeCommand() {
-		super.executeCommand();
-		for (OsmPrimitive osm : data) {
-			osm.delete(true);
-		}
-		return true;
-	}
-	
-	@Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
-		deleted.addAll(data);
-	}
-
-	@Override public MutableTreeNode description() {
-		NameVisitor v = new NameVisitor();
-
-		if (data.size() == 1) {
-			data.iterator().next().visit(v);
-			return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", v.name, tr(v.className)), v.icon, JLabel.HORIZONTAL));
-		}
-
-		String cname = null;
-		String cnamem = null;
-		for (OsmPrimitive osm : data) {
-			osm.visit(v);
-			if (cname == null)
-			{
-				cname = v.className;
-				cnamem = v.classNamePlural;
-			}
-			else if (!cname.equals(v.className))
-			{
-				cname = "object";
-				cnamem = trn("object", "objects", 2);
-			}
-		}
-		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(
-				tr("Delete {0} {1}", data.size(), trn(cname, cnamem, data.size())), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
-		for (OsmPrimitive osm : data) {
-			osm.visit(v);
-			root.add(new DefaultMutableTreeNode(v.toLabel()));
-		}
-		return root;
-	}
-
-	/**
-	 * Delete the primitives and everything they reference.
-	 *
-	 * If a node is deleted, the node and all ways and relations
-	 * the node is part of are deleted as well.
-	 *
-	 * If a way is deleted, all relations the way is member of are also deleted.
-	 * 
-	 * If a way is deleted, only the way and no nodes are deleted.
-	 * 
-	 * @param selection The list of all object to be deleted.
-	 * @return command A command to perform the deletions, or null of there is
-	 * nothing to delete.
-	 */
-	public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
-		CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
-		for (OsmPrimitive osm : selection)
-			osm.visit(v);
-		v.data.addAll(selection);
-		if (v.data.isEmpty()) 
-			return null;
-		return new DeleteCommand(v.data);
-	}
-
-	/**
-	 * Try to delete all given primitives.
-	 *
-	 * If a node is used by a way, it's removed from that way.  If a node or a
-	 * way is used by a relation, inform the user and do not delete.
-	 *
-	 * If this would cause ways with less than 2 nodes to be created, delete
-	 * these ways instead.  If they are part of a relation, inform the user
-	 * and do not delete.
-	 * 
-	 * @param selection The objects to delete.
-	 * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
-	 * @return command A command to perform the deletions, or null of there is
-	 * nothing to delete.
-	 */
-	private static int testRelation(Relation ref, OsmPrimitive osm)
-	{
-		NameVisitor n = new NameVisitor();
-		ref.visit(n);
-		NameVisitor s = new NameVisitor();
-		osm.visit(s);
-		String role = new String();
-		for (RelationMember m : ref.members)
-		{
-			if (m.member == osm)
-			{
-				role = m.role;
-				break;
-			}
-		}
-		if (role.length() > 0)
-		{
-			return JOptionPane.showConfirmDialog(Main.parent,
-			tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name, n.name, role),
-			tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
-		}
-		else
-		{
-			return JOptionPane.showConfirmDialog(Main.parent,
-			tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
-			tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
-		}
-	}
-
-	public static Command delete(Collection<? extends OsmPrimitive> selection)
-	{
-		return delete(selection, true);
-	}
-
-	public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
-		if (selection.isEmpty()) return null;
-
-		Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
-		Collection<Way> waysToBeChanged = new HashSet<Way>();
-		HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
-
-		if (alsoDeleteNodesInWay) {
-			// Delete untagged nodes that are to be unreferenced.
-			Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
-			for (OsmPrimitive osm : del) {
-				if (osm instanceof Way) {
-					for (Node n : ((Way)osm).nodes) {
-						if (!n.tagged) {
-							CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
-							n.visit(v);
-							v.data.removeAll(del);
-							if (v.data.isEmpty()) {
-								delNodes.add(n);
-							}
-						}
-					}
-				}
-			}
-			del.addAll(delNodes);
-		}
-		
-		for (OsmPrimitive osm : del) {
-			CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
-			osm.visit(v);
-			for (OsmPrimitive ref : v.data) {
-				if (del.contains(ref)) continue;
-				if (ref instanceof Way) {
-					waysToBeChanged.add((Way) ref);
-				} else if (ref instanceof Relation) {
-					if (testRelation((Relation)ref, osm) == JOptionPane.YES_OPTION)
-					{
-						Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
-						if(relset == null) relset = new HashSet<OsmPrimitive>();
-						relset.add(osm);
-						relationsToBeChanged.put(ref, relset);
-					}
-					else
-						return null;
-				} else {
-					return null;
-				}
-			}
-		}
-
-		Collection<Command> cmds = new LinkedList<Command>();
-		for (Way w : waysToBeChanged) {
-			Way wnew = new Way(w);
-			wnew.nodes.removeAll(del);
-			if (wnew.nodes.size() < 2) {
-				del.add(w);
-
-				CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
-				w.visit(v);
-				for (OsmPrimitive ref : v.data) {
-					if (del.contains(ref)) continue;
-					if (ref instanceof Relation) {
-						Boolean found = false;
-						Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
-						if (relset == null)
-							relset = new HashSet<OsmPrimitive>();
-						else
-						{
-							for (OsmPrimitive m : relset) {
-								if(m == w)
-								{
-									found = true;
-									break;
-								}
-							}
-						}
-						if (!found)
-						{
-							if (testRelation((Relation)ref, w) == JOptionPane.YES_OPTION)
-							{
-								relset.add(w);
-								relationsToBeChanged.put(ref, relset);
-							}
-							else
-								return null;
-						}
-					} else {
-						return null;
-					}
-				}
-			} else {
-				cmds.add(new ChangeCommand(w, wnew));
-			}
-		}
-
-		Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
-		while(iterator.hasNext())
-		{
-			Relation cur = (Relation)iterator.next();
-			Relation rel = new Relation(cur);
-			for(OsmPrimitive osm : relationsToBeChanged.get(cur))
-			{
-				for (RelationMember rm : rel.members) {
-					if (rm.member == osm)
-					{
-						RelationMember mem = new RelationMember();
-						mem.role = rm.role;
-						mem.member = rm.member;
-						rel.members.remove(mem);
-						break;
-					}
-				}
-			}
-			cmds.add(new ChangeCommand(cur, rel));
-		}
-
-		if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
-
-		return new SequenceCommand(tr("Delete"), cmds);
-	}
-
-	public static Command deleteWaySegment(WaySegment ws) {
-		List<Node> n1 = new ArrayList<Node>(),
-			n2 = new ArrayList<Node>();
-
-		n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
-		n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
-
-		if (n1.size() < 2 && n2.size() < 2) {
-			return new DeleteCommand(Collections.singleton(ws.way));
-		}
-		
-		Way wnew = new Way(ws.way);
-		wnew.nodes.clear();
-
-		if (n1.size() < 2) {
-			wnew.nodes.addAll(n2);
-			return new ChangeCommand(ws.way, wnew);
-		} else if (n2.size() < 2) {
-			wnew.nodes.addAll(n1);
-			return new ChangeCommand(ws.way, wnew);
-		} else {
-			Collection<Command> cmds = new LinkedList<Command>();
-
-			wnew.nodes.addAll(n1);
-			cmds.add(new ChangeCommand(ws.way, wnew));
-
-			Way wnew2 = new Way();
-			if (wnew.keys != null) {
-				wnew2.keys = new HashMap<String, String>(wnew.keys);
-				wnew2.checkTagged();
-                                wnew2.checkDirectionTagged();
-			}
-			wnew2.nodes.addAll(n2);
-			cmds.add(new AddCommand(wnew2));
-
-			return new SequenceCommand(tr("Split way segment"), cmds);
-		}
-	}
+    @Override public boolean executeCommand() {
+        super.executeCommand();
+        for (OsmPrimitive osm : data) {
+            osm.delete(true);
+        }
+        return true;
+    }
+
+    @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
+            Collection<OsmPrimitive> added) {
+        deleted.addAll(data);
+    }
+
+    @Override public MutableTreeNode description() {
+        NameVisitor v = new NameVisitor();
+
+        if (data.size() == 1) {
+            data.iterator().next().visit(v);
+            return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", v.name, tr(v.className)), v.icon,
+                    JLabel.HORIZONTAL));
+        }
+
+        String cname = null;
+        String cnamem = null;
+        for (OsmPrimitive osm : data) {
+            osm.visit(v);
+            if (cname == null) {
+                cname = v.className;
+                cnamem = v.classNamePlural;
+            } else if (!cname.equals(v.className)) {
+                cname = "object";
+                cnamem = trn("object", "objects", 2);
+            }
+        }
+        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(tr("Delete {0} {1}", data.size(), trn(
+                cname, cnamem, data.size())), ImageProvider.get("data", cname), JLabel.HORIZONTAL));
+        for (OsmPrimitive osm : data) {
+            osm.visit(v);
+            root.add(new DefaultMutableTreeNode(v.toLabel()));
+        }
+        return root;
+    }
+
+    /**
+     * Delete the primitives and everything they reference.
+     * 
+     * If a node is deleted, the node and all ways and relations the node is part of are deleted as
+     * well.
+     * 
+     * If a way is deleted, all relations the way is member of are also deleted.
+     * 
+     * If a way is deleted, only the way and no nodes are deleted.
+     * 
+     * @param selection The list of all object to be deleted.
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     */
+    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
+        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
+        for (OsmPrimitive osm : selection)
+            osm.visit(v);
+        v.data.addAll(selection);
+        if (v.data.isEmpty())
+            return null;
+        if (!checkAndConfirmOutlyingDeletes(v.data))
+            return null;
+        return new DeleteCommand(v.data);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     * 
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     * 
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     * 
+     * @param selection The objects to delete.
+     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     */
+    private static int testRelation(Relation ref, OsmPrimitive osm) {
+        NameVisitor n = new NameVisitor();
+        ref.visit(n);
+        NameVisitor s = new NameVisitor();
+        osm.visit(s);
+        String role = new String();
+        for (RelationMember m : ref.members) {
+            if (m.member == osm) {
+                role = m.role;
+                break;
+            }
+        }
+        if (role.length() > 0) {
+            return JOptionPane.showConfirmDialog(Main.parent, tr(
+                    "Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name,
+                    n.name, role), tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
+        } else {
+            return JOptionPane.showConfirmDialog(Main.parent, tr(
+                    "Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
+                    tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
+        }
+    }
+
+    public static Command delete(Collection<? extends OsmPrimitive> selection) {
+        return delete(selection, true);
+    }
+
+    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
+        if (selection.isEmpty())
+            return null;
+
+        Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
+        Collection<Way> waysToBeChanged = new HashSet<Way>();
+        HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
+
+        if (alsoDeleteNodesInWay) {
+            // Delete untagged nodes that are to be unreferenced.
+            Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
+            for (OsmPrimitive osm : del) {
+                if (osm instanceof Way) {
+                    for (Node n : ((Way) osm).nodes) {
+                        if (!n.tagged) {
+                            CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
+                            n.visit(v);
+                            v.data.removeAll(del);
+                            if (v.data.isEmpty()) {
+                                delNodes.add(n);
+                            }
+                        }
+                    }
+                }
+            }
+            del.addAll(delNodes);
+        }
+
+        if (!checkAndConfirmOutlyingDeletes(del))
+            return null;
+
+        for (OsmPrimitive osm : del) {
+            CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
+            osm.visit(v);
+            for (OsmPrimitive ref : v.data) {
+                if (del.contains(ref))
+                    continue;
+                if (ref instanceof Way) {
+                    waysToBeChanged.add((Way) ref);
+                } else if (ref instanceof Relation) {
+                    if (testRelation((Relation) ref, osm) == JOptionPane.YES_OPTION) {
+                        Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
+                        if (relset == null)
+                            relset = new HashSet<OsmPrimitive>();
+                        relset.add(osm);
+                        relationsToBeChanged.put(ref, relset);
+                    } else
+                        return null;
+                } else {
+                    return null;
+                }
+            }
+        }
+
+        Collection<Command> cmds = new LinkedList<Command>();
+        for (Way w : waysToBeChanged) {
+            Way wnew = new Way(w);
+            wnew.nodes.removeAll(del);
+            if (wnew.nodes.size() < 2) {
+                del.add(w);
+
+                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
+                w.visit(v);
+                for (OsmPrimitive ref : v.data) {
+                    if (del.contains(ref))
+                        continue;
+                    if (ref instanceof Relation) {
+                        Boolean found = false;
+                        Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
+                        if (relset == null)
+                            relset = new HashSet<OsmPrimitive>();
+                        else {
+                            for (OsmPrimitive m : relset) {
+                                if (m == w) {
+                                    found = true;
+                                    break;
+                                }
+                            }
+                        }
+                        if (!found) {
+                            if (testRelation((Relation) ref, w) == JOptionPane.YES_OPTION) {
+                                relset.add(w);
+                                relationsToBeChanged.put(ref, relset);
+                            } else
+                                return null;
+                        }
+                    } else {
+                        return null;
+                    }
+                }
+            } else {
+                cmds.add(new ChangeCommand(w, wnew));
+            }
+        }
+
+        Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
+        while (iterator.hasNext()) {
+            Relation cur = (Relation) iterator.next();
+            Relation rel = new Relation(cur);
+            for (OsmPrimitive osm : relationsToBeChanged.get(cur)) {
+                for (RelationMember rm : rel.members) {
+                    if (rm.member == osm) {
+                        RelationMember mem = new RelationMember();
+                        mem.role = rm.role;
+                        mem.member = rm.member;
+                        rel.members.remove(mem);
+                        break;
+                    }
+                }
+            }
+            cmds.add(new ChangeCommand(cur, rel));
+        }
+
+        if (!del.isEmpty())
+            cmds.add(new DeleteCommand(del));
+
+        return new SequenceCommand(tr("Delete"), cmds);
+    }
+
+    public static Command deleteWaySegment(WaySegment ws) {
+        List<Node> n1 = new ArrayList<Node>(), n2 = new ArrayList<Node>();
+
+        n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
+        n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
+
+        if (n1.size() < 2 && n2.size() < 2) {
+            return new DeleteCommand(Collections.singleton(ws.way));
+        }
+
+        Way wnew = new Way(ws.way);
+        wnew.nodes.clear();
+
+        if (n1.size() < 2) {
+            wnew.nodes.addAll(n2);
+            return new ChangeCommand(ws.way, wnew);
+        } else if (n2.size() < 2) {
+            wnew.nodes.addAll(n1);
+            return new ChangeCommand(ws.way, wnew);
+        } else {
+            Collection<Command> cmds = new LinkedList<Command>();
+
+            wnew.nodes.addAll(n1);
+            cmds.add(new ChangeCommand(ws.way, wnew));
+
+            Way wnew2 = new Way();
+            if (wnew.keys != null) {
+                wnew2.keys = new HashMap<String, String>(wnew.keys);
+                wnew2.checkTagged();
+                wnew2.checkDirectionTagged();
+            }
+            wnew2.nodes.addAll(n2);
+            cmds.add(new AddCommand(wnew2));
+
+            return new SequenceCommand(tr("Split way segment"), cmds);
+        }
+    }
+
+    /**
+     * Check whether user is about to delete data outside of the download area.
+     * Request confirmation if he is.
+     */
+    private static boolean checkAndConfirmOutlyingDeletes(Collection<OsmPrimitive> del) {
+        Area a = Main.ds.getDataSourceArea();
+        if (a != null) {
+            for (OsmPrimitive osm : del) {
+                if (osm instanceof Node && osm.id != 0) {
+                    Node n = (Node) osm;
+                    if (!a.contains(n.coor)) {
+                        JPanel msg = new JPanel(new GridBagLayout());
+                        msg.add(new JLabel(
+                            "<html>" +
+                            // leave message in one tr() as there is a grammatical connection.
+                            tr("You are about to delete nodes outside of the area you have downloaded." +
+                            "<br>" + 
+                            "This can cause problems because other objects (that you don't see) might use them." +
+                            "<br>" + 
+                            "Do you really want to delete?") + "</html>"));
+                        return DontShowAgainInfo.show("delete_outside_nodes", msg, false, JOptionPane.YES_NO_OPTION, JOptionPane.YES_OPTION);
+                    }
+
+                }
+            }
+        }
+        return true;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/coor/Coordinate.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/coor/Coordinate.java	(revision 1003)
+++ trunk/src/org/openstreetmap/josm/data/coor/Coordinate.java	(revision 1004)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.data.coor;
 
-import java.io.Serializable;
+import java.awt.geom.Point2D;
 
 /**
@@ -15,18 +15,11 @@
  * @author imi
  */ 
-abstract class Coordinate implements Serializable {
+abstract class Coordinate extends Point2D {
 
-	/**
-	 * Either easting or latitude
-	 */
-	final double x;
-	/**
-	 * Either northing or longitude
-	 */
-	final double y;
-
+    protected double x;
+    protected double y;
+    
 	/**
 	 * Construct the point with latitude / longitude values.
-	 * The x/y values are left uninitialized.
 	 * 
 	 * @param x X coordinate of the point.
@@ -34,44 +27,19 @@
 	 */
 	Coordinate(double x, double y) {
-		this.x = x;
-		this.y = y;
+        this.x = x; this.y = y;
 	}
+    
+    public double getX() {
+        return x;
+    }
+    
+    public double getY() {
+        return y; 
+    }
+    
+    public void setLocation (double x, double y) {
+        this.x = x; 
+        this.y = y;
+    }
 
-	/**
-	 * Return the squared distance of the northing/easting values between 
-	 * this and the argument.
-	 * 
-	 * This method does NOT compute a great circle distance between two 
-	 * locations!
-	 *
-	 * @param other The other point to calculate the distance to.
-	 * @return The square of the distance between this and the other point,
-	 * 		regarding to the x/y values.
-	 */
-	public double distanceSq(Coordinate other) {
-		return (x-other.x)*(x-other.x)+(y-other.y)*(y-other.y);
-	}
-	
-	/** 
-	 * Return the distance of the northing/easting values between this and
-	 * the argument.
-	 * 
-	 * This method does NOT compute a great circle distance between two 
-	 * locations!
-	 * 
-	 * @param other The other point to calculate the distance to.
-	 * @return The square of the distance between this and the other point,
-	 * 		regarding to the x/y values.
-	 */
-	public double distance(Coordinate other) {
-		return Math.sqrt(distanceSq(other));
-	}
-
-	@Override public boolean equals(Object obj) {
-		return obj instanceof Coordinate ? x == ((Coordinate)obj).x && ((Coordinate)obj).y == y : false;
-	}
-
-	@Override public int hashCode() {
-		return (int)(x*65536+y*4096);
-	}
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 1003)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 1004)
@@ -15,258 +15,250 @@
 
 /**
- * DataSet is the data behind the application. It can consists of only a few
- * points up to the whole osm database. DataSet's can be merged together,
- * saved, (up/down/disk)loaded etc.
- *
- * Note that DataSet is not an osm-primitive and so has no key association
- * but a few members to store some information.
- *
+ * DataSet is the data behind the application. It can consists of only a few points up to the whole
+ * osm database. DataSet's can be merged together, saved, (up/down/disk)loaded etc.
+ * 
+ * Note that DataSet is not an osm-primitive and so has no key association but a few members to
+ * store some information.
+ * 
  * @author imi
  */
 public class DataSet implements Cloneable {
 
-	/**
-	 * All nodes goes here, even when included in other data (ways etc).
-	 * This enables the instant conversion of the whole DataSet by iterating over
-	 * this data structure.
-	 */
-	public Collection<Node> nodes = new LinkedList<Node>();
-
-	/**
-	 * All ways (Streets etc.) in the DataSet.
-	 *
-	 * The way nodes are stored only in the way list.
-	 */
-	public Collection<Way> ways = new LinkedList<Way>();
-
-	/**
-	 * All relations/relationships
-	 */
-	public Collection<Relation> relations = new LinkedList<Relation>();
-
-	/**
-	 * All data sources of this DataSet.
-	 */
-	public Collection<DataSource> dataSources = new LinkedList<DataSource>();
-	
-	/**
-	 * A list of listeners to selection changed events. The list is static,
-	 * as listeners register themselves for any dataset selection changes that 
-	 * occur, regardless of the current active dataset. (However, the
-	 * selection does only change in the active layer)
-	 */
-	public static Collection<SelectionChangedListener> selListeners = new LinkedList<SelectionChangedListener>();
-
-	/**
-	 * @return A collection containing all primitives of the dataset. The
-	 * data is ordered after: first come nodes, then ways, then relations.
-	 * Ordering in between the categories is not guaranteed.
-	 */
-	public List<OsmPrimitive> allPrimitives() {
-		List<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
-		o.addAll(nodes);
-		o.addAll(ways);
-		o.addAll(relations);
-		return o;
-	}
-
-	/**
-	 * @return A collection containing all not-deleted primitives (except keys).
-	 */
-	public Collection<OsmPrimitive> allNonDeletedPrimitives() {
-		Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
-		for (OsmPrimitive osm : allPrimitives())
-			if (!osm.deleted)
-				o.add(osm);
-		return o;
-	}
-
-	public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
-		Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
-		for (OsmPrimitive osm : allPrimitives())
-			if (!osm.deleted && !osm.incomplete)
-				o.add(osm);
-		return o;
-	}
-
-	public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
-		Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
-		for (OsmPrimitive osm : allPrimitives())
-			if (!osm.deleted && !osm.incomplete && !(osm instanceof Relation))
-				o.add(osm);
-		return o;
-	}
-
-	public void addPrimitive(OsmPrimitive osm) {
-		if (osm instanceof Node) {
-			nodes.add((Node) osm);
-		} else if (osm instanceof Way) {
-			ways.add((Way) osm);
-		} else if (osm instanceof Relation) { 
-			relations.add((Relation) osm);
-		}
-	}
-
-	/**
-	 * Remove the selection of the whole dataset.
-	 * @deprecated Use {@link #setSelected(Collection) setSelected}
-	 * instead.
-	 */
-	@Deprecated
-	public void clearSelection() {
-		clearSelection(nodes);
-		clearSelection(ways);
-		clearSelection(relations);
-		Collection<OsmPrimitive> sel = Collections.emptyList();
-		fireSelectionChanged(sel);
-	}
-
-	/**
-	 * Return a list of all selected objects. Even keys are returned.
-	 * @return List of all selected objects.
-	 */
-	public Collection<OsmPrimitive> getSelected() {
-		Collection<OsmPrimitive> sel = getSelected(nodes);
-		sel.addAll(getSelected(ways));
-		sel.addAll(getSelected(relations));
-		return sel;
-	}
-
-	/**
-	 * Return selected nodes.
-	 */
-	public Collection<OsmPrimitive> getSelectedNodes() {
-		return getSelected(nodes);
-	}
-
-	/**
-	 * Return selected ways.
-	 */
-	public Collection<OsmPrimitive> getSelectedWays() {
-		return getSelected(ways);
-	}
-
-	/**
-	 * Return selected relations.
-	 */
-	public Collection<OsmPrimitive> getSelectedRelations() {
-		return getSelected(relations);
-	}
-
-	public void setSelected(Collection<? extends OsmPrimitive> selection) {
-		clearSelection(nodes);
-		clearSelection(ways);
-		clearSelection(relations);
-		for (OsmPrimitive osm : selection)
-			osm.selected = true;
-		fireSelectionChanged(selection);
-	}
-
-	public void setSelected(OsmPrimitive... osm) {
-		if (osm.length == 1 && osm[0] == null) {
-			setSelected();
-			return;
-		}
-		clearSelection(nodes);
-		clearSelection(ways);
-		clearSelection(relations);
-		for (OsmPrimitive o : osm)
-			if (o != null)
-				o.selected = true;
-		fireSelectionChanged(Arrays.asList(osm));
-	}
-
-	/**
-	 * Remove the selection from every value in the collection.
-	 * @param list The collection to remove the selection from.
-	 */
-	private void clearSelection(Collection<? extends OsmPrimitive> list) {
-		if (list == null)
-			return;
-		for (OsmPrimitive osm : list)
-			osm.selected = false;
-	}
-
-	/**
-	 * Return all selected items in the collection.
-	 * @param list The collection from which the selected items are returned.
-	 */
-	private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
-		Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
-		if (list == null)
-			return sel;
-		for (OsmPrimitive osm : list)
-			if (osm.selected && !osm.deleted)
-				sel.add(osm);
-		return sel;
-	}
-
-	/**
-	 * Remember to fire an selection changed event. A call to this will not fire
-	 * the event immediately. For more, @see SelectionChangedListener
-	 */
-	public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
-		for (SelectionChangedListener l : selListeners)
-			l.selectionChanged(sel);
-	}
-	
-	@Override public DataSet clone() {
-		DataSet ds = new DataSet();
-		for (Node n : nodes)
-			ds.nodes.add(new Node(n));
-		for (Way w : ways)
-			ds.ways.add(new Way(w));
-		for (Relation e : relations)
-			ds.relations.add(new Relation(e));
-		for (DataSource source : dataSources)
-			ds.dataSources.add(new DataSource(source.bounds, source.origin));
-	    return ds;
-    }
-	
-	/**
-	 * Returns the total area of downloaded data (the "yellow rectangles").
-	 * @return Area object encompassing downloaded data.
-	 */
-	public Area getDataSourceArea()
-	{
-		Area a = new Area();
-		for (DataSource source : dataSources) {
-			// create area from data bounds
-			a.add(new Area(source.bounds.asRect()));
-		}
-		return a;
-		
-	}
-
-	// Search für Relation wieder erlauben.
-	public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
-		OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
-		final HashMap<Object, String> h = new HashMap<Object, String>();
-		selArr = list.toArray(selArr);
-		Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
-			public int compare(OsmPrimitive a, OsmPrimitive b)
-			{
-				if(a.getClass() == b.getClass())
-				{
-					String as = h.get(a);
-					if(as == null)
-					{
-						as = a.getName();
-						h.put(a, as);
-					}
-					String bs = h.get(b);
-					if(bs == null)
-					{
-						bs = b.getName();
-						h.put(b, bs);
-					}
-					int res = as.compareTo(bs);
-					if(res != 0)
-						return res;
-				}
-				return a.compareTo(b);
-			}
-		});
-		return selArr;
-	}
+    /**
+     * All nodes goes here, even when included in other data (ways etc). This enables the instant
+     * conversion of the whole DataSet by iterating over this data structure.
+     */
+    public Collection<Node> nodes = new LinkedList<Node>();
+
+    /**
+     * All ways (Streets etc.) in the DataSet.
+     * 
+     * The way nodes are stored only in the way list.
+     */
+    public Collection<Way> ways = new LinkedList<Way>();
+
+    /**
+     * All relations/relationships
+     */
+    public Collection<Relation> relations = new LinkedList<Relation>();
+
+    /**
+     * All data sources of this DataSet.
+     */
+    public Collection<DataSource> dataSources = new LinkedList<DataSource>();
+
+    /**
+     * A list of listeners to selection changed events. The list is static, as listeners register
+     * themselves for any dataset selection changes that occur, regardless of the current active
+     * dataset. (However, the selection does only change in the active layer)
+     */
+    public static Collection<SelectionChangedListener> selListeners = new LinkedList<SelectionChangedListener>();
+
+    /**
+     * @return A collection containing all primitives of the dataset. The data is ordered after:
+     * first come nodes, then ways, then relations. Ordering in between the categories is not
+     * guaranteed.
+     */
+    public List<OsmPrimitive> allPrimitives() {
+        List<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
+        o.addAll(nodes);
+        o.addAll(ways);
+        o.addAll(relations);
+        return o;
+    }
+
+    /**
+     * @return A collection containing all not-deleted primitives (except keys).
+     */
+    public Collection<OsmPrimitive> allNonDeletedPrimitives() {
+        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
+        for (OsmPrimitive osm : allPrimitives())
+            if (!osm.deleted)
+                o.add(osm);
+        return o;
+    }
+
+    public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
+        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
+        for (OsmPrimitive osm : allPrimitives())
+            if (!osm.deleted && !osm.incomplete)
+                o.add(osm);
+        return o;
+    }
+
+    public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
+        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
+        for (OsmPrimitive osm : allPrimitives())
+            if (!osm.deleted && !osm.incomplete && !(osm instanceof Relation))
+                o.add(osm);
+        return o;
+    }
+
+    public void addPrimitive(OsmPrimitive osm) {
+        if (osm instanceof Node) {
+            nodes.add((Node) osm);
+        } else if (osm instanceof Way) {
+            ways.add((Way) osm);
+        } else if (osm instanceof Relation) {
+            relations.add((Relation) osm);
+        }
+    }
+
+    /**
+     * Remove the selection of the whole dataset.
+     * @deprecated Use {@link #setSelected(Collection) setSelected} instead.
+     */
+    @Deprecated public void clearSelection() {
+        clearSelection(nodes);
+        clearSelection(ways);
+        clearSelection(relations);
+        Collection<OsmPrimitive> sel = Collections.emptyList();
+        fireSelectionChanged(sel);
+    }
+
+    /**
+     * Return a list of all selected objects. Even keys are returned.
+     * @return List of all selected objects.
+     */
+    public Collection<OsmPrimitive> getSelected() {
+        Collection<OsmPrimitive> sel = getSelected(nodes);
+        sel.addAll(getSelected(ways));
+        sel.addAll(getSelected(relations));
+        return sel;
+    }
+
+    /**
+     * Return selected nodes.
+     */
+    public Collection<OsmPrimitive> getSelectedNodes() {
+        return getSelected(nodes);
+    }
+
+    /**
+     * Return selected ways.
+     */
+    public Collection<OsmPrimitive> getSelectedWays() {
+        return getSelected(ways);
+    }
+
+    /**
+     * Return selected relations.
+     */
+    public Collection<OsmPrimitive> getSelectedRelations() {
+        return getSelected(relations);
+    }
+
+    public void setSelected(Collection<? extends OsmPrimitive> selection) {
+        clearSelection(nodes);
+        clearSelection(ways);
+        clearSelection(relations);
+        for (OsmPrimitive osm : selection)
+            osm.selected = true;
+        fireSelectionChanged(selection);
+    }
+
+    public void setSelected(OsmPrimitive... osm) {
+        if (osm.length == 1 && osm[0] == null) {
+            setSelected();
+            return;
+        }
+        clearSelection(nodes);
+        clearSelection(ways);
+        clearSelection(relations);
+        for (OsmPrimitive o : osm)
+            if (o != null)
+                o.selected = true;
+        fireSelectionChanged(Arrays.asList(osm));
+    }
+
+    /**
+     * Remove the selection from every value in the collection.
+     * @param list The collection to remove the selection from.
+     */
+    private void clearSelection(Collection<? extends OsmPrimitive> list) {
+        if (list == null)
+            return;
+        for (OsmPrimitive osm : list)
+            osm.selected = false;
+    }
+
+    /**
+     * Return all selected items in the collection.
+     * @param list The collection from which the selected items are returned.
+     */
+    private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
+        Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
+        if (list == null)
+            return sel;
+        for (OsmPrimitive osm : list)
+            if (osm.selected && !osm.deleted)
+                sel.add(osm);
+        return sel;
+    }
+
+    /**
+     * Remember to fire an selection changed event. A call to this will not fire the event
+     * immediately. For more,
+     * @see SelectionChangedListener
+     */
+    public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
+        for (SelectionChangedListener l : selListeners)
+            l.selectionChanged(sel);
+    }
+
+    @Override public DataSet clone() {
+        DataSet ds = new DataSet();
+        for (Node n : nodes)
+            ds.nodes.add(new Node(n));
+        for (Way w : ways)
+            ds.ways.add(new Way(w));
+        for (Relation e : relations)
+            ds.relations.add(new Relation(e));
+        for (DataSource source : dataSources)
+            ds.dataSources.add(new DataSource(source.bounds, source.origin));
+        return ds;
+    }
+
+    /**
+     * Returns the total area of downloaded data (the "yellow rectangles").
+     * @return Area object encompassing downloaded data.
+     */
+    public Area getDataSourceArea() {
+        if (dataSources.isEmpty()) return null;
+        Area a = new Area();
+        for (DataSource source : dataSources) {
+            // create area from data bounds
+            a.add(new Area(source.bounds.asRect()));
+        }
+        return a;
+    }
+
+    // Provide well-defined sorting for collections of OsmPrimitives.
+    // FIXME: probably not a good place to put this code. 
+    public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
+        OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
+        final HashMap<Object, String> h = new HashMap<Object, String>();
+        selArr = list.toArray(selArr);
+        Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
+            public int compare(OsmPrimitive a, OsmPrimitive b) {
+                if (a.getClass() == b.getClass()) {
+                    String as = h.get(a);
+                    if (as == null) {
+                        as = a.getName();
+                        h.put(a, as);
+                    }
+                    String bs = h.get(b);
+                    if (bs == null) {
+                        bs = b.getName();
+                        h.put(b, bs);
+                    }
+                    int res = as.compareTo(bs);
+                    if (res != 0)
+                        return res;
+                }
+                return a.compareTo(b);
+            }
+        });
+        return selArr;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/tools/DontShowAgainInfo.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/DontShowAgainInfo.java	(revision 1003)
+++ trunk/src/org/openstreetmap/josm/tools/DontShowAgainInfo.java	(revision 1004)
@@ -17,16 +17,16 @@
 
 	public static boolean show(String prefKey, String msg) {
-		return show(prefKey, new JLabel(msg), true);
+		return show(prefKey, new JLabel(msg), true, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
 	}
 
 	public static boolean show(String prefKey, String msg, Boolean state) {
-		return show(prefKey, new JLabel(msg), state);
+		return show(prefKey, new JLabel(msg), state, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
 	}
 
 	public static boolean show(String prefKey, Container msg) {
-		return show(prefKey, msg, true);
+		return show(prefKey, msg, true, JOptionPane.OK_CANCEL_OPTION, JOptionPane.OK_OPTION);
 	}
 
-	public static boolean show(String prefKey, Container msg, Boolean state) {
+	public static boolean show(String prefKey, Container msg, Boolean state, int options, int true_option) {
 		if (!Main.pref.getBoolean("message."+prefKey)) {
 			JCheckBox dontshowagain = new JCheckBox(tr("Do not show again"));
@@ -35,6 +35,6 @@
 			all.add(msg, GBC.eop());
 			all.add(dontshowagain, GBC.eol());
-			int answer = JOptionPane.showConfirmDialog(Main.parent, all, tr("Information"), JOptionPane.OK_CANCEL_OPTION);
-			if (answer != JOptionPane.OK_OPTION)
+			int answer = JOptionPane.showConfirmDialog(Main.parent, all, tr("Information"), options);
+			if (answer != true_option)
 				return false;
 			Main.pref.put("message."+prefKey, dontshowagain.isSelected());
