Index: src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 41)
+++ src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 42)
@@ -110,4 +110,6 @@
 			}
 		});
+		wc.addListMarker(bookmarks);
+		wc.addLatLonInputField(latlon);
 		dlg.add(new JScrollPane(bookmarks), GBC.eol().fill());
 
Index: src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- src/org/openstreetmap/josm/data/Preferences.java	(revision 41)
+++ src/org/openstreetmap/josm/data/Preferences.java	(revision 42)
@@ -18,5 +18,5 @@
 import org.jdom.output.Format;
 import org.jdom.output.XMLOutputter;
-import org.openstreetmap.josm.data.projection.LatitudeLongitude;
+import org.openstreetmap.josm.data.projection.Epsg4263;
 import org.openstreetmap.josm.data.projection.Mercator;
 import org.openstreetmap.josm.data.projection.Projection;
@@ -80,5 +80,5 @@
 		new Mercator(),
 		new UTM(),
-		new LatitudeLongitude()
+		new Epsg4263()
 	};
 
Index: src/org/openstreetmap/josm/data/projection/Epsg4263.java
===================================================================
--- src/org/openstreetmap/josm/data/projection/Epsg4263.java	(revision 42)
+++ src/org/openstreetmap/josm/data/projection/Epsg4263.java	(revision 42)
@@ -0,0 +1,39 @@
+package org.openstreetmap.josm.data.projection;
+
+import javax.swing.JComponent;
+
+import org.openstreetmap.josm.data.GeoPoint;
+
+/**
+ * Directly use latitude / longitude values as x/y.
+ *
+ * @author imi
+ */
+public class Epsg4263 extends Projection {
+
+	@Override
+	public void latlon2xy(GeoPoint p) {
+		p.x = p.lon;
+		p.y = p.lat;
+	}
+
+	@Override
+	public void xy2latlon(GeoPoint p) {
+		p.lat = p.y;
+		p.lon = p.x;
+	}
+
+	@Override
+	public String toString() {
+		return "EPSG:4263";
+	}
+
+	@Override
+	public JComponent getConfigurationPanel() {
+		return null;
+	}
+
+	@Override
+	public void commitConfigurationPanel() {
+	}
+}
Index: src/org/openstreetmap/josm/data/projection/LatitudeLongitude.java
===================================================================
--- src/org/openstreetmap/josm/data/projection/LatitudeLongitude.java	(revision 41)
+++ 	(revision )
@@ -1,39 +1,0 @@
-package org.openstreetmap.josm.data.projection;
-
-import javax.swing.JComponent;
-
-import org.openstreetmap.josm.data.GeoPoint;
-
-/**
- * Directly use latitude / longitude values as x/y.
- *
- * @author imi
- */
-public class LatitudeLongitude extends Projection {
-
-	@Override
-	public void latlon2xy(GeoPoint p) {
-		p.x = p.lon;
-		p.y = p.lat;
-	}
-
-	@Override
-	public void xy2latlon(GeoPoint p) {
-		p.lat = p.y;
-		p.lon = p.x;
-	}
-
-	@Override
-	public String toString() {
-		return "Latitude/Longitude";
-	}
-
-	@Override
-	public JComponent getConfigurationPanel() {
-		return null;
-	}
-
-	@Override
-	public void commitConfigurationPanel() {
-	}
-}
Index: src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapMover.java	(revision 41)
+++ src/org/openstreetmap/josm/gui/MapMover.java	(revision 42)
@@ -32,10 +32,10 @@
 	private Cursor oldCursor;
 
+	
 	/**
 	 * Create a new MapMover
-	 * @param mapView The map that should be moved.
 	 */
