Index: c/org/openstreetmap/josm/actions/DebugAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DebugAction.java	(revision 3)
+++ 	(revision )
@@ -1,77 +1,0 @@
-package org.openstreetmap.josm.actions;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-import javax.swing.JLabel;
-
-import org.openstreetmap.josm.data.GeoPoint;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.MapView;
-
-/**
- * To debug zone information
- * 
- * @author imi
- */
-public class DebugAction extends MapMode implements MouseMotionListener, MouseListener {
-
-	private JLabel label = new JLabel();
-
-	public DebugAction(MapFrame mapFrame) {
-		super("Debug Zones", "debug", KeyEvent.VK_D, mapFrame);
-	}
-	
-	public void registerListener(MapView mapView) {
-		mapView.addMouseMotionListener(this);
-		mapView.addMouseListener(this);
-		mapFrame.add(label, BorderLayout.SOUTH);
-	}
-
-	public void unregisterListener(MapView mapView) {
-		mapView.removeMouseMotionListener(this);
-		mapView.removeMouseListener(this);
-		mapFrame.remove(label);
-	}
-
-	public void mouseDragged(MouseEvent e) {
-	}
-
-	public void mouseMoved(MouseEvent e) {
-		double lon = ((double)e.getX()/mapFrame.mapView.getWidth()*360) - 180;
-		double lat = 90 - (double)e.getY()/mapFrame.mapView.getHeight() * 180;
-		GeoPoint p = new GeoPoint(lat, lon);
-		mapFrame.mapView.getProjection().latlon2xy(p);
-		label.setText("x="+e.getX()+" y="+e.getY()+" lat="+p.lat+" lon="+p.lon+" N="+p.y+" E="+p.x);
-		
-		GeoPoint mousePoint = mapFrame.mapView.getPoint(e.getX(), e.getY(), false);
-		GeoPoint center = mapFrame.mapView.getCenter();
-		double scale = mapFrame.mapView.getScale();
-		int xscr = (int)Math.round((mousePoint.x-center.x) / scale + mapFrame.mapView.getWidth()/2);
-		int yscr = (int)Math.round((center.y-mousePoint.y) / scale + mapFrame.mapView.getHeight()/2);
-		Graphics g = mapFrame.mapView.getGraphics();
-		g.setColor(Color.CYAN);
-		g.drawArc(xscr, yscr, 4,4,0,360);
-	}
-
-	public void mouseClicked(MouseEvent e) {
-	}
-
-	public void mousePressed(MouseEvent e) {
-	}
-
-	public void mouseReleased(MouseEvent e) {
-	}
-
-	public void mouseEntered(MouseEvent e) {
-	}
-
-	public void mouseExited(MouseEvent e) {
-	}
-
-}
Index: c/org/openstreetmap/josm/actions/MapMode.java
===================================================================
--- /src/org/openstreetmap/josm/actions/MapMode.java	(revision 3)
+++ 	(revision )
@@ -1,56 +1,0 @@
-package org.openstreetmap.josm.actions;
-
-import java.awt.event.ActionEvent;
-
-import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
-
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.MapView;
-
-/**
- * A class implementing MapMode is able to be selected as an mode for map editing.
- * As example scrolling the map is a MapMode, connecting Nodes to new LineSegments
- * is another.
- * 
- * MapModes should register/deregister all necessary listener on the map's view
- * control. 
- */
-abstract public class MapMode extends AbstractAction {
-
-	/**
-	 * The parent mapframe this mode belongs to.
-	 */
-	protected final MapFrame mapFrame;
-
-	/**
-	 * Construct a mapMode with the given icon and the given MapFrame
-	 *
-	 * @param iconName The filename of the icon.
-	 * @param mapFrame The parent MapFrame, this MapMode belongs to.
-	 */
-	public MapMode(String name, String iconName, int mnemonic, MapFrame mapFrame) {
-		super(name, new ImageIcon("images/"+iconName+".png"));
-		putValue(MNEMONIC_KEY, mnemonic);
-		this.mapFrame = mapFrame;
-	}
-	
-	/**
-	 * Register all listener to the mapView
-	 * @param mapView	The view, where the listener should be registered.
-	 */
-	abstract public void registerListener(MapView mapView);
-	
-	/**
-	 * Unregister all listener previously registered. 
-	 * @param mapView	The view from which the listener should be deregistered.
-	 */
-	abstract public void unregisterListener(MapView mapView);
-
-	/**
-	 * Call selectMapMode(this) on the parent mapFrame.
-	 */
-	public void actionPerformed(ActionEvent e) {
-		mapFrame.selectMapMode(this);
-	}
-}
Index: c/org/openstreetmap/josm/actions/SelectionAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/SelectionAction.java	(revision 3)
+++ 	(revision )
@@ -1,127 +1,0 @@
-package org.openstreetmap.josm.actions;
-
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-
-import org.openstreetmap.josm.actions.SelectionManager.SelectionEnded;
-import org.openstreetmap.josm.data.osm.LineSegment;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Track;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.MapView;
-
-/**
- * This MapMode enables the user to easy make a selection of different objects.
- * 
- * The selected objects are drawn in a different style.
- * 
- * Holding and dragging the left mouse button draws an selection rectangle. 
- * When releasing the left mouse button, all objects within the rectangle get 
- * selected. 
- * 
- * When releasing the left mouse button while the right mouse button pressed,
- * nothing happens (the selection rectangle will be cleared, however).
- *
- * When releasing the mouse button and one of the following keys was hold:
- *
- * If Alt key was hold, select all objects that are touched by the 
- * selection rectangle. If the Alt key was not hold, select only those objects 
- * completly within (e.g. for tracks mean: only if all nodes of the track are 
- * within).  
- *
- * If Shift key was hold, the objects are added to the current selection. If
- * Shift key wasn't hold, the current selection get replaced.
- * 
- * If Ctrl key was hold, remove all objects under the current rectangle from
- * the active selection (if there were any). Nothing is added to the current
- * selection.
- *
- * Alt can be combined with Ctrl or Shift. Ctrl and Shift cannot be combined.
- * If both are pressed, nothing happens when releasing the mouse button.
- *
- * @author imi
- */
-public class SelectionAction extends MapMode implements SelectionEnded {
-
-	/**
-	 * Shortcut for the MapView.
-	 */
-	private MapView mv;
-	/**
-	 * The SelectionManager that manages the selection rectangle.
-	 */
-	private SelectionManager selectionManager;
-
-	/**
-	 * Create a new SelectionAction in the given frame.
-	 * @param mapFrame
-	 */
-	public SelectionAction(MapFrame mapFrame) {
-		super("Selection", "selection", KeyEvent.VK_S, mapFrame);
-		this.mv = mapFrame.mapView;
-		this.selectionManager = new SelectionManager(this, false, mv);
-	}
-
-	@Override
-	public void registerListener(MapView mapView) {
-		selectionManager.register(mapView);
-	}
-
-	@Override
-	public void unregisterListener(MapView mapView) {
-		selectionManager.unregister(mapView);
-	}
-
-
-	/**
-	 * Check the state of the keys and buttons and set the selection accordingly.
-	 */
-	public void selectionEnded(Rectangle r, int modifiers) {
-		boolean shift = (modifiers & MouseEvent.SHIFT_DOWN_MASK) != 0;
-		boolean alt = (modifiers & MouseEvent.ALT_DOWN_MASK) != 0;
-		boolean ctrl = (modifiers & MouseEvent.CTRL_DOWN_MASK) != 0;
-		if (shift && ctrl)
-			return; // not allowed together
-
-		if (!ctrl && !shift) {
-			// remove the old selection. The new selection will replace the old.
-			mv.dataSet.clearSelection();
-		}
-
-		// now set the selection to this value
-		boolean selection = !ctrl;
-
-		// nodes
-		for (Node n : mv.dataSet.allNodes) {
-			Point sp = mv.getScreenPoint(n.coor);
-			if (r.contains(sp))
-				n.selected = selection;
-		}
-		
-		// tracks
-		for (Track t : mv.dataSet.tracks) {
-			boolean wholeTrackSelected = t.segments.size() > 0;
-			for (LineSegment ls : t.segments) {
-				if (alt) {
-					Point p1 = mv.getScreenPoint(ls.start.coor);
-					Point p2 = mv.getScreenPoint(ls.end.coor);
-					if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
-						ls.selected = selection;
-					else
-						wholeTrackSelected = false;
-				} else {
-					if (r.contains(mv.getScreenPoint(ls.start.coor)) && 
-							r.contains(mv.getScreenPoint(ls.end.coor)))
-						ls.selected = selection;
-					else
-						wholeTrackSelected = false;
-				}
-			}
-			if (wholeTrackSelected)
-				t.selected = true;
-		}
-		mv.repaint();
-	}
-}
Index: c/org/openstreetmap/josm/actions/SelectionManager.java
===================================================================
--- /src/org/openstreetmap/josm/actions/SelectionManager.java	(revision 3)
+++ 	(revision )
@@ -1,231 +1,0 @@
-package org.openstreetmap.josm.actions;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.InputEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-/**
- * Manages the selection of a rectangle. Listening to left and right mouse button
- * presses and to mouse motions and draw the rectangle accordingly.
- * 
- * Left mouse button selects a rectangle from the press until release. Pressing
- * right mouse button while left is still pressed enable the rectangle to move
- * around. Releasing the left button fires an action event to the listener given
- * at constructor, except if the right is still pressed, which just remove the
- * selection rectangle and does nothing.
- * 
- * The point where the left mouse button was pressed and the current mouse 
- * position are two opposite corners of the selection rectangle.
- * 
- * It is possible to specify an aspect ratio (width per height) which the 
- * selection rectangle always must have. In this case, the selection rectangle
- * will be the largest window with this aspect ratio, where the position the left
- * mouse button was pressed and the corner of the current mouse position are at 
- * opposite sites (the mouse position corner is the corner nearest to the mouse
- * cursor). 
- * 
- * When the left mouse button was released, an ActionEvent is send to the 
- * ActionListener given at constructor. The source of this event is this manager.
- * 
- * @author imi
- */
-public class SelectionManager implements MouseListener, MouseMotionListener {
-
-	/**
-	 * This is the interface that an user of SelectionManager has to implement
-	 * to get informed when a selection closes.
-	 * @author imi
-	 */
-	public interface SelectionEnded {
-		/**
-		 * Called, when the left mouse button was released.
-		 * @param r The rectangle, that is currently the selection.
-		 * @param modifiers The modifiers returned from the MouseEvent when
-		 * 		the left mouse button was released. 
-		 * @see InputEvent#getModifiersEx()
-		 */
-		public void selectionEnded(Rectangle r, int modifiers);
-	}
-	/**
-	 * The listener that receives the events after left mouse button is released.
-	 */
-	private final SelectionEnded selectionEndedListener;
-	/**
-	 * Position of the map when the mouse button was pressed.
-	 * If this is not <code>null</code>, a rectangle is drawn on screen. 
-	 */
-	private Point mousePosStart;
-	/**
-	 * Position of the map when the selection rectangle was last drawn.
-	 */
-	private Point mousePos;
-	/**
-	 * The component, the selection rectangle is drawn onto.
-	 */
-	private final Component drawComponent;
-	/**
-	 * Whether the selection rectangle must obtain the aspect ratio of the 
-	 * drawComponent.
-	 */
-	private boolean aspectRatio;
-
-	/**
-	 * Create a new SelectionManager.
-	 *
-	 * @param actionListener The action listener that receives the event when
-	 * 		the left button is released.
-	 * @param aspectRatio If true, the selection window must obtain the aspect
-	 * 		ratio of the drawComponent.
-	 * @param drawComponent The component, the rectangle is drawn onto.
-	 */
-	public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, Component drawComponent) {
-		this.selectionEndedListener = selectionEndedListener;
-		this.aspectRatio = aspectRatio;
-		this.drawComponent = drawComponent;
-	}
-	
-	/**
-	 * Register itself at the given event source.
-	 * @param eventSource The emitter of the mouse events.
-	 */
-	public void register(Component eventSource) {
-		eventSource.addMouseListener(this);
-		eventSource.addMouseMotionListener(this);
-	}
-	/**
-	 * Unregister itself from the given event source. If a selection rectangle is
-	 * shown, hide it first.
-	 *
-	 * @param eventSource The emitter of the mouse events.
-	 */
-	public void unregister(Component eventSource) {
-		eventSource.removeMouseListener(this);
-		eventSource.removeMouseMotionListener(this);
-	}
-
-	/**
-	 * If the correct button, start the "drawing rectangle" mode
-	 */
-	public void mousePressed(MouseEvent e) {
-		if (e.getButton() == MouseEvent.BUTTON1) {
-			mousePosStart = e.getPoint();
-			mousePos = e.getPoint();
-			paintRect();
-		}
-	}
-
-	/**
-	 * If the correct button is hold, draw the rectangle.
-	 */
-	public void mouseDragged(MouseEvent e) {
-		int buttonPressed = e.getModifiersEx() & (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK); 
-
-		if (buttonPressed != 0) {
-			if (mousePosStart == null) {
-				mousePosStart = e.getPoint();
-				mousePos = e.getPoint();
-				paintRect();
-			}
-			paintRect();
-		}
-		
-		if (buttonPressed == MouseEvent.BUTTON1_DOWN_MASK) {
-			mousePos = e.getPoint();
-			paintRect();
-		} else if (buttonPressed == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK)) {
-			mousePosStart.x += e.getX()-mousePos.x;
-			mousePosStart.y += e.getY()-mousePos.y;
-			mousePos = e.getPoint();
-			paintRect();
-		}
-	}
-
-	/**
-	 * Check the state of the keys and buttons and set the selection accordingly.
-	 */
-	public void mouseReleased(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-		// disable the selection rect
-		paintRect();
-		Rectangle r = getSelectionRectangle();
-		mousePosStart = null;
-		mousePos = null;
-		if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 0)
-			selectionEndedListener.selectionEnded(r, e.getModifiersEx());
-	}
-
-
-	/**
-	 * Draw a selection rectangle on screen. If already a rectangle is drawn,
-	 * it is removed instead.
-	 */
-	private void paintRect() {
-		Graphics g = drawComponent.getGraphics();
-		g.setColor(Color.BLACK);
-		g.setXORMode(Color.WHITE);
-
-		Rectangle r = getSelectionRectangle();
-		g.drawRect(r.x,r.y,r.width,r.height);
-	}
-
-	/**
-	 * Calculate and return the current selection rectangle
-	 * @return A rectangle that spans from mousePos to mouseStartPos
-	 */
-	private Rectangle getSelectionRectangle() {
-		int x = mousePosStart.x;
-		int y = mousePosStart.y;
-		int w = mousePos.x - mousePosStart.x;
-		int h = mousePos.y - mousePosStart.y;
-		if (w < 0) {
-			x += w;
-			w = -w;
-		}
-		if (h < 0) {
-			y += h;
-			h = -h;
-		}
-		
-		if (aspectRatio) {
-			// keep the aspect ration by shrinking the rectangle
-			double aspectRatio = (double)drawComponent.getWidth()/drawComponent.getHeight();
-			if ((double)w/h > aspectRatio) {
-				int neww = (int)(h*aspectRatio);
-				if (mousePos.x < mousePosStart.x)
-					x += w-neww;
-				w = neww;
-			} else {
-				int newh = (int)(w/aspectRatio);
-				if (mousePos.y < mousePosStart.y)
-					y += h-newh;
-				h = newh;
-			}
-		}
-		
-		return new Rectangle(x,y,w,h);
-	}
-	
-	/**
-	 * Does nothing. Only to satisfy MouseListener
-	 */
-	public void mouseClicked(MouseEvent e) {}
-	/**
-	 * Does nothing. Only to satisfy MouseListener
-	 */
-	public void mouseEntered(MouseEvent e) {}
-	/**
-	 * Does nothing. Only to satisfy MouseListener
-	 */
-	public void mouseExited(MouseEvent e) {}
-	/**
-	 * Does nothing. Only to satisfy MouseMotionListener
-	 */
-	public void mouseMoved(MouseEvent e) {}
-}
Index: c/org/openstreetmap/josm/actions/ZoomAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/ZoomAction.java	(revision 3)
+++ 	(revision )
@@ -1,60 +1,0 @@
-package org.openstreetmap.josm.actions;
-
-import java.awt.Rectangle;
-import java.awt.event.KeyEvent;
-
-import org.openstreetmap.josm.actions.SelectionManager.SelectionEnded;
-import org.openstreetmap.josm.data.GeoPoint;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.MapView;
-
-/**
- * Enable the zoom mode within the MapFrame. 
- * 
- * Holding down the left mouse button select a rectangle with the same aspect 
- * ratio than the current map view.
- * Holding down left and right let the user move the former selected rectangle.
- * Releasing the left button zoom to the selection.
- * 
- * @author imi
- */
-public class ZoomAction extends MapMode implements SelectionEnded {
-
-	/**
-	 * Shortcut to the mapview.
-	 */
-	private final MapView mv;
-	/**
-	 * Manager that manages the selection rectangle with the aspect ratio of the
-	 * MapView.
-	 */
-	private final SelectionManager selectionManager;
-	
-	
-	/**
-	 * Construct a ZoomAction without a label.
-	 * @param mapFrame The MapFrame, whose zoom mode should be enabled.
-	 */
-	public ZoomAction(MapFrame mapFrame) {
-		super("Zoom", "zoom", KeyEvent.VK_Z, mapFrame);
-		mv = mapFrame.mapView;
-		selectionManager = new SelectionManager(this, true, mv);
-	}
-
-	/**
-	 * Zoom to the rectangle on the map.
-	 */
-	public void selectionEnded(Rectangle r, int modifier) {
-		double scale = mv.getScale() * r.getWidth()/mv.getWidth();
-		GeoPoint newCenter = mv.getPoint(r.x+r.width/2, r.y+r.height/2, false);
-		mv.zoomTo(newCenter, scale);
-	}
-
-	public void registerListener(MapView mapView) {
-		selectionManager.register(mapView);
-	}
-
-	public void unregisterListener(MapView mapView) {
-		selectionManager.unregister(mapView);
-	}
-}
Index: /src/org/openstreetmap/josm/actions/mapmode/DebugAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/DebugAction.java	(revision 4)
+++ /src/org/openstreetmap/josm/actions/mapmode/DebugAction.java	(revision 4)
@@ -0,0 +1,83 @@
+package org.openstreetmap.josm.actions.mapmode;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+import javax.swing.JLabel;
+
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Track;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+
+/**
+ * To debug zone information
+ * 
+ * @author imi
+ */
+public class DebugAction extends MapMode implements MouseMotionListener, MouseListener {
+
+	private JLabel label = new JLabel();
+
+	public DebugAction(MapFrame mapFrame) {
+		super("Debug Zones", "debug", "Debug only. Just ignore.", KeyEvent.VK_D, mapFrame);
+	}
+	
+	public void registerListener(MapView mapView) {
+		mapView.addMouseMotionListener(this);
+		mapView.addMouseListener(this);
+		mapFrame.add(label, BorderLayout.SOUTH);
+	}
+
+	public void unregisterListener(MapView mapView) {
+		mapView.removeMouseMotionListener(this);
+		mapView.removeMouseListener(this);
+		mapFrame.remove(label);
+	}
+
+	public void mouseDragged(MouseEvent e) {
+	}
+
+	public void mouseMoved(MouseEvent e) {
+	}
+
+	public void mouseClicked(MouseEvent e) {
+		Graphics g = mapFrame.mapView.getGraphics();
+		g.setColor(Color.WHITE);
+		for (Track t :mapFrame.mapView.dataSet.tracks)
+			for (LineSegment ls : t.segments) {
+				Point A = mapFrame.mapView.getScreenPoint(ls.start.coor);
+				Point B = mapFrame.mapView.getScreenPoint(ls.end.coor);
+				Point C = e.getPoint();
+				Rectangle r = new Rectangle(A.x, A.y, B.x-A.x, B.y-A.y);
+				double dist = perpendicularDistSq(B.distanceSq(C), A.distanceSq(C), A.distanceSq(B));
+				g.drawString(""+dist, (int)r.getCenterX(), (int)r.getCenterY());
+			}
+	}
+
+	private double perpendicularDistSq(double a, double b, double c) {
+		// I did this on paper by myself, so I am surprised too, that it is that 
+		// performant ;-) 
+		return a-(a-b+c)*(a-b+c)/4/c;
+	}
+
+	public void mousePressed(MouseEvent e) {
+	}
+
+	public void mouseReleased(MouseEvent e) {
+	}
+
+	public void mouseEntered(MouseEvent e) {
+	}
+
+	public void mouseExited(MouseEvent e) {
+	}
+
+}
Index: /src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 4)
+++ /src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 4)
@@ -0,0 +1,57 @@
+package org.openstreetmap.josm.actions.mapmode;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+
+/**
+ * A class implementing MapMode is able to be selected as an mode for map editing.
+ * As example scrolling the map is a MapMode, connecting Nodes to new LineSegments
+ * is another.
+ * 
+ * MapModes should register/deregister all necessary listener on the map's view
+ * control. 
+ */
+abstract public class MapMode extends AbstractAction {
+
+	/**
+	 * The parent mapframe this mode belongs to.
+	 */
+	protected final MapFrame mapFrame;
+
+	/**
+	 * Construct a mapMode with the given icon and the given MapFrame
+	 *
+	 * @param iconName The filename of the icon.
+	 * @param mapFrame The parent MapFrame, this MapMode belongs to.
+	 */
+	public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) {
+		super(name, new ImageIcon("images/"+iconName+".png"));
+		putValue(MNEMONIC_KEY, mnemonic);
+		putValue(LONG_DESCRIPTION, tooltip);
+		this.mapFrame = mapFrame;
+	}
+	
+	/**
+	 * Register all listener to the mapView
+	 * @param mapView	The view, where the listener should be registered.
+	 */
+	abstract public void registerListener(MapView mapView);
+	
+	/**
+	 * Unregister all listener previously registered. 
+	 * @param mapView	The view from which the listener should be deregistered.
+	 */
+	abstract public void unregisterListener(MapView mapView);
+
+	/**
+	 * Call selectMapMode(this) on the parent mapFrame.
+	 */
+	public void actionPerformed(ActionEvent e) {
+		mapFrame.selectMapMode(this);
+	}
+}
Index: /src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 4)
+++ /src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 4)
@@ -0,0 +1,32 @@
+package org.openstreetmap.josm.actions.mapmode;
+
+import java.awt.event.KeyEvent;
+
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+
+/**
+ * Move is an action that can move all kind of OsmPrimitives (except Keys for now).
+ * 
+ * If any object is selected, all selected objects are moved. If no object is 
+ * selected, only nodes can be moved. In this case, the Node which is nearest to
+ * the mouse cursor when the left mouse button is pressed get selected and moved.
+ * (Of course, all primitives, which use this node are moved somewhat too).
+ * 
+ * @author imi
+ */
+public class MoveAction extends MapMode {
+
+	public MoveAction(MapFrame mapFrame) {
+		super("Move", "move", "Move selected objects around", KeyEvent.VK_M, mapFrame);
+	}
+
+	@Override
+	public void registerListener(MapView mapView) {
+	}
+
+	@Override
+	public void unregisterListener(MapView mapView) {
+	}
+
+}
Index: /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 4)
+++ /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 4)
@@ -0,0 +1,199 @@
+package org.openstreetmap.josm.actions.mapmode;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.Point2D;
+
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Track;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.SelectionManager;
+import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
+
+/**
+ * This MapMode enables the user to easy make a selection of different objects.
+ * 
+ * The selected objects are drawn in a different style.
+ * 
+ * Holding and dragging the left mouse button draws an selection rectangle. 
+ * When releasing the left mouse button, all objects within the rectangle get 
+ * selected. 
+ * 
+ * When releasing the left mouse button while the right mouse button pressed,
+ * nothing happens (the selection rectangle will be cleared, however).
+ *
+ * When releasing the mouse button and one of the following keys was hold:
+ *
+ * If Alt key was hold, select all objects that are touched by the 
+ * selection rectangle. If the Alt key was not hold, select only those objects 
+ * completly within (e.g. for tracks mean: only if all nodes of the track are 
+ * within).  
+ *
+ * If Shift key was hold, the objects are added to the current selection. If
+ * Shift key wasn't hold, the current selection get replaced.
+ * 
+ * If Ctrl key was hold, remove all objects under the current rectangle from
+ * the active selection (if there were any). Nothing is added to the current
+ * selection.
+ *
+ * Alt can be combined with Ctrl or Shift. Ctrl and Shift cannot be combined.
+ * If both are pressed, nothing happens when releasing the mouse button.
+ *
+ * The user can also only click on the map. All total movements of 2 or less 
+ * pixel are considered "only click". If that happens, the nearest Node will
+ * be selected if there is any within 10 pixel range. If there is no Node within
+ * 10 pixel, the nearest LineSegment (or Street, if user hold down the Alt-Key)
+ * within 10 pixel range is selected. If there is no LineSegment within 10 pixel
+ * and the user clicked in or 10 pixel away from an area, this area is selected. 
+ * If there is even no area, nothing is selected. Shift and Ctrl key applies to 
+ * this as usual.
+ *
+ * @author imi
+ */
+public class SelectionAction extends MapMode implements SelectionEnded {
+
+	/**
+	 * Shortcut for the MapView.
+	 */
+	private MapView mv;
+	/**
+	 * The SelectionManager that manages the selection rectangle.
+	 */
+	private SelectionManager selectionManager;
+
+	/**
+	 * Create a new SelectionAction in the given frame.
+	 * @param mapFrame
+	 */
+	public SelectionAction(MapFrame mapFrame) {
+		super("Selection", "selection", "Select objects by dragging or clicking", KeyEvent.VK_S, mapFrame);
+		this.mv = mapFrame.mapView;
+		this.selectionManager = new SelectionManager(this, false, mv);
+	}
+
+	@Override
+	public void registerListener(MapView mapView) {
+		selectionManager.register(mapView);
+	}
+
+	@Override
+	public void unregisterListener(MapView mapView) {
+		selectionManager.unregister(mapView);
+	}
+
+
+	/**
+	 * Check the state of the keys and buttons and set the selection accordingly.
+	 */
+	public void selectionEnded(Rectangle r, int modifiers) {
+		boolean shift = (modifiers & MouseEvent.SHIFT_DOWN_MASK) != 0;
+		boolean alt = (modifiers & MouseEvent.ALT_DOWN_MASK) != 0;
+		boolean ctrl = (modifiers & MouseEvent.CTRL_DOWN_MASK) != 0;
+		if (shift && ctrl)
+			return; // not allowed together
+
+		if (!ctrl && !shift) {
+			// remove the old selection. The new selection will replace the old.
+			mv.dataSet.clearSelection();
+		}
+
+		// now set the selection to this value
+		boolean selection = !ctrl;
+
+		// whether user only clicked, not dragged.
+		boolean clicked = r.width <= 2 && r.height <= 2;
+		Point2D.Double center = new Point2D.Double(r.getCenterX(), r.getCenterY());
+
+		try {
+			// nodes
+			double minDistanceSq = Double.MAX_VALUE;
+			OsmPrimitive minPrimitive = null;
+			for (Node n : mv.dataSet.allNodes) {
+				Point sp = mv.getScreenPoint(n.coor);
+				double dist = center.distanceSq(sp);
+				if (clicked && minDistanceSq > dist && dist < 100) {
+					minDistanceSq = center.distanceSq(sp);
+					minPrimitive = n;
+				} else if (r.contains(sp))
+					n.selected = selection;
+			}
+			if (minPrimitive != null) {
+				minPrimitive.selected = selection;
+				return;
+			}
+
+			// tracks
+			minDistanceSq = Double.MAX_VALUE;
+			for (Track t : mv.dataSet.tracks) {
+				boolean wholeTrackSelected = t.segments.size() > 0;
+				for (LineSegment ls : t.segments) {
+					if (clicked) {
+						Point A = mv.getScreenPoint(ls.start.coor);
+						Point B = mv.getScreenPoint(ls.end.coor);
+						double c = A.distanceSq(B);
+						double a = center.distanceSq(B);
+						double b = center.distanceSq(A);
+						double perDist = perpendicularDistSq(a,b,c);
+						if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
+							minDistanceSq = perDist;
+							if (alt)
+								minPrimitive = t;
+							else
+								minPrimitive = ls;
+						}
+					} else {
+						if (alt) {
+							Point p1 = mv.getScreenPoint(ls.start.coor);
+							Point p2 = mv.getScreenPoint(ls.end.coor);
+							if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
+								ls.selected = selection;
+							else
+								wholeTrackSelected = false;
+						} else {
+							if (r.contains(mv.getScreenPoint(ls.start.coor))
+									&& r.contains(mv.getScreenPoint(ls.end.coor)))
+								ls.selected = selection;
+							else
+								wholeTrackSelected = false;
+						}
+					}
+				}
+				if (wholeTrackSelected && !clicked)
+					t.selected = true;
+			}
+			if (minPrimitive != null) {
+				minPrimitive.selected = selection;
+				return;
+			}
+			
+			// TODO arrays
+		} finally {
+			mv.repaint();
+		}
+	}
+
+	/**
+	 * Calculates the squared perpendicular distance named "h" from a point C to the
+	 * straight line going to the points A and B, where the distance to B is 
+	 * sqrt(a) and the distance to A is sqrt(b).
+	 * 
+	 * Think of a, b and c as the squared line lengths of any ordinary triangle 
+	 * A,B,C. a = BC, b = AC and c = AB. The straight line goes through A and B 
+	 * and the desired return value is the perpendicular distance from C to c.
+	 *
+	 * @param a Squared distance from B to C.
+	 * @param b Squared distance from A to C.
+	 * @param c Squared distance from A to B.
+	 * @return The perpendicular distance from C to c.
+	 */
+	private double perpendicularDistSq(double a, double b, double c) {
+		// I did this on paper by myself, so I am surprised too, that it is that 
+		// performant ;-) 
+		return a-(a-b+c)*(a-b+c)/4/c;
+	}
+}
Index: /src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 4)
+++ /src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 4)
@@ -0,0 +1,61 @@
+package org.openstreetmap.josm.actions.mapmode;
+
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+
+import org.openstreetmap.josm.data.GeoPoint;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.SelectionManager;
+import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
+
+/**
+ * Enable the zoom mode within the MapFrame. 
+ * 
+ * Holding down the left mouse button select a rectangle with the same aspect 
+ * ratio than the current map view.
+ * Holding down left and right let the user move the former selected rectangle.
+ * Releasing the left button zoom to the selection.
+ * 
+ * @author imi
+ */
+public class ZoomAction extends MapMode implements SelectionEnded {
+
+	/**
+	 * Shortcut to the mapview.
+	 */
+	private final MapView mv;
+	/**
+	 * Manager that manages the selection rectangle with the aspect ratio of the
+	 * MapView.
+	 */
+	private final SelectionManager selectionManager;
+	
+	
+	/**
+	 * Construct a ZoomAction without a label.
+	 * @param mapFrame The MapFrame, whose zoom mode should be enabled.
+	 */
+	public ZoomAction(MapFrame mapFrame) {
+		super("Zoom", "zoom", "Zoom in by dragging", KeyEvent.VK_Z, mapFrame);
+		mv = mapFrame.mapView;
+		selectionManager = new SelectionManager(this, true, mv);
+	}
+
+	/**
+	 * Zoom to the rectangle on the map.
+	 */
+	public void selectionEnded(Rectangle r, int modifier) {
+		double scale = mv.getScale() * r.getWidth()/mv.getWidth();
+		GeoPoint newCenter = mv.getPoint(r.x+r.width/2, r.y+r.height/2, false);
+		mv.zoomTo(newCenter, scale);
+	}
+
+	public void registerListener(MapView mapView) {
+		selectionManager.register(mapView);
+	}
+
+	public void unregisterListener(MapView mapView) {
+		selectionManager.unregister(mapView);
+	}
+}
Index: /src/org/openstreetmap/josm/gui/IconToggleButton.java
===================================================================
--- /src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 3)
+++ /src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 4)
@@ -2,4 +2,5 @@
 
 import javax.swing.Action;