-	public MapMover(NavigatableComponent mapView) {
-		this.nc = mapView;
+	MapMover(NavigatableComponent navComp) {
+		this.nc = navComp;
 		nc.addMouseListener(this);
 		nc.addMouseMotionListener(this);
Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 41)
+++ src/org/openstreetmap/josm/gui/MapView.java	(revision 42)
@@ -11,5 +11,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedList;
 
@@ -21,8 +20,5 @@
 import org.openstreetmap.josm.data.GeoPoint;
 import org.openstreetmap.josm.data.osm.DataSet;
-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.data.projection.Projection;
 import org.openstreetmap.josm.gui.layer.Layer;
@@ -103,8 +99,8 @@
 		// initialize the projection if it is the first layer
 		if (layers.isEmpty())
-			Main.pref.getProjection().init(layer.getBoundsLatLon());
+			getProjection().init(layer.getBoundsLatLon());
 
 		// reinitialize layer's data
-		layer.init(Main.pref.getProjection());
+		layer.init(getProjection());
 
 		if (layer instanceof OsmDataLayer) {
@@ -161,145 +157,4 @@
 	}
 
-	/**
-	 * Return the object, that is nearest to the given screen point.
-	 * 
-	 * First, a node will be searched. If a node within 10 pixel is found, the
-	 * nearest node is returned.
-	 * 
-	 * If no node is found, search for pending line segments.
-	 * 
-	 * If no such line segment is found, and a non-pending line segment is 
-	 * within 10 pixel to p, this segment is returned, except when 
-	 * <code>wholeTrack</code> is <code>true</code>, in which case the 
-	 * corresponding Track is returned.
-	 * 
-	 * If no line segment is found and the point is within an area, return that
-	 * area.
-	 * 
-	 * If no area is found, return <code>null</code>.
-	 * 
-	 * @param p				 The point on screen.
-	 * @param lsInsteadTrack Whether the line segment (true) or only the whole
-	 * 					 	 track should be returned.
-	 * @return	The primitive, that is nearest to the point p.
-	 */
-	public OsmPrimitive getNearest(Point p, boolean lsInsteadTrack) {
-		double minDistanceSq = Double.MAX_VALUE;
-		OsmPrimitive minPrimitive = null;
-
-		// nodes
-		for (Node n : Main.main.ds.nodes) {
-			if (n.isDeleted())
-				continue;
-			Point sp = getScreenPoint(n.coor);
-			double dist = p.distanceSq(sp);
-			if (minDistanceSq > dist && dist < 100) {
-				minDistanceSq = p.distanceSq(sp);
-				minPrimitive = n;
-			}
-		}
-		if (minPrimitive != null)
-			return minPrimitive;
-		
-		// for whole tracks, try the tracks first
-		minDistanceSq = Double.MAX_VALUE;
-		if (!lsInsteadTrack) {
-			for (Track t : Main.main.ds.tracks) {
-				if (t.isDeleted())
-					continue;
-				for (LineSegment ls : t.segments) {
-					if (ls.isDeleted())
-						continue;
-					Point A = getScreenPoint(ls.start.coor);
-					Point B = getScreenPoint(ls.end.coor);
-					double c = A.distanceSq(B);
-					double a = p.distanceSq(B);
-					double b = p.distanceSq(A);
-					double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
-					if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
-						minDistanceSq = perDist;
-						minPrimitive = t;
-					}
-				}			
-			}
-			if (minPrimitive != null)
-				return minPrimitive;
-		}
-		
-		minDistanceSq = Double.MAX_VALUE;
-		// line segments
-		for (LineSegment ls : Main.main.ds.lineSegments) {
-			if (ls.isDeleted())
-				continue;
-			Point A = getScreenPoint(ls.start.coor);
-			Point B = getScreenPoint(ls.end.coor);
-			double c = A.distanceSq(B);
-			double a = p.distanceSq(B);
-			double b = p.distanceSq(A);
-			double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
-			if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
-				minDistanceSq = perDist;
-				minPrimitive = ls;
-			}
-		}
-
-		return minPrimitive;
-	}
-
-	/**
-	 * @return A list of all objects that are nearest to 
-	 * the mouse. To do this, first the nearest object is 
-	 * determined.
-	 * 
-	 * If its a node, return all line segments and
-	 * streets the node is part of, as well as all nodes
-	 * (with their line segments and tracks) with the same
-	 * location.
-	 * 
-	 * If its a line segment, return all tracks this segment 
-	 * belongs to as well as all line segments that are between
-	 * the same nodes (in both direction) with all their tracks.
-	 * 
-	 * @return A collection of all items or <code>null</code>
-	 * 		if no item under or near the point. The returned
-	 * 		list is never empty.
-	 */
-	public Collection<OsmPrimitive> getAllNearest(Point p) {
-		OsmPrimitive osm = getNearest(p, true);
-		if (osm == null)
-			return null;
-		Collection<OsmPrimitive> c = new HashSet<OsmPrimitive>();
-		c.add(osm);
-		if (osm instanceof Node) {
-			Node node = (Node)osm;
-			for (Node n : Main.main.ds.nodes)
-				if (!n.isDeleted() && n.coor.equalsLatLon(node.coor))
-					c.add(n);
-			for (LineSegment ls : Main.main.ds.lineSegments)
-				// line segments never match nodes, so they are skipped by contains
-				if (!ls.isDeleted() && (c.contains(ls.start) || c.contains(ls.end)))
-					c.add(ls);
-		} 
-		if (osm instanceof LineSegment) {
-			LineSegment line = (LineSegment)osm;
-			for (LineSegment ls : Main.main.ds.lineSegments)
-				if (!ls.isDeleted() && ls.equalPlace(line))
-					c.add(ls);
-		}
-		if (osm instanceof Node || osm instanceof LineSegment) {
-			for (Track t : Main.main.ds.tracks) {
-				if (t.isDeleted())
-					continue;
-				for (LineSegment ls : t.segments) {
-					if (!ls.isDeleted() && c.contains(ls)) {
-						c.add(t);
-						break;
-					}
-				}
-			}
-		}
-		return c;
-	}
-	
 	/**
 	 * Draw the component.
@@ -378,9 +233,9 @@
 				// no bounds means standard scale and center 
 				center = new GeoPoint(51.526447, -0.14746371);
-				Main.pref.getProjection().latlon2xy(center);
+				getProjection().latlon2xy(center);
 				scale = 10;
 			} else {
 				center = bounds.centerXY();
-				Main.pref.getProjection().xy2latlon(center);
+				getProjection().xy2latlon(center);
 				double scaleX = (bounds.max.x-bounds.min.x)/w;
 				double scaleY = (bounds.max.y-bounds.min.y)/h;
@@ -483,5 +338,5 @@
 	public void stateChanged(ChangeEvent e) {
 		// reset all datasets.
-		Projection p = Main.pref.getProjection();
+		Projection p = getProjection();
 		for (Node n : Main.main.ds.nodes)
 			p.latlon2xy(n.coor);
Index: src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 41)
+++ src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 42)
@@ -2,4 +2,6 @@
 
 import java.awt.Point;
+import java.util.Collection;
+import java.util.HashSet;
 
 import javax.swing.JComponent;
@@ -7,4 +9,9 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.GeoPoint;
+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.data.projection.Projection;
 
 /**
@@ -17,5 +24,7 @@
 
 	/**
-	 * The scale factor in meter per pixel.
+	 * The scale factor in x or y-units per pixel. This means, if scale = 10,
+	 * every physical pixel on screen are 10 x or 10 y units in the 
+	 * northing/easting space of the projection.
 	 */
 	protected double scale;
@@ -58,8 +67,8 @@
 	public GeoPoint getPoint(int x, int y, boolean latlon) {
 		GeoPoint p = new GeoPoint();
-		p.x = (x - getWidth()/2.0)*scale + center.x;
-		p.y = (getHeight()/2.0 - y)*scale + center.y;
+		p.x = center.x + (x - getWidth()/2.0)*scale;
+		p.y = center.y - (y - getHeight()/2.0)*scale;
 		if (latlon)
-			Main.pref.getProjection().xy2latlon(p);
+			getProjection().xy2latlon(p);
 		return p;
 	}
@@ -79,9 +88,9 @@
 				throw new IllegalArgumentException("point: Either lat/lon or x/y must be set.");
 			p = point.clone();
-			Main.pref.getProjection().latlon2xy(p);
-		}
-		int x = ((int)Math.round((p.x-center.x) / scale + getWidth()/2));
-		int y = ((int)Math.round((center.y-p.y) / scale + getHeight()/2));
-		return new Point(x,y);
+			getProjection().latlon2xy(p);
+		}
+		double x = (p.x-center.x)/scale + getWidth()/2;
+		double y = (center.y-p.y)/scale + getHeight()/2;
+		return new Point((int)x,(int)y);
 	}
 
@@ -93,9 +102,156 @@
 	 */
 	public void zoomTo(GeoPoint newCenter, double scale) {
-		System.out.println(scale);
 		center = newCenter.clone();
-		Main.pref.getProjection().xy2latlon(center);
+		getProjection().xy2latlon(center);
 		this.scale = scale;
 		repaint();
 	}