+import javax.swing.JComponent;
 import javax.swing.JToggleButton;
 
@@ -15,7 +16,10 @@
 	 * Construct the toggle button with the given action.
 	 */
-	public IconToggleButton(Action action) {
+	public IconToggleButton(JComponent acceleratorReceiver, Action action) {
 		super(action);
 		setText(null);
+		Object o = action.getValue(Action.LONG_DESCRIPTION);
+		if (o != null)
+			setToolTipText(o.toString());
 	}
 }
Index: /src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 3)
+++ /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 4)
@@ -25,8 +25,8 @@
 import javax.swing.event.ChangeListener;
 
-import org.openstreetmap.josm.actions.DebugAction;
-import org.openstreetmap.josm.actions.MapMode;
-import org.openstreetmap.josm.actions.SelectionAction;
-import org.openstreetmap.josm.actions.ZoomAction;
+import org.openstreetmap.josm.actions.mapmode.DebugAction;
+import org.openstreetmap.josm.actions.mapmode.MapMode;
+import org.openstreetmap.josm.actions.mapmode.SelectionAction;
+import org.openstreetmap.josm.actions.mapmode.ZoomAction;
 import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -125,7 +125,7 @@
 		
 		toolBarActions.setFloatable(false);
-		toolBarActions.add(new IconToggleButton(new ZoomAction(this)));
-		toolBarActions.add(new IconToggleButton(new SelectionAction(this)));
-		toolBarActions.add(new IconToggleButton(new DebugAction(this)));
+		toolBarActions.add(new IconToggleButton(this, new ZoomAction(this)));
+		toolBarActions.add(new IconToggleButton(this, new SelectionAction(this)));
+		toolBarActions.add(new IconToggleButton(this, new DebugAction(this)));
 
 		// all map modes in one button group