+
+	/**
+	 * Return the object, that is nearest to the given screen point.
+	 * 
+	 * First, a node will be searched. If a node within 10 pixel is found, the
+	 * nearest node is returned.
+	 * 
+	 * If no node is found, search for pending line segments.
+	 * 
+	 * If no such line segment is found, and a non-pending line segment is 
+	 * within 10 pixel to p, this segment is returned, except when 
+	 * <code>wholeTrack</code> is <code>true</code>, in which case the 
+	 * corresponding Track is returned.
+	 * 
+	 * If no line segment is found and the point is within an area, return that
+	 * area.
+	 * 
+	 * If no area is found, return <code>null</code>.
+	 * 
+	 * @param p				 The point on screen.
+	 * @param lsInsteadTrack Whether the line segment (true) or only the whole
+	 * 					 	 track should be returned.
+	 * @return	The primitive, that is nearest to the point p.
+	 */
+	public OsmPrimitive getNearest(Point p, boolean lsInsteadTrack) {
+		double minDistanceSq = Double.MAX_VALUE;
+		OsmPrimitive minPrimitive = null;
+	
+		// nodes
+		for (Node n : Main.main.ds.nodes) {
+			if (n.isDeleted())
+				continue;
+			Point sp = getScreenPoint(n.coor);
+			double dist = p.distanceSq(sp);
+			if (minDistanceSq > dist && dist < 100) {
+				minDistanceSq = p.distanceSq(sp);
+				minPrimitive = n;
+			}
+		}
+		if (minPrimitive != null)
+			return minPrimitive;
+		
+		// for whole tracks, try the tracks first
+		minDistanceSq = Double.MAX_VALUE;
+		if (!lsInsteadTrack) {
+			for (Track t : Main.main.ds.tracks) {
+				if (t.isDeleted())
+					continue;
+				for (LineSegment ls : t.segments) {
+					if (ls.isDeleted())
+						continue;
+					Point A = getScreenPoint(ls.start.coor);
+					Point B = getScreenPoint(ls.end.coor);
+					double c = A.distanceSq(B);
+					double a = p.distanceSq(B);
+					double b = p.distanceSq(A);
+					double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
+					if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
+						minDistanceSq = perDist;
+						minPrimitive = t;
+					}
+				}			
+			}
+			if (minPrimitive != null)
+				return minPrimitive;
+		}
+		
+		minDistanceSq = Double.MAX_VALUE;
+		// line segments
+		for (LineSegment ls : Main.main.ds.lineSegments) {
+			if (ls.isDeleted())
+				continue;
+			Point A = getScreenPoint(ls.start.coor);
+			Point B = getScreenPoint(ls.end.coor);
+			double c = A.distanceSq(B);
+			double a = p.distanceSq(B);
+			double b = p.distanceSq(A);
+			double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
+			if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
+				minDistanceSq = perDist;
+				minPrimitive = ls;
+			}
+		}
+	
+		return minPrimitive;
+	}
+
+	/**
+	 * @return A list of all objects that are nearest to 
+	 * the mouse. To do this, first the nearest object is 
+	 * determined.
+	 * 
+	 * If its a node, return all line segments and
+	 * streets the node is part of, as well as all nodes
+	 * (with their line segments and tracks) with the same
+	 * location.
+	 * 
+	 * If its a line segment, return all tracks this segment 
+	 * belongs to as well as all line segments that are between
+	 * the same nodes (in both direction) with all their tracks.
+	 * 
+	 * @return A collection of all items or <code>null</code>
+	 * 		if no item under or near the point. The returned
+	 * 		list is never empty.
+	 */
+	public Collection<OsmPrimitive> getAllNearest(Point p) {
+		OsmPrimitive osm = getNearest(p, true);
+		if (osm == null)
+			return null;
+		Collection<OsmPrimitive> c = new HashSet<OsmPrimitive>();
+		c.add(osm);
+		if (osm instanceof Node) {
+			Node node = (Node)osm;
+			for (Node n : Main.main.ds.nodes)
+				if (!n.isDeleted() && n.coor.equalsLatLon(node.coor))
+					c.add(n);
+			for (LineSegment ls : Main.main.ds.lineSegments)
+				// line segments never match nodes, so they are skipped by contains
+				if (!ls.isDeleted() && (c.contains(ls.start) || c.contains(ls.end)))
+					c.add(ls);
+		} 
+		if (osm instanceof LineSegment) {
+			LineSegment line = (LineSegment)osm;
+			for (LineSegment ls : Main.main.ds.lineSegments)
+				if (!ls.isDeleted() && ls.equalPlace(line))
+					c.add(ls);
+		}
+		if (osm instanceof Node || osm instanceof LineSegment) {
+			for (Track t : Main.main.ds.tracks) {
+				if (t.isDeleted())
+					continue;
+				for (LineSegment ls : t.segments) {
+					if (!ls.isDeleted() && c.contains(ls)) {
+						c.add(t);
+						break;
+					}
+				}
+			}
+		}
+		return c;
+	}
+	
+	/**
+	 * @return The projection to be used in calculating stuff.
+	 */
+	protected Projection getProjection() {
+		return Main.pref.getProjection();
+	}
 }
Index: src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 41)
+++ src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 42)
@@ -89,7 +89,7 @@
 	private Point mousePos;
 	/**
-	 * The MapView, the selection rectangle is drawn onto.
-	 */
-	private final MapView mv;
+	 * The Component, the selection rectangle is drawn onto.
+	 */
+	private final NavigatableComponent nc;
 	/**
 	 * Whether the selection rectangle must obtain the aspect ratio of the 
@@ -105,10 +105,10 @@
 	 * @param aspectRatio If true, the selection window must obtain the aspect
 	 * 		ratio of the drawComponent.
-	 * @param mapView The view, the rectangle is drawn onto.
-	 */
-	public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, MapView mapView) {
+	 * @param navComp The component, the rectangle is drawn onto.
+	 */
+	public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, NavigatableComponent navComp) {
 		this.selectionEndedListener = selectionEndedListener;
 		this.aspectRatio = aspectRatio;
-		this.mv = mapView;
+		this.nc = navComp;
 	}
 	
@@ -196,5 +196,5 @@
 		if (mousePos == null || mousePosStart == null || mousePos == mousePosStart)
 			return;
-		Graphics g = mv.getGraphics();
+		Graphics g = nc.getGraphics();
 		g.setColor(Color.BLACK);
 		g.setXORMode(Color.WHITE);