@@ -138,5 +138,5 @@
 		// autoScale
 		toolBarActions.addSeparator();
-		final JToggleButton autoScaleButton = new IconToggleButton(mapView.new AutoScaleAction());
+		final JToggleButton autoScaleButton = new IconToggleButton(this, mapView.new AutoScaleAction());
 		toolBarActions.add(autoScaleButton);
 		autoScaleButton.setText(null);
@@ -149,5 +149,5 @@
 
 		// properties
-		toolBarActions.add(new IconToggleButton(new PropertiesAction()));
+		toolBarActions.add(new IconToggleButton(this, new PropertiesAction()));
 	}
 
Index: /src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapView.java	(revision 3)
+++ /src/org/openstreetmap/josm/gui/MapView.java	(revision 4)
@@ -2,5 +2,4 @@
 
 import java.awt.Color;
-import java.awt.Component;
 import java.awt.Graphics;
 import java.awt.Point;
@@ -14,4 +13,5 @@
 import javax.swing.AbstractAction;
 import javax.swing.ImageIcon;
+import javax.swing.JComponent;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
@@ -37,5 +37,5 @@
  * @author imi
  */
-public class MapView extends Component implements ComponentListener, ChangeListener {
+public class MapView extends JComponent implements ComponentListener, ChangeListener {
 
 	/**
@@ -251,5 +251,5 @@
 			for (Track track : dataSet.tracks)
 				for (LineSegment ls : track.segments) {
-					g.setColor(ls.selected ? Color.WHITE : Color.GRAY);
+					g.setColor(ls.selected || track.selected ? Color.WHITE : Color.GRAY);
 					g.drawLine(toScreenX(ls.start.coor.x), toScreenY(ls.start.coor.y),
 							toScreenX(ls.end.coor.x), toScreenY(ls.end.coor.y));
Index: /src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- /src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 4)
+++ /src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 4)
@@ -0,0 +1,231 @@
+package org.openstreetmap.josm.gui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * Manages the selection of a rectangle. Listening to left and right mouse button
+ * presses and to mouse motions and draw the rectangle accordingly.
+ * 
+ * Left mouse button selects a rectangle from the press until release. Pressing
+ * right mouse button while left is still pressed enable the rectangle to move
+ * around. Releasing the left button fires an action event to the listener given
+ * at constructor, except if the right is still pressed, which just remove the
+ * selection rectangle and does nothing.
+ * 
+ * The point where the left mouse button was pressed and the current mouse 
+ * position are two opposite corners of the selection rectangle.
+ * 
+ * It is possible to specify an aspect ratio (width per height) which the 
+ * selection rectangle always must have. In this case, the selection rectangle
+ * will be the largest window with this aspect ratio, where the position the left
+ * mouse button was pressed and the corner of the current mouse position are at 
+ * opposite sites (the mouse position corner is the corner nearest to the mouse
+ * cursor). 
+ * 
+ * When the left mouse button was released, an ActionEvent is send to the 
+ * ActionListener given at constructor. The source of this event is this manager.
+ * 
+ * @author imi
+ */
+public class SelectionManager implements MouseListener, MouseMotionListener {
+
+	/**
+	 * This is the interface that an user of SelectionManager has to implement
+	 * to get informed when a selection closes.
+	 * @author imi
+	 */
+	public interface SelectionEnded {
+		/**
+		 * Called, when the left mouse button was released.
+		 * @param r The rectangle, that is currently the selection.
+		 * @param modifiers The modifiers returned from the MouseEvent when
+		 * 		the left mouse button was released. 
+		 * @see InputEvent#getModifiersEx()
+		 */
+		public void selectionEnded(Rectangle r, int modifiers);
+	}
+	/**
+	 * The listener that receives the events after left mouse button is released.
+	 */
+	private final SelectionEnded selectionEndedListener;
+	/**
+	 * Position of the map when the mouse button was pressed.
+	 * If this is not <code>null</code>, a rectangle is drawn on screen. 
+	 */
+	private Point mousePosStart;
+	/**
+	 * Position of the map when the selection rectangle was last drawn.
+	 */
+	private Point mousePos;
+	/**
+	 * The component, the selection rectangle is drawn onto.
+	 */
+	private final Component drawComponent;
+	/**
+	 * Whether the selection rectangle must obtain the aspect ratio of the 
+	 * drawComponent.
+	 */
+	private boolean aspectRatio;
+
+	/**
+	 * Create a new SelectionManager.
+	 *
+	 * @param actionListener The action listener that receives the event when
+	 * 		the left button is released.
+	 * @param aspectRatio If true, the selection window must obtain the aspect
+	 * 		ratio of the drawComponent.
+	 * @param drawComponent The component, the rectangle is drawn onto.
+	 */
+	public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, Component drawComponent) {
+		this.selectionEndedListener = selectionEndedListener;
+		this.aspectRatio = aspectRatio;
+		this.drawComponent = drawComponent;
+	}
+	
+	/**
+	 * Register itself at the given event source.
+	 * @param eventSource The emitter of the mouse events.
+	 */
+	public void register(Component eventSource) {
+		eventSource.addMouseListener(this);
+		eventSource.addMouseMotionListener(this);
+	}
+	/**
+	 * Unregister itself from the given event source. If a selection rectangle is
+	 * shown, hide it first.
+	 *
+	 * @param eventSource The emitter of the mouse events.
+	 */
+	public void unregister(Component eventSource) {
+		eventSource.removeMouseListener(this);
+		eventSource.removeMouseMotionListener(this);
+	}
+
+	/**
+	 * If the correct button, start the "drawing rectangle" mode
+	 */
+	public void mousePressed(MouseEvent e) {
+		if (e.getButton() == MouseEvent.BUTTON1) {
+			mousePosStart = e.getPoint();
+			mousePos = e.getPoint();
+			paintRect();
+		}
+	}
+
+	/**
+	 * If the correct button is hold, draw the rectangle.
+	 */
+	public void mouseDragged(MouseEvent e) {
+		int buttonPressed = e.getModifiersEx() & (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK); 
+
+		if (buttonPressed != 0) {
+			if (mousePosStart == null) {
+				mousePosStart = e.getPoint();
+				mousePos = e.getPoint();
+				paintRect();
+			}
+			paintRect();
+		}
+		
+		if (buttonPressed == MouseEvent.BUTTON1_DOWN_MASK) {
+			mousePos = e.getPoint();
+			paintRect();
+		} else if (buttonPressed == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK)) {
+			mousePosStart.x += e.getX()-mousePos.x;
+			mousePosStart.y += e.getY()-mousePos.y;
+			mousePos = e.getPoint();
+			paintRect();
+		}
+	}
+
+	/**
+	 * Check the state of the keys and buttons and set the selection accordingly.
+	 */
+	public void mouseReleased(MouseEvent e) {
+		if (e.getButton() != MouseEvent.BUTTON1)
+			return;
+		// disable the selection rect
+		paintRect();
+		Rectangle r = getSelectionRectangle();
+		mousePosStart = null;
+		mousePos = null;
+		if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 0)
+			selectionEndedListener.selectionEnded(r, e.getModifiersEx());
+	}
+
+
+	/**
+	 * Draw a selection rectangle on screen. If already a rectangle is drawn,
+	 * it is removed instead.
+	 */
+	private void paintRect() {
+		Graphics g = drawComponent.getGraphics();
+		g.setColor(Color.BLACK);
+		g.setXORMode(Color.WHITE);
+
+		Rectangle r = getSelectionRectangle();
+		g.drawRect(r.x,r.y,r.width,r.height);
+	}
+
+	/**
+	 * Calculate and return the current selection rectangle
+	 * @return A rectangle that spans from mousePos to mouseStartPos
+	 */
+	private Rectangle getSelectionRectangle() {
+		int x = mousePosStart.x;
+		int y = mousePosStart.y;
+		int w = mousePos.x - mousePosStart.x;
+		int h = mousePos.y - mousePosStart.y;
+		if (w < 0) {
+			x += w;
+			w = -w;
+		}
+		if (h < 0) {
+			y += h;
+			h = -h;
+		}
+		
+		if (aspectRatio) {
+			// keep the aspect ration by shrinking the rectangle
+			double aspectRatio = (double)drawComponent.getWidth()/drawComponent.getHeight();
+			if ((double)w/h > aspectRatio) {
+				int neww = (int)(h*aspectRatio);
+				if (mousePos.x < mousePosStart.x)
+					x += w-neww;
+				w = neww;
+			} else {
+				int newh = (int)(w/aspectRatio);
+				if (mousePos.y < mousePosStart.y)
+					y += h-newh;
+				h = newh;
+			}
+		}
+		
+		return new Rectangle(x,y,w,h);
+	}
+	
+	/**
+	 * Does nothing. Only to satisfy MouseListener
+	 */
+	public void mouseClicked(MouseEvent e) {}
+	/**
+	 * Does nothing. Only to satisfy MouseListener
+	 */
+	public void mouseEntered(MouseEvent e) {}
+	/**
+	 * Does nothing. Only to satisfy MouseListener
+	 */
+	public void mouseExited(MouseEvent e) {}
+	/**
+	 * Does nothing. Only to satisfy MouseMotionListener
+	 */
+	public void mouseMoved(MouseEvent e) {}
+}