@@ -224,5 +224,5 @@
 		if (aspectRatio) {
 			// keep the aspect ration by shrinking the rectangle
-			double aspectRatio = (double)mv.getWidth()/mv.getHeight();
+			double aspectRatio = (double)nc.getWidth()/nc.getHeight();
 			if ((double)w/h > aspectRatio) {
 				int neww = (int)(h*aspectRatio);
@@ -267,5 +267,5 @@
 
 		if (clicked) {
-			OsmPrimitive osm = mv.getNearest(center, alt);
+			OsmPrimitive osm = nc.getNearest(center, alt);
 			if (osm != null)
 				selection.add(osm);
@@ -273,5 +273,5 @@
 			// nodes
 			for (Node n : Main.main.ds.nodes) {
-				if (r.contains(mv.getScreenPoint(n.coor)))
+				if (r.contains(nc.getScreenPoint(n.coor)))
 					selection.add(n);
 			}
@@ -310,11 +310,11 @@
 	private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) {
 		if (alt) {
-			Point p1 = mv.getScreenPoint(ls.start.coor);
-			Point p2 = mv.getScreenPoint(ls.end.coor);
+			Point p1 = nc.getScreenPoint(ls.start.coor);
+			Point p2 = nc.getScreenPoint(ls.end.coor);
 			if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
 				return true;
 		} else {
-			if (r.contains(mv.getScreenPoint(ls.start.coor))
-					&& r.contains(mv.getScreenPoint(ls.end.coor)))
+			if (r.contains(nc.getScreenPoint(ls.start.coor))
+					&& r.contains(nc.getScreenPoint(ls.end.coor)))
 				return true;
 		}
Index: src/org/openstreetmap/josm/gui/WorldChooser.java
===================================================================
--- src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 41)
+++ src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 42)
@@ -4,13 +4,25 @@
 import java.awt.Dimension;
 import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.beans.PropertyChangeListener;
 import java.net.URL;
 
 import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.GeoPoint;
+import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.gui.BookmarkList.Bookmark;
+import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
 
 /**
@@ -30,8 +42,15 @@
 
 	/**
+	 * Maximum scale level
+	 */
+	private double scaleMax;
+	
+	/**
 	 * Mark this rectangle (lat/lon values) when painting.
 	 */
-	protected double[] markerRect;
-
+	protected Bounds marker;
+
+	private Projection projection;
+	
 	/**
 	 * Create the chooser component.
@@ -40,7 +59,30 @@
 		URL path = Main.class.getResource("/images/world.jpg");
 		world = new ImageIcon(path);
-		center = new GeoPoint(0,0,30,165);
+		center = new GeoPoint(0,0,world.getIconWidth()/2, world.getIconHeight()/2);
 		setPreferredSize(new Dimension(200, 100));
-		//new MapMover(this);
+		new MapMover(this);
+		projection = new Projection(){
+			@Override
+			public void latlon2xy(GeoPoint p) {
+				p.x = (p.lon+180) / 360 * world.getIconWidth();
+				p.y = (p.lat+90) / 180 * world.getIconHeight();
+			}
+			@Override
+			public void xy2latlon(GeoPoint p) {
+				p.lon = p.x*360/world.getIconWidth() - 180;
+				p.lat = p.y*180/world.getIconHeight() - 90;
+			}
+			@Override
+			public String toString() {
+				return "WorldChooser";
+			}
+			@Override
+			public JComponent getConfigurationPanel() {
+				return null;
+			}
+			@Override
+			public void commitConfigurationPanel() {
+			}
+		};
 	}
 
@@ -52,5 +94,6 @@
 	public void setPreferredSize(Dimension preferredSize) {
 		super.setPreferredSize(preferredSize);
-		scale = 60/preferredSize.getWidth();
+		scale = world.getIconWidth()/preferredSize.getWidth();
+		scaleMax = scale;
 	}
 
@@ -61,15 +104,23 @@
 	@Override
 	public void paint(Graphics g) {
-		int x1 = getScreenPoint(new GeoPoint(0,0,0,180)).x;
-		int y1 = getScreenPoint(new GeoPoint(0,0,0,180)).y;
-		int x2 = getScreenPoint(new GeoPoint(0,0,360,0)).x;
-		int y2 = getScreenPoint(new GeoPoint(0,0,360,0)).y;
-		System.out.println(x1+" "+y1+" "+x2+" "+y2);
-		System.out.println(center.x+" "+center.y+" "+(scale*getWidth()));
-		g.drawImage(world.getImage(),0,0,getWidth(),getHeight(),x1,y1,x2,y2, null);
-		g.setColor(Color.WHITE);
-		
+		GeoPoint tl = getPoint(0,0,false);
+		GeoPoint br = getPoint(getWidth(),getHeight(),false);
+		g.drawImage(world.getImage(),0,0,getWidth(),getHeight(),(int)tl.x,(int)tl.y,(int)br.x,(int)br.y, null);
+
 		// draw marker rect
-		//TODO
+		if (marker != null) {
+			Point p1 = getScreenPoint(marker.min);
+			Point p2 = getScreenPoint(marker.max);
+			double x = Math.min(p1.x, p2.x);
+			double y = Math.min(p1.y, p2.y);
+			double w = Math.max(p1.x, p2.x) - x;
+			double h = Math.max(p1.y, p2.y) - y;
+			if (w < 1)
+				w = 1;
+			if (h < 1)
+				h = 1;
+			g.setColor(Color.YELLOW);
+			g.drawRect((int)x, (int)y, (int)w, (int)h);
+		}
 	}
 
@@ -77,9 +128,9 @@
 	@Override
 	public void zoomTo(GeoPoint newCenter, double scale) {
-		if (getWidth() != 0 && scale < 60.0/getWidth())
-			scale = 60.0/getWidth();
+		if (getWidth() != 0 && scale > scaleMax)
+			scale = scaleMax;
 		super.zoomTo(newCenter, scale);
 	}
-	
+
 	/**
 	 * Show the selection bookmark in the world.
@@ -89,11 +140,83 @@
 			public void valueChanged(ListSelectionEvent e) {
 				Bookmark b = (Bookmark)list.getSelectedValue();
-				if (b != null)
-					markerRect = b.latlon;
-				else
-					markerRect = null;
+				if (b != null) {
+					marker = new Bounds(new GeoPoint(b.latlon[0],b.latlon[1]),
+							new GeoPoint(b.latlon[2],b.latlon[3]));
+				} else
+					marker = null;
 				repaint();
 			}
 		});
 	}
+
+	/**
+	 * Update edit fields and react upon changes.
+	 * @param field Must have exactly 4 entries (min lat to max lon)
+	 */
+	public void addLatLonInputField(final JTextField[] field) {
+		if (field.length != 4)
+			throw new IllegalArgumentException();
+
+		// listener that invokes updateMarkerFromTextField after all
+		// messages are dispatched and so text fields are updated.
+		KeyListener listener = new KeyAdapter(){
+			@Override
+			public void keyTyped(KeyEvent e) {
+				SwingUtilities.invokeLater(new Runnable(){
+					public void run() {
+						updateMarkerFromTextFields(field);
+					}
+				});
+			}
+		};
+
+		for (JTextField f : field)
+			f.addKeyListener(listener);
+
+		SelectionEnded selListener = new SelectionEnded(){
+			public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
+				GeoPoint min = getPoint(r.x, r.y+r.height, true);
+				GeoPoint max = getPoint(r.x+r.width, r.y, true);
+				marker = new Bounds(min, max);
+				field[0].setText(""+min.lat);
+				field[1].setText(""+min.lon);
+				field[2].setText(""+max.lat);
+				field[3].setText(""+max.lon);
+				for (JTextField f : field)
+					f.setCaretPosition(0);
+				repaint();
+			}
+			public void addPropertyChangeListener(PropertyChangeListener listener) {}
+			public void removePropertyChangeListener(PropertyChangeListener listener) {}
+		};
+		SelectionManager sm = new SelectionManager(selListener, false, this);
+		sm.register(this);
+		updateMarkerFromTextFields(field);
+	}
+
+	/**
+	 * Update the marker field from the values of the given textfields
+	 */
+	private void updateMarkerFromTextFields(JTextField[] field) {
+		// try to read all values
+		double v[] = new double[field.length];
+		for (int i = 0; i < field.length; ++i) {
+			try {
+				v[i] = Double.parseDouble(field[i].getText());
+			} catch (NumberFormatException nfe) {
+				return;
+			}
+		}
+
+		marker = new Bounds(new GeoPoint(v[0], v[1]), new GeoPoint(v[2], v[3]));
+		repaint();
+	}
+
+	/**
+	 * Always use our image projection mode.
+	 */
+	@Override
+	protected Projection getProjection() {
+		return projection;
+	}
 }
