Index: src/org/openstreetmap/josm/actions/AutoScaleAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 17)
+++ src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 17)
@@ -0,0 +1,39 @@
+package org.openstreetmap.josm.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JComponent;
+import javax.swing.KeyStroke;
+
+import org.openstreetmap.josm.gui.ImageProvider;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+
+/**
+ * Toggles the autoScale feature of the mapView
+ * @author imi
+ */
+public class AutoScaleAction extends AbstractAction {
+	/**
+	 * The mapView this action operates on.
+	 */
+	private final MapView mapView;
+	
+	public AutoScaleAction(MapFrame mapFrame) {
+		super("Auto Scale", ImageProvider.get("autoscale"));
+		mapView = mapFrame.mapView;
+		putValue(MNEMONIC_KEY, KeyEvent.VK_A);
+		putValue(SHORT_DESCRIPTION, "Zoom the view to show the whole layer. Disabled if the view is moved.");
+		KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
+		putValue(ACCELERATOR_KEY, ks);
+		mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this);
+		mapFrame.getActionMap().put(this, this);
+	}
+
+
+	public void actionPerformed(ActionEvent e) {
+		mapView.setAutoScale(!mapView.isAutoScale());
+	}
+}
Index: src/org/openstreetmap/josm/actions/ExitAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/ExitAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/ExitAction.java	(revision 17)
@@ -5,7 +5,6 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
 
-import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.ImageProvider;
 
 /**
@@ -20,6 +19,7 @@
 	 */
 	public ExitAction() {
-		super("Exit", new ImageIcon(Main.class.getResource("/images/exit.png")));
+		super("Exit", ImageProvider.get("exit"));
 		putValue(MNEMONIC_KEY, KeyEvent.VK_X);
+		putValue(SHORT_DESCRIPTION, "Exit the application.");
 	}
 	
Index: src/org/openstreetmap/josm/actions/OpenGpxAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/OpenGpxAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/OpenGpxAction.java	(revision 17)
@@ -1,4 +1,5 @@
 package org.openstreetmap.josm.actions;
 
+import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -8,12 +9,19 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
+import javax.swing.Box;
+import javax.swing.JCheckBox;
 import javax.swing.JFileChooser;
+import javax.swing.JLabel;
 import javax.swing.JOptionPane;
+import javax.swing.JPanel;
 import javax.swing.filechooser.FileFilter;
 
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.GBC;
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.Main;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerFactory;
 import org.openstreetmap.josm.io.GpxReader;
 import org.openstreetmap.josm.io.DataReader.ConnectionException;
@@ -32,6 +40,7 @@
 	 */
 	public OpenGpxAction() {
-		super("Open GPX", new ImageIcon(Main.class.getResource("/images/opengpx.png")));
+		super("Open GPX", ImageProvider.get("opengpx"));
 		putValue(MNEMONIC_KEY, KeyEvent.VK_O);
+		putValue(SHORT_DESCRIPTION, "Open a file in GPX format.");
 	}
 
@@ -48,5 +57,25 @@
 				return "GPX or XML Files";
 			}});
-		fc.showOpenDialog(Main.main);
+		
+		// additional options
+		JCheckBox rawGps = new JCheckBox("Raw GPS data", true);
+		rawGps.setToolTipText("Check this, if the data are obtained from a gps device.");
+		JCheckBox newLayer = new JCheckBox("As Layer", true); 
+		newLayer.setToolTipText("Open as a new layer or replace all current layers.");
+		if (Main.main.getMapFrame() == null) {
+			newLayer.setEnabled(false);
+			newLayer.setSelected(false);
+		}
+		
+		JPanel p = new JPanel(new GridBagLayout());
+		p.add(new JLabel("Options"), GBC.eop());
+		p.add(rawGps, GBC.eol());
+		p.add(newLayer, GBC.eol());
+		p.add(Box.createVerticalGlue(), GBC.eol().fill());
+		fc.setAccessory(p);
+
+		if (fc.showOpenDialog(Main.main) != JFileChooser.APPROVE_OPTION)
+			return;
+		
 		File gpxFile = fc.getSelectedFile();
 		if (gpxFile == null)
@@ -54,7 +83,13 @@
 		
 		try {
-			DataSet dataSet = new GpxReader(new FileReader(gpxFile)).parse();
-			MapFrame map = new MapFrame(dataSet);
-			Main.main.setMapFrame(gpxFile.getName(), map);
+			DataSet dataSet = new GpxReader(new FileReader(gpxFile), rawGps.isSelected()).parse();
+
+			Layer layer = LayerFactory.create(dataSet, gpxFile.getName(), rawGps.isSelected());
+			
+			if (Main.main.getMapFrame() == null || !newLayer.isSelected())
+				Main.main.setMapFrame(gpxFile.getName(), new MapFrame(layer));
+			else
+				Main.main.getMapFrame().mapView.addLayer(layer);
+			
 		} catch (ParseException x) {
 			x.printStackTrace();
Index: src/org/openstreetmap/josm/actions/PreferencesAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 17)
@@ -5,7 +5,6 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
 
-import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.PreferenceDialog;
 
@@ -21,6 +20,7 @@
 	 */
 	public PreferencesAction() {
-		super("Preferences", new ImageIcon(Main.class.getResource("/images/preference.png")));
+		super("Preferences", ImageProvider.get("preference"));
 		putValue(MNEMONIC_KEY, KeyEvent.VK_P);
+		putValue(SHORT_DESCRIPTION, "Open a preferences page for global settings.");
 	}
 
Index: src/org/openstreetmap/josm/actions/SaveGpxAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveGpxAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/SaveGpxAction.java	(revision 17)
@@ -8,8 +8,8 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
 import javax.swing.JFileChooser;
 import javax.swing.JOptionPane;
 
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.Main;
 import org.openstreetmap.josm.io.GpxWriter;
@@ -28,6 +28,7 @@
 	 */
 	public SaveGpxAction() {
-		super("Save GPX", new ImageIcon(Main.class.getResource("/images/savegpx.png")));
+		super("Save GPX", ImageProvider.get("savegpx"));
 		putValue(MNEMONIC_KEY, KeyEvent.VK_S);
+		putValue(SHORT_DESCRIPTION, "Save the current active layer as GPX file.");
 	}
 	
@@ -46,5 +47,5 @@
 		try {
 			FileWriter fileWriter = new FileWriter(gpxFile);
-			GpxWriter out = new GpxWriter(fileWriter, Main.main.getMapFrame().mapView.dataSet);
+			GpxWriter out = new GpxWriter(fileWriter, Main.main.getMapFrame().mapView.getActiveDataSet());
 			out.output();
 			fileWriter.close();
Index: src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 17)
@@ -10,4 +10,5 @@
 import javax.swing.JOptionPane;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.LineSegment;
 import org.openstreetmap.josm.data.osm.Node;
@@ -129,4 +130,6 @@
 		
 		if (start != end) {
+			DataSet ds = mv.getActiveDataSet();
+
 			// try to find a line segment
 			for (Track t : ds.tracks())
@@ -183,3 +186,8 @@
 		hintDrawn = !hintDrawn;
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 17)
@@ -24,5 +24,5 @@
 	 */
 	public AddNodeAction(MapFrame mapFrame) {
-		super("Add nodes", "addnode", "Add new nodes to the map.", KeyEvent.VK_A, mapFrame);
+		super("Add nodes", "addnode", "Add nodes to the map.", KeyEvent.VK_N, mapFrame);
 	}
 
@@ -48,7 +48,12 @@
 			Node node = new Node();
 			node.coor = mv.getPoint(e.getX(), e.getY(), true);
-			ds.nodes.add(node);
+			mv.getActiveDataSet().nodes.add(node);
 			mv.repaint();
 		}
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java	(revision 17)
@@ -6,4 +6,5 @@
 import java.util.LinkedList;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.LineSegment;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -75,4 +76,6 @@
 			return; // not allowed together
 
+		DataSet ds = mv.getActiveDataSet();
+		
 		if (!ctrl && !shift)
 			ds.clearSelection(); // new selection will replace the old.
@@ -105,3 +108,8 @@
 		ds.clearSelection();
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/CombineAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/CombineAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/CombineAction.java	(revision 17)
@@ -9,4 +9,5 @@
 import javax.swing.JOptionPane;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.LineSegment;
 import org.openstreetmap.josm.data.osm.Node;
@@ -82,5 +83,5 @@
 		mv.addMouseListener(this);
 		mv.addMouseMotionListener(this);
-		ds.clearSelection();
+		mv.getActiveDataSet().clearSelection();
 	}
 
@@ -165,5 +166,5 @@
 				else	
 					t1.keys.putAll(t2.keys);
-				ds.removeTrack(t2);
+				mv.getActiveDataSet().removeTrack(t2);
 			}
 		}
@@ -178,4 +179,5 @@
 	 */
 	private void combine(LineSegment ls, Track t) {
+		DataSet ds = mv.getActiveDataSet();
 		if (!ds.pendingLineSegments().contains(ls))
 			throw new IllegalStateException("Should not be able to select non-pending line segments.");
@@ -216,5 +218,5 @@
 			Point start = mv.getScreenPoint(ls.getStart().coor);
 			Point end = mv.getScreenPoint(ls.getEnd().coor);
-			if (mv.dataSet.pendingLineSegments().contains(osm) && g.getColor() == Color.GRAY)
+			if (mv.getActiveDataSet().pendingLineSegments().contains(osm) && g.getColor() == Color.GRAY)
 				g.drawLine(start.x, start.y, end.x, end.y);
 			else
@@ -225,3 +227,8 @@
 		}
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/DebugAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DebugAction.java	(revision 16)
+++ 	(revision )
@@ -1,64 +1,0 @@
-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 javax.swing.JLabel;
-
-import org.openstreetmap.josm.data.osm.LineSegment;
-import org.openstreetmap.josm.data.osm.Track;
-import org.openstreetmap.josm.gui.MapFrame;
-
-/**
- * To debug zone information
- * 
- * @author imi
- */
-public class DebugAction extends MapMode {
-
-	private JLabel label = new JLabel();
-
-	public DebugAction(MapFrame mapFrame) {
-		super("Debug Zones", "debug", "Debug only. Just ignore.", KeyEvent.VK_D, mapFrame);
-	}
-	
-	@Override
-	public void registerListener() {
-		super.registerListener();
-		mv.addMouseMotionListener(this);
-		mv.addMouseListener(this);
-		mapFrame.add(label, BorderLayout.SOUTH);
-	}
-
-	@Override
-	public void unregisterListener() {
-		super.unregisterListener();
-		mv.removeMouseMotionListener(this);
-		mv.removeMouseListener(this);
-		mapFrame.remove(label);
-	}
-
-	@Override
-	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.getStart().coor);
-				Point B = mapFrame.mapView.getScreenPoint(ls.getEnd().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) {
-		return a-(a-b+c)*(a-b+c)/4/c;
-	}
-}
Index: src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 17)
@@ -10,4 +10,5 @@
 import javax.swing.JOptionPane;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Key;
 import org.openstreetmap.josm.data.osm.LineSegment;
@@ -93,8 +94,10 @@
 			return;
 
+		DataSet ds = mv.getActiveDataSet();
+
 		if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0)
-			deleteWithReferences(sel);
+			deleteWithReferences(sel, ds);
 		else
-			delete(sel);
+			delete(sel, ds);
 
 		mv.repaint();
@@ -126,5 +129,5 @@
 	 * @param osm The object to delete.
 	 */
-	private void deleteWithReferences(OsmPrimitive osm) {
+	private void deleteWithReferences(OsmPrimitive osm, DataSet ds) {
 		// collect all tracks, areas and pending line segments that should be deleted
 		ArrayList<Track> tracksToDelete = new ArrayList<Track>();
@@ -172,5 +175,5 @@
 		// removing all unreferenced nodes
 		for (Node n : checkUnreferencing) {
-			if (!isReferenced(n))
+			if (!isReferenced(n, ds))
 				ds.nodes.remove(n);
 		}
@@ -187,9 +190,9 @@
 	 * @param osm The object to delete.
 	 */
-	private void delete(OsmPrimitive osm) {
+	private void delete(OsmPrimitive osm, DataSet ds) {
 		if (osm instanceof Node) {
 			Node n = (Node)osm;
-			if (isReferenced(n)) {
-				String combined = combine(n);
+			if (isReferenced(n, ds)) {
+				String combined = combine(n, ds);
 				if (combined != null) {
 					JOptionPane.showMessageDialog(Main.main, combined);
@@ -222,5 +225,5 @@
 	 * @return Whether the node is used by a track or area.
 	 */
-	private boolean isReferenced(Node n) {
+	private boolean isReferenced(Node n, DataSet ds) {
 		for (Track t : ds.tracks())
 			for (LineSegment ls : t.segments())
@@ -243,5 +246,5 @@
 	 * 		are problems combining the node.
 	 */
-	private String combine(Node n) {
+	private String combine(Node n, DataSet ds) {
 		// first, check for pending line segments
 		for (LineSegment ls : ds.pendingLineSegments())
@@ -365,3 +368,8 @@
 		return first;
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 17)
@@ -7,12 +7,12 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
 import javax.swing.JComponent;
 import javax.swing.KeyStroke;
 
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.Layer;
 
 /**
@@ -34,8 +34,4 @@
 	 */
 	protected final MapView mv;
-	/**
-	 * Shortcut to the DataSet.
-	 */
-	protected final DataSet ds;
 
 	/**
@@ -46,5 +42,5 @@
 	 */
 	public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) {
-		super(name, new ImageIcon(Main.class.getResource("/images/mapmode/"+iconName+".png")));
+		super(name, ImageProvider.get("mapmode", iconName));
 		putValue(MNEMONIC_KEY, mnemonic);
 		putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic,0));
@@ -54,7 +50,19 @@
 		this.mapFrame = mapFrame;
 		mv = mapFrame.mapView;
-		ds = mv.dataSet;
+		mv.addLayerChangeListener(new LayerChangeListener(){
+			public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+				setEnabled(!isEditMode() || newLayer.isEditable());
+			}
+			public void layerAdded(Layer newLayer) {}
+			public void layerRemoved(Layer oldLayer) {}
+		});
 	}
-	
+
+	/**
+	 * Subclasses should return whether they want to edit the map data or
+	 * whether they are read-only.
+	 */
+	abstract protected boolean isEditMode();
+
 	/**
 	 * Register all listener to the mapView
Index: src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 17)
@@ -8,4 +8,5 @@
 import java.util.HashSet;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -79,5 +80,5 @@
 			return;
 
-		Collection<OsmPrimitive> selection = ds.getSelected();
+		Collection<OsmPrimitive> selection = mv.getActiveDataSet().getSelected();
 		// creating a list of all nodes that should be moved.
 		Collection<Node> movingNodes = new HashSet<Node>();
@@ -110,4 +111,6 @@
 			return;
 
+		DataSet ds = mv.getActiveDataSet();
+
 		if (ds.getSelected().size() == 0) {
 			OsmPrimitive osm = mv.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0);
@@ -131,7 +134,12 @@
 		mv.setCursor(oldCursor);
 		if (singleOsmPrimitive != null) {
-			singleOsmPrimitive.setSelected(false, ds);
+			singleOsmPrimitive.setSelected(false, mv.getActiveDataSet());
 			mv.repaint();
 		}
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return true;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 17)
@@ -5,4 +5,5 @@
 import java.util.Collection;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.MapFrame;
@@ -86,4 +87,6 @@
 			return; // not allowed together
 
+		DataSet ds = mv.getActiveDataSet();
+
 		if (!ctrl && !shift)
 			ds.clearSelection(); // new selection will replace the old.
@@ -94,3 +97,8 @@
 		mv.repaint();
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return false;
+	}
 }
Index: src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 16)
+++ src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 17)
@@ -68,3 +68,8 @@
 		selectionManager.unregister(mv);
 	}
+
+	@Override
+	protected boolean isEditMode() {
+		return false;
+	}
 }
Index: src/org/openstreetmap/josm/data/GeoPoint.java
===================================================================
--- src/org/openstreetmap/josm/data/GeoPoint.java	(revision 16)
+++ src/org/openstreetmap/josm/data/GeoPoint.java	(revision 17)
@@ -59,4 +59,9 @@
 	}
 	
-	
+	/**
+	 * @return <code>true</code>, if the other GeoPoint has the same lat/lon values.
+	 */
+	public boolean equalsLatLon(GeoPoint other) {
+		return lat == other.lat && lon == other.lon;
+	}
 }
Index: src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- src/org/openstreetmap/josm/data/Preferences.java	(revision 16)
+++ src/org/openstreetmap/josm/data/Preferences.java	(revision 17)
@@ -1,4 +1,6 @@
 package org.openstreetmap.josm.data;
 
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.FileReader;
@@ -38,4 +40,8 @@
 
 
+	/**
+	 * Whether lines should be drawn between track points of raw gps data.
+	 */
+	private boolean drawRawGpsLines = false;
 	/**
 	 * Whether nodes on the same place should be considered identical.
@@ -100,4 +106,5 @@
 
 			mergeNodes = root.getChild("mergeNodes") != null;
+			drawRawGpsLines = root.getChild("drawRawGpsLines") != null;
 		} catch (Exception e) {
 			if (e instanceof PreferencesException)
@@ -120,4 +127,6 @@
 		if (mergeNodes)
 			children.add(new Element("mergeNodes"));
+		if (drawRawGpsLines)
+			children.add(new Element("drawRawGpsLines"));
 
 		try {
@@ -134,19 +143,12 @@
 	
 	/**
-	 * This interface notifies any interested about changes in the projection
-	 * @author imi
-	 */
-	public interface ProjectionChangeListener {
-		void projectionChanged(Projection oldProjection, Projection newProjection);
-	}
-	/**
 	 * The list of all listeners to projection changes.
 	 */
-	private Collection<ProjectionChangeListener> listener = new LinkedList<ProjectionChangeListener>();
+	private Collection<PropertyChangeListener> listener = new LinkedList<PropertyChangeListener>();
 	/**
 	 * Add a listener of projection changes to the list of listeners.
 	 * @param listener The listerner to add.
 	 */
-	public void addProjectionChangeListener(ProjectionChangeListener listener) {
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
 		if (listener != null)
 			this.listener.add(listener);
@@ -155,7 +157,23 @@
 	 * Remove the listener from the list.
 	 */
-	public void removeProjectionChangeListener(ProjectionChangeListener listener) {
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
 		this.listener.remove(listener);
 	}
+	/**
+	 * Fires a PropertyChangeEvent if the old value differs from the new value.
+	 */
+	private <T> void firePropertyChanged(String name, T oldValue, T newValue) {
+		if (oldValue == newValue)
+			return;
+		PropertyChangeEvent evt = null;
+		for (PropertyChangeListener l : listener) {
+			if (evt == null)
+				evt = new PropertyChangeEvent(this, name, oldValue, newValue);
+			l.propertyChange(evt);
+		}
+	}
+
+	// getter / setter
+	
 	/**
 	 * Set the projection and fire an event to all ProjectionChangeListener
@@ -165,7 +183,5 @@
 		Projection old = this.projection;
 		this.projection = projection;
-		if (old != projection)
-			for (ProjectionChangeListener l : listener)
-				l.projectionChanged(old, projection);
+		firePropertyChanged("projection", old, projection);
 	}
 	/**
@@ -176,3 +192,11 @@
 		return projection;
 	}
+	public void setDrawRawGpsLines(boolean drawRawGpsLines) {
+		boolean old = this.drawRawGpsLines;
+		this.drawRawGpsLines = drawRawGpsLines;
+		firePropertyChanged("drawRawGpsLines", old, drawRawGpsLines);
+	}
+	public boolean isDrawRawGpsLines() {
+		return drawRawGpsLines;
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 16)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 17)
@@ -186,4 +186,30 @@
 
 	/**
+	 * Import the given dataset by merging all data with this dataset.
+	 * The objects imported are not cloned, so from now on, these data belong
+	 * to both datasets. So use mergeFrom only if you are about to abandon the
+	 * other dataset or this dataset.
+	 * 
+	 * @param ds	The DataSet to merge into this one.
+	 * @param mergeEqualNodes If <code>true</code>, nodes with the same lat/lon
+	 * 		are merged together.
+	 */
+	public void mergeFrom(DataSet ds, boolean mergeEqualNodes) {
+		if (mergeEqualNodes) {
+			LinkedList<Node> nodesToAdd = new LinkedList<Node>();
+			for (Node n : ds.nodes)
+				for (Node mynode : nodes) {
+					if (mynode.coor.equalsLatLon(n.coor))
+						mynode.mergeFrom(n);
+					else
+						nodesToAdd.add(n);
+				}
+		} else
+			nodes.addAll(ds.nodes);
+		tracks.addAll(ds.tracks);
+		pendingLineSegments.addAll(ds.pendingLineSegments);
+	}
+
+	/**
 	 * Remove the selection from every value in the collection.
 	 * @param list The collection to remove the selection from.
Index: src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Node.java	(revision 16)
+++ src/org/openstreetmap/josm/data/osm/Node.java	(revision 17)
@@ -33,4 +33,20 @@
 		return Collections.unmodifiableCollection(parentSegment);
 	}
+
+	/**
+	 * Merge the node given at parameter with this node.
+	 * All parents of the parameter-node become parents of this node.
+	 * 
+	 * The argument node is not changed.
+	 * 
+	 * @param node Merge the node to this.
+	 */
+	public void mergeFrom(Node node) {
+		parentSegment.addAll(node.parentSegment);
+		if (keys == null)
+			keys = node.keys;
+		else if (node.keys != null)
+			keys.putAll(node.keys);
+	}
 	
 	/**
Index: src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 16)
+++ src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 17)
@@ -7,5 +7,4 @@
 
 import javax.swing.Icon;
-import javax.swing.ImageIcon;
 
 import org.openstreetmap.josm.data.osm.Key;
@@ -13,5 +12,5 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Track;
-import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.ImageProvider;
 
 /**
@@ -38,5 +37,5 @@
 	public void visit(Key k) {
 		name = k.name;
-		icon = new ImageIcon(Main.class.getResource("/images/data/key.png"));
+		icon = ImageProvider.get("data", "key");
 	}
 
@@ -53,5 +52,5 @@
 			
 		this.name = name;
-		icon = new ImageIcon("images/data/linesegment.png");
+		icon = ImageProvider.get("data", "linesegment");
 	}
 
@@ -67,5 +66,5 @@
 		
 		this.name = name;
-		icon = new ImageIcon("images/data/node.png");
+		icon = ImageProvider.get("data", "node");
 	}
 
@@ -87,5 +86,5 @@
 		
 		this.name = name;
-		icon = new ImageIcon("images/data/track.png");
+		icon = ImageProvider.get("data", "track");
 	}
 
Index: src/org/openstreetmap/josm/data/projection/UTM.java
===================================================================
--- src/org/openstreetmap/josm/data/projection/UTM.java	(revision 16)
+++ src/org/openstreetmap/josm/data/projection/UTM.java	(revision 17)
@@ -98,13 +98,13 @@
 	 * Combobox with all ellipsoids for the configuration panel
 	 */
-	private JComboBox ellipsoidCombo = new JComboBox(allEllipsoids);
+	private JComboBox ellipsoidCombo;
 	/**
 	 * Spinner with all possible zones for the configuration panel
 	 */
-	private JSpinner zoneSpinner = new JSpinner(new SpinnerNumberModel(1,1,60,1));
+	private JSpinner zoneSpinner;
 	/**
 	 * Hemisphere combo for the configuration panel
 	 */
-	private JComboBox hemisphereCombo = new JComboBox(Hemisphere.values());
+	private JComboBox hemisphereCombo;
 
 	
@@ -248,4 +248,6 @@
 		
 		// ellipsoid
+		if (ellipsoidCombo == null)
+			ellipsoidCombo = new JComboBox(allEllipsoids);
 		panel.add(new JLabel("Ellipsoid"), gbc);
 		panel.add(ellipsoidCombo, GBC.eol());
@@ -253,4 +255,6 @@
 		
 		// zone
+		if (zoneSpinner == null)
+			zoneSpinner = new JSpinner(new SpinnerNumberModel(1,1,60,1));
 		panel.add(new JLabel("Zone"), gbc);
 		panel.add(zoneSpinner, GBC.eol().insets(0,5,0,5));
@@ -259,4 +263,6 @@
 		
 		// hemisphere
+		if (hemisphereCombo == null)
+			hemisphereCombo = new JComboBox(Hemisphere.values());
 		panel.add(new JLabel("Hemisphere"), gbc);
 		panel.add(hemisphereCombo, GBC.eop());
@@ -268,5 +274,5 @@
 			public void actionPerformed(ActionEvent e) {
 				if (Main.main.getMapFrame() != null) {
-					DataSet ds = Main.main.getMapFrame().mapView.dataSet;
+					DataSet ds = Main.main.getMapFrame().mapView.getActiveDataSet();
 					ZoneData zd = autoDetect(ds);
 					if (zd.zone == 0)
@@ -291,8 +297,10 @@
 	@Override
 	public void commitConfigurationPanel() {
-		ellipsoid = (Ellipsoid)ellipsoidCombo.getSelectedItem();
-		zone = (Integer)zoneSpinner.getValue();
-		hemisphere = (Hemisphere)hemisphereCombo.getSelectedItem();
-		fireStateChanged();
+		if (ellipsoidCombo != null && zoneSpinner != null && hemisphereCombo != null) {
+			ellipsoid = (Ellipsoid)ellipsoidCombo.getSelectedItem();
+			zone = (Integer)zoneSpinner.getValue();
+			hemisphere = (Hemisphere)hemisphereCombo.getSelectedItem();
+			fireStateChanged();
+		}
 	}
 }
Index: src/org/openstreetmap/josm/gui/ImageProvider.java
===================================================================
--- src/org/openstreetmap/josm/gui/ImageProvider.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/ImageProvider.java	(revision 17)
@@ -0,0 +1,85 @@
+package org.openstreetmap.josm.gui;
+
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Transparency;
+import java.awt.image.BufferedImage;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+/**
+ * Helperclass to support the application with images.
+ * @author imi
+ */
+public class ImageProvider {
+
+	/**
+	 * Position of an overlay icon
+	 * @author imi
+	 */
+	public enum OverlayPosition {NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST};
+	
+	/**
+	 * The icon cache
+	 */
+	private static Map<URL, Icon> cache = new HashMap<URL, Icon>();
+	
+	/**
+	 * Return an image from the specified location.
+	 *
+	 * @param subdir	The position of the directory, e.g. "layer"
+	 * @param name		The icons name (without the ending of ".png")
+	 * @return	The requested ImageIcon.
+	 */
+	public static Icon get(String subdir, String name) {
+		if (subdir != "")
+			subdir += "/";
+		URL path = Main.class.getResource("/images/"+subdir+name+".png");
+		Icon icon = cache.get(path);
+		if (icon == null) {
+			icon = new ImageIcon(Main.class.getResource("/images/"+subdir+name+".png"));
+			cache.put(path, icon);
+		}
+		return icon;
+	}
+
+	/**
+	 * Shortcut for get("", name);
+	 */
+	public static Icon get(String name) {
+		return get("", name);
+	}
+
+	/**
+	 * Return an icon that represent the overlay of the two given icons. The
+	 * second icon is layed on the first relative to the given position.
+	 *
+	 * @param ground The ground icon (base)
+	 * @param overlay The icon to put on top of the ground (overlay)
+	 * @return The merged icon.
+	 */
+	public static Icon overlay(Icon ground, Icon overlay, OverlayPosition pos) {
+		GraphicsConfiguration conf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
+		int w = ground.getIconWidth();
+		int h = ground.getIconHeight();
+		int wo = overlay.getIconWidth();
+		int ho = overlay.getIconHeight();
+		BufferedImage img = conf.createCompatibleImage(w,h, Transparency.TRANSLUCENT);
+		Graphics g = img.createGraphics();
+		ground.paintIcon(null, g, 0, 0);
+		int x = 0, y = 0;
+		switch (pos) {
+		case NORTHWEST: x = 0;		y = 0;		break;
+		case NORTHEAST: x = w-wo;	y = 0;		break;
+		case SOUTHWEST: x = 0;		y = h-ho;	break;
+		case SOUTHEAST: x = w-wo;	y = h-ho;	break;
+		}
+		overlay.paintIcon(null, g, x, y);
+		return new ImageIcon(img);
+	}
+}
Index: src/org/openstreetmap/josm/gui/Main.java
===================================================================
--- src/org/openstreetmap/josm/gui/Main.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/Main.java	(revision 17)
@@ -5,5 +5,4 @@
 import java.awt.Container;
 
-import javax.swing.ImageIcon;
 import javax.swing.JFrame;
 import javax.swing.JMenu;
@@ -36,5 +35,5 @@
 	 * Global application preferences
 	 */
-	public static Preferences pref = new Preferences();
+	public final static Preferences pref = new Preferences();
 	
 	/**
@@ -141,11 +140,14 @@
 		//TODO: Check for changes and ask user
 		this.name = name;
+		if (this.mapFrame != null)
+			this.mapFrame.setVisible(false);
 		this.mapFrame = mapFrame;
 		panel.setVisible(false);
 		panel.removeAll();
-		panel.add(mapFrame, BorderLayout.CENTER);
-		panel.add(mapFrame.toolBarActions, BorderLayout.WEST);
-		panel.add(mapFrame.statusLine, BorderLayout.SOUTH);
-		panel.setVisible(true);
+		if (mapFrame != null) {
+			mapFrame.fillPanel(panel);
+			panel.setVisible(true);
+			mapFrame.setVisible(true);
+		}
 	}
 	/**
@@ -167,7 +169,7 @@
 	 */
 	private static void setupUiDefaults() {
-		UIManager.put("OptionPane.okIcon", new ImageIcon(Main.class.getResource("/images/ok.png")));
+		UIManager.put("OptionPane.okIcon", ImageProvider.get("ok"));
 		UIManager.put("OptionPane.yesIcon", UIManager.get("OptionPane.okIcon"));
-		UIManager.put("OptionPane.cancelIcon", new ImageIcon(Main.class.getResource("/images/cancel.png")));
+		UIManager.put("OptionPane.cancelIcon", ImageProvider.get("cancel"));
 		UIManager.put("OptionPane.noIcon", UIManager.get("OptionPane.cancelIcon"));
 	}
Index: src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapFrame.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/MapFrame.java	(revision 17)
@@ -3,4 +3,5 @@
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Container;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
@@ -14,9 +15,9 @@
 import javax.swing.JToolBar;
 
+import org.openstreetmap.josm.actions.AutoScaleAction;
 import org.openstreetmap.josm.actions.mapmode.AddLineSegmentAction;
 import org.openstreetmap.josm.actions.mapmode.AddNodeAction;
 import org.openstreetmap.josm.actions.mapmode.AddTrackAction;
 import org.openstreetmap.josm.actions.mapmode.CombineAction;
-import org.openstreetmap.josm.actions.mapmode.DebugAction;
 import org.openstreetmap.josm.actions.mapmode.DeleteAction;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
@@ -24,7 +25,8 @@
 import org.openstreetmap.josm.actions.mapmode.SelectionAction;
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
-import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.dialogs.LayerList;
 import org.openstreetmap.josm.gui.dialogs.PropertiesDialog;
 import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
+import org.openstreetmap.josm.gui.layer.Layer;
 
 /**
@@ -54,12 +56,15 @@
 
 	/**
-	 * Construct a map with a given DataSet. The set cannot be replaced after construction
-	 * (but of course, the data can be altered using the map's editing features). 
+	 * Construct a map with a given DataSet. The set cannot be replaced after 
+	 * construction (but of course, the data can be altered using the map's
+	 * editing features).
+	 * 
+	 * @param layer The first layer in the mapView. 
 	 */
-	public MapFrame(DataSet dataSet) {
+	public MapFrame(Layer layer) {
 		setSize(400,400);
 		setLayout(new BorderLayout());
 
-		add(mapView = new MapView(dataSet), BorderLayout.CENTER);
+		add(mapView = new MapView(layer), BorderLayout.CENTER);
 
 		// toolbar
@@ -73,5 +78,4 @@
 		toolBarActions.add(new IconToggleButton(this, new CombineAction(this)));
 		toolBarActions.add(new IconToggleButton(this, new DeleteAction(this)));
-		toolBarActions.add(new IconToggleButton(this, new DebugAction(this)));
 
 		// all map modes in one button group
@@ -84,5 +88,5 @@
 		// autoScale
 		toolBarActions.addSeparator();
-		final JToggleButton autoScaleButton = new IconToggleButton(this, mapView.new AutoScaleAction());
+		final JToggleButton autoScaleButton = new IconToggleButton(this, new AutoScaleAction(this));
 		toolBarActions.add(autoScaleButton);
 		autoScaleButton.setText(null);
@@ -95,9 +99,12 @@
 		});
 
+		// layer list
+		toolBarActions.add(new IconToggleButton(this, new LayerList(this)));
+		
 		// properties
 		toolBarActions.add(new IconToggleButton(this, new PropertiesDialog(this)));
 
 		// selection dialog
-		SelectionListDialog selectionList = new SelectionListDialog(dataSet);
+		SelectionListDialog selectionList = new SelectionListDialog(this);
 		final IconToggleButton buttonSelection = new IconToggleButton(this, selectionList);
 		selectionList.addWindowListener(new WindowAdapter(){
@@ -110,6 +117,20 @@
 
 		// status line below the map
-		statusLine = new MapStatus(mapView);
+		statusLine = new MapStatus(this);
 	}
+
+	
+	/**
+	 * Fires an property changed event "visible".
+	 */
+	@Override
+	public void setVisible(boolean aFlag) {
+		boolean old = isVisible();
+		super.setVisible(aFlag);
+		if (old != aFlag)
+			firePropertyChange("visible", old, aFlag);
+	}
+
+
 
 	/**
@@ -124,3 +145,15 @@
 		mapMode.registerListener();
 	}
+
+	/**
+	 * Fill the given panel by adding all necessary components to the different
+	 * locations.
+	 * 
+	 * @param panel The container to fill. Must have an BorderLayout.
+	 */
+	public void fillPanel(Container panel) {
+		panel.add(this, BorderLayout.CENTER);
+		panel.add(toolBarActions, BorderLayout.WEST);
+		panel.add(statusLine, BorderLayout.SOUTH);
+	}
 }
Index: src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapStatus.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/MapStatus.java	(revision 17)
@@ -8,4 +8,6 @@
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.Map.Entry;
 
@@ -50,8 +52,4 @@
 	 */
 	private JTextField nameText = new JTextField(30);
-	/**
-	 * The background thread thats collecting the data.
-	 */
-	private Runnable collector;
 
 	/**
@@ -78,4 +76,8 @@
 		 */
 		private Popup popup;
+		/**
+		 * Signals the collector to shut down on next event.
+		 */
+		boolean exitCollector = false;
 
 		/**
@@ -90,4 +92,6 @@
 					ms.mousePos = mouseState.mousePos;
 				}
+				if (exitCollector)
+					return;
 				if ((ms.modifiers & MouseEvent.CTRL_DOWN_MASK) != 0 || ms.mousePos == null)
 					continue; // freeze display when holding down ctrl
@@ -119,4 +123,5 @@
 					}
 					JLabel l = new JLabel(text.toString(), visitor.icon, JLabel.HORIZONTAL);
+					l.setVerticalTextPosition(JLabel.TOP);
 					
 					Point p = mv.getLocationOnScreen();
@@ -148,6 +153,6 @@
 	 * @param mv The MapView the status line is part of.
 	 */
-	public MapStatus(final MapView mv) {
-		this.mv = mv;
+	public MapStatus(final MapFrame mapFrame) {
+		this.mv = mapFrame.mapView;
 		
 		// Listen for mouse movements and set the position text field
@@ -165,4 +170,17 @@
 		});
 		
+		positionText.setEditable(false);
+		nameText.setEditable(false);
+		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+		setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		add(new JLabel("Lat/Lon "));
+		add(positionText);
+		add(new JLabel(" Object "));
+		add(nameText);
+
+		// The background thread
+		final Collector collector = new Collector();
+		new Thread(collector).start();
+
 		// Listen to keyboard/mouse events for pressing/releasing alt key and
 		// inform the collector.
@@ -177,17 +195,16 @@
 			}
 		}, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
-
-		positionText.setEditable(false);
-		nameText.setEditable(false);
-		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
-		setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-		add(new JLabel("Lat/Lon "));
-		add(positionText);
-		add(new JLabel(" Object "));
-		add(nameText);
-
-		// The background thread
-		collector = new Collector();
-		new Thread(collector).start();
+		
+		// listen for shutdowns to cancel the background thread
+		mapFrame.addPropertyChangeListener("visible", new PropertyChangeListener(){
+			public void propertyChange(PropertyChangeEvent evt) {
+				if (evt.getNewValue() == Boolean.FALSE) {
+					collector.exitCollector = true;
+					synchronized (collector) {
+						collector.notify();
+					}
+				}
+			}
+		});
 	}
 }
Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/MapView.java	(revision 17)
@@ -1,13 +1,16 @@
 package org.openstreetmap.josm.gui;
 
+import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Point;
-import java.awt.event.ActionEvent;
+import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
-import java.awt.event.KeyEvent;
-
-import javax.swing.AbstractAction;
-import javax.swing.ImageIcon;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+
 import javax.swing.JComponent;
 import javax.swing.event.ChangeEvent;
@@ -16,5 +19,4 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.GeoPoint;
-import org.openstreetmap.josm.data.Preferences.ProjectionChangeListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.LineSegment;
@@ -23,6 +25,5 @@
 import org.openstreetmap.josm.data.osm.Track;
 import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.gui.engine.Engine;
-import org.openstreetmap.josm.gui.engine.SimpleEngine;
+import org.openstreetmap.josm.gui.layer.Layer;
 
 /**
@@ -36,21 +37,19 @@
  * what projection the map is viewed etc..
  *
+ * MapView is able to administrate several layers, but there must be always at
+ * least one layer with a dataset in it (Layer.getDataSet returning non-null).
+ *
  * @author imi
  */
-public class MapView extends JComponent implements ComponentListener, ChangeListener, ProjectionChangeListener {
-
-	/**
-	 * Toggles the autoScale feature of the mapView
+public class MapView extends JComponent implements ChangeListener, PropertyChangeListener {
+
+	/**
+	 * Interface to notify listeners of the change of the active layer.
 	 * @author imi
 	 */
-	public class AutoScaleAction extends AbstractAction {
-		public AutoScaleAction() {
-			super("Auto Scale", new ImageIcon(Main.class.getResource("/images/autoscale.png")));
-			putValue(MNEMONIC_KEY, KeyEvent.VK_A);
-		}
-		public void actionPerformed(ActionEvent e) {
-			autoScale = !autoScale;
-			recalculateCenterScale();
-		}
+	public interface LayerChangeListener {
+		void activeLayerChange(Layer oldLayer, Layer newLayer);
+		void layerAdded(Layer newLayer);
+		void layerRemoved(Layer oldLayer);
 	}
 
@@ -58,5 +57,5 @@
 	 * Whether to adjust the scale property on every resize.
 	 */
-	private boolean autoScale = true;
+	boolean autoScale = true;
 
 	/**
@@ -70,19 +69,30 @@
 
 	/**
-	 * The underlying DataSet.
-	 */
-	public final DataSet dataSet;
-
-	/**
-	 * The drawing engine.
-	 */
-	private Engine engine;
+	 * A list of all layers currently loaded.
+	 */
+	private ArrayList<Layer> layers = new ArrayList<Layer>();
+	/**
+	 * The layer from the layers list that is currently active.
+	 */
+	private Layer activeLayer;
+	/**
+	 * The listener of the active layer changes.
+	 */
+	private Collection<LayerChangeListener> listeners = new LinkedList<LayerChangeListener>();
 	
 	/**
 	 * Construct a MapView.
-	 */
-	public MapView(DataSet dataSet) {
-		this.dataSet = dataSet;
-		addComponentListener(this);
+	 * @param layer The first layer in the view.
+	 */
+	public MapView(Layer layer) {
+		if (layer.getDataSet() == null)
+			throw new IllegalArgumentException("Initial layer must have a dataset.");
+
+		addComponentListener(new ComponentAdapter(){
+			@Override
+			public void componentResized(ComponentEvent e) {
+				recalculateCenterScale();
+			}
+		});
 
 		// initialize the movement listener
@@ -90,9 +100,62 @@
 
 		// initialize the projection
-		projectionChanged(null, Main.pref.getProjection());
-		Main.pref.addProjectionChangeListener(this);
-		
-		// initialize the drawing engine
-		engine = new SimpleEngine(this);
+		addLayer(layer);
+		Main.pref.addPropertyChangeListener(this);
+
+		// init screen
+		recalculateCenterScale();
+	}
+
+	/**
+	 * Add a layer to the current MapView. The layer will be added at topmost
+	 * position.
+	 */
+	public void addLayer(Layer layer) {
+		layers.add(0,layer);
+
+		DataSet ds = layer.getDataSet();
+
+		if (ds != null) {
+			// initialize the projection if it was the first layer
+			if (layers.size() == 1)
+				Main.pref.getProjection().init(ds);
+			
+			// initialize the dataset in the new layer
+			for (Node n : ds.nodes)
+				Main.pref.getProjection().latlon2xy(n.coor);
+		}
+
+		for (LayerChangeListener l : listeners)
+			l.layerAdded(layer);
+
+		setActiveLayer(layer);
+	}
+	
+	/**
+	 * Remove the layer from the mapview. If the layer was in the list before,
+	 * an LayerChange event is fired.
+	 */
+	public void removeLayer(Layer layer) {
+		if (layers.remove(layer))
+			for (LayerChangeListener l : listeners)
+				l.layerRemoved(layer);
+	}
+
+	/**
+	 * Moves the layer to the given new position. No event is fired.
+	 * @param layer		The layer to move
+	 * @param pos		The new position of the layer
+	 */
+	public void moveLayer(Layer layer, int pos) {
+		int curLayerPos = layers.indexOf(layer);
+		if (curLayerPos == -1)
+			throw new IllegalArgumentException("layer not in list.");
+		if (pos == curLayerPos)
+			return; // already in place.
+		layers.remove(curLayerPos);
+		if (pos >= layers.size())
+			layers.add(layer);
+		else
+			layers.add(pos, layer);
 	}
 
@@ -168,7 +231,10 @@
 		double minDistanceSq = Double.MAX_VALUE;
 		OsmPrimitive minPrimitive = null;
+
+		// calculate the object based on the current active dataset.
+		DataSet ds = getActiveDataSet();
 		
 		// nodes
-		for (Node n : dataSet.nodes) {
+		for (Node n : ds.nodes) {
 			Point sp = getScreenPoint(n.coor);
 			double dist = p.distanceSq(sp);
@@ -182,5 +248,5 @@
 		
 		// pending line segments
-		for (LineSegment ls : dataSet.pendingLineSegments()) {
+		for (LineSegment ls : ds.pendingLineSegments()) {
 			Point A = getScreenPoint(ls.getStart().coor);
 			Point B = getScreenPoint(ls.getEnd().coor);
@@ -197,5 +263,5 @@
 		// tracks & line segments
 		minDistanceSq = Double.MAX_VALUE;
-		for (Track t : dataSet.tracks()) {
+		for (Track t : ds.tracks()) {
 			for (LineSegment ls : t.segments()) {
 				Point A = getScreenPoint(ls.getStart().coor);
@@ -243,5 +309,5 @@
 			firePropertyChange("scale", oldScale, scale);
 	}
-	
+
 	/**
 	 * Draw the component.
@@ -249,13 +315,12 @@
 	@Override
 	public void paint(Graphics g) {
-		engine.init(g);
-		engine.drawBackground(getPoint(0,0,true), getPoint(getWidth(), getHeight(), true));
-
-		for (Track t : dataSet.tracks())
-			engine.drawTrack(t);
-		for (LineSegment ls : dataSet.pendingLineSegments())
-			engine.drawPendingLineSegment(ls);
-		for (Node n : dataSet.nodes)
-			engine.drawNode(n);
+		g.setColor(Color.BLACK);
+		g.fillRect(0, 0, getWidth(), getHeight());
+
+		for (int i = layers.size()-1; i >= 0; --i) {
+			Layer l = layers.get(i);
+			if (l.isVisible())
+				l.paint(g, this);
+		}
 	}
 
@@ -265,6 +330,12 @@
 	 */
 	public void stateChanged(ChangeEvent e) {
-		for (Node n : dataSet.nodes)
-			Main.pref.getProjection().latlon2xy(n.coor);
+		// reset all datasets.
+		Projection p = Main.pref.getProjection();
+		for (Layer l : layers) {
+			DataSet ds = l.getDataSet();
+			if (ds != null)
+				for (Node n : ds.nodes)
+					p.latlon2xy(n.coor);
+		}
 		recalculateCenterScale();
 	}
@@ -292,4 +363,5 @@
 			this.autoScale = autoScale;
 			firePropertyChange("autoScale", !autoScale, autoScale);
+			recalculateCenterScale();
 		}
 	}
@@ -303,4 +375,20 @@
 
 	
+	/**
+	 * Return the dataSet for the current selected layer. If the active layer
+	 * does not have a dataset, return the DataSet from the next layer a.s.o.
+	 *  
+	 * @return The DataSet of the current active layer.
+	 */
+	public DataSet getActiveDataSet() {
+		if (activeLayer.getDataSet() != null)
+			return activeLayer.getDataSet();
+		for (Layer l : layers) {
+			DataSet ds = l.getDataSet();
+			if (ds != null)
+				return ds;
+		}
+		throw new IllegalStateException("No dataset found.");
+	}
 
 	/**
@@ -310,14 +398,15 @@
 	 * @param newProjection	The new projection. Register as state change listener.
 	 */
-	public void projectionChanged(Projection oldProjection, Projection newProjection) {
-		if (oldProjection != null)
-			oldProjection.removeChangeListener(this);
-		if (newProjection != null) {
-			newProjection.addChangeListener(this);
-			newProjection.init(dataSet);
-			for (Node n : dataSet.nodes)
-				newProjection.latlon2xy(n.coor);
-		}
-		recalculateCenterScale();
+	public void propertyChange(PropertyChangeEvent evt) {
+		if (!evt.getPropertyName().equals("projection"))
+			return;
+		if (evt.getOldValue() != null)
+			((Projection)evt.getOldValue()).removeChangeListener(this);
+		if (evt.getNewValue() != null) {
+			Projection p = (Projection)evt.getNewValue();
+			p.addChangeListener(this);
+
+			stateChanged(new ChangeEvent(this));
+		}
 	}
 	
@@ -326,5 +415,5 @@
 	 * scale, if in autoScale mode.
 	 */
-	private void recalculateCenterScale() {
+	void recalculateCenterScale() {
 		if (autoScale) {
 			// -20 to leave some border
@@ -335,5 +424,6 @@
 			if (h < 20)
 				h = 20;
-			Bounds bounds = dataSet.getBoundsXY();
+			
+			Bounds bounds = getActiveDataSet().getBoundsXY();
 			
 			boolean oldAutoScale = autoScale;
@@ -364,21 +454,49 @@
 
 	/**
-	 * Call to recalculateCenterScale.
-	 */
-	public void componentResized(ComponentEvent e) {
-		recalculateCenterScale();
-	}
-
-	/**
-	 * Does nothing. Just to satisfy ComponentListener.
-	 */
-	public void componentMoved(ComponentEvent e) {}
-	/**
-	 * Does nothing. Just to satisfy ComponentListener.
-	 */
-	public void componentShown(ComponentEvent e) {}
-	/**
-	 * Does nothing. Just to satisfy ComponentListener.
-	 */
-	public void componentHidden(ComponentEvent e) {}
+	 * Add a listener for changes of active layer.
+	 * @param listener The listener that get added.
+	 */
+	public void addLayerChangeListener(LayerChangeListener listener) {
+		if (listener != null)
+			listeners.add(listener);
+	}
+
+	/**
+	 * Remove the listener.
+	 * @param listener The listener that get removed from the list.
+	 */
+	public void removeLayerChangeListener(LayerChangeListener listener) {
+		listeners.remove(listener);
+	}
+
+	/**
+	 * @return An unmodificable list of all layers
+	 */
+	public Collection<Layer> getAllLayers() {
+		return Collections.unmodifiableCollection(layers);
+	}
+
+	/**
+	 * Set the active selection to the given value and raise an layerchange event.
+	 */
+	public void setActiveLayer(Layer layer) {
+		if (!layers.contains(layer))
+			throw new IllegalArgumentException("layer must be in layerlist");
+		Layer old = activeLayer;
+		activeLayer = layer;
+		if (old != layer) {
+			if (old != null && old.getDataSet() != null)
+				old.getDataSet().clearSelection();
+			for (LayerChangeListener l : listeners)
+				l.activeLayerChange(old, layer);
+			recalculateCenterScale();
+		}
+	}
+
+	/**
+	 * @return The current active layer
+	 */
+	public Layer getActiveLayer() {
+		return activeLayer;
+	}
 }
Index: src/org/openstreetmap/josm/gui/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 17)
@@ -7,5 +7,4 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.io.File;
 
 import javax.swing.AbstractAction;
@@ -13,5 +12,4 @@
 import javax.swing.Box;
 import javax.swing.DefaultListCellRenderer;
-import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
@@ -54,4 +52,5 @@
 			Main.pref.setProjection(projection);
 			Main.pref.mergeNodes = mergeNodes.isSelected();
+			Main.pref.setDrawRawGpsLines(drawRawGpsLines.isSelected());
 			try {
 				Main.pref.save();
@@ -96,10 +95,14 @@
 	 */
 	private JTabbedPane tabPane = new JTabbedPane(JTabbedPane.LEFT);
+
 	/**
 	 * The checkbox stating whether nodes should be merged together.
 	 */
+	private JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");
+	/**
+	 * The checkbox stating whether nodes should be merged together.
+	 */
 	private JCheckBox mergeNodes = new JCheckBox("Merge nodes with equal latitude/longitude.");
 
-	
 	/**
 	 * Create a preference setting dialog from an preferences-file. If the file does not
@@ -110,14 +113,4 @@
 	public PreferenceDialog() {
 		super(Main.main, "Preferences");
-
-		Preferences pref = new Preferences();
-		try {
-			if (new File(Preferences.getPreferencesFile()).exists())
-				pref.load();
-		} catch (PreferencesException e) {
-			JOptionPane.showMessageDialog(Main.main, "Preferences settings could not be parsed:\n"+e.getMessage());
-			e.printStackTrace();
-			return;
-		}
 
 		// look and feel combo box
@@ -128,5 +121,5 @@
 				return oldRenderer.getListCellRendererComponent(list, ((LookAndFeelInfo)value).getName(), index, isSelected, cellHasFocus);
 			}});
-		lafCombo.setSelectedItem(pref.laf);
+		lafCombo.setSelectedItem(Main.pref.laf);
 		lafCombo.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -136,5 +129,5 @@
 		// projection combo box
 		for (int i = 0; i < projectionCombo.getItemCount(); ++i) {
-			if (projectionCombo.getItemAt(i).getClass().equals(pref.getProjection().getClass())) {
+			if (projectionCombo.getItemAt(i).getClass().equals(Main.pref.getProjection().getClass())) {
 				projectionCombo.setSelectedIndex(i);
 				break;
@@ -162,4 +155,9 @@
 		});
 		
+		// tooltips
+		drawRawGpsLines.setToolTipText("If your gps device draw to few lines, select this to draw lines along your track.");
+		drawRawGpsLines.setSelected(Main.pref.isDrawRawGpsLines());
+		mergeNodes.setToolTipText("When importing GPX data, all nodes with exact the same lat/lon are merged.");
+		mergeNodes.setSelected(Main.pref.mergeNodes);
 		
 		// Display tab
@@ -168,4 +166,5 @@
 		display.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
 		display.add(lafCombo, GBC.eol().fill(GBC.HORIZONTAL));
+		display.add(drawRawGpsLines, GBC.eol().insets(20,0,0,0));
 		display.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
 
@@ -180,6 +179,5 @@
 		
 		map.add(new JLabel("GPX import / export"), GBC.eol());
-		mergeNodes.setSelected(pref.mergeNodes);
-		map.add(mergeNodes, GBC.eol());
+		map.add(mergeNodes, GBC.eol().insets(20,0,0,0));
 		map.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
 
@@ -222,5 +220,5 @@
 		p.add(descLabel, GBC.eol().insets(5,0,5,20).fill(GBC.HORIZONTAL));
 
-		tabPane.addTab(null, new ImageIcon("images/preferences/"+icon+".png"), p);
+		tabPane.addTab(null, ImageProvider.get("preferences", icon), p);
 		return p;
 	}
Index: src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 17)
@@ -15,4 +15,5 @@
 import java.util.LinkedList;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.LineSegment;
 import org.openstreetmap.josm.data.osm.Node;
@@ -271,5 +272,6 @@
 		} else {
 			// nodes
-			for (Node n : mv.dataSet.nodes) {
+			DataSet ds = mv.getActiveDataSet();
+			for (Node n : ds.nodes) {
 				if (r.contains(mv.getScreenPoint(n.coor)))
 					selection.add(n);
@@ -277,10 +279,10 @@
 			
 			// pending line segments
-			for (LineSegment ls : mv.dataSet.pendingLineSegments())
+			for (LineSegment ls : ds.pendingLineSegments())
 				if (rectangleContainLineSegment(r, alt, ls))
 					selection.add(ls);
 
 			// tracks
-			for (Track t : mv.dataSet.tracks()) {
+			for (Track t : ds.tracks()) {
 				boolean wholeTrackSelected = !t.segments().isEmpty();
 				for (LineSegment ls : t.segments())
Index: src/org/openstreetmap/josm/gui/dialogs/LayerList.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 17)
@@ -0,0 +1,226 @@
+package org.openstreetmap.josm.gui.dialogs;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.util.Collection;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.UIManager;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.ImageProvider;
+import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.Layer;
+
+/**
+ * A component that manages the list of all layers and react to selection changes
+ * by setting the active layer in the mapview.
+ *
+ * @author imi
+ */
+public class LayerList extends ToggleDialog implements LayerChangeListener {
+
+	/**
+	 * The data model for the list component.
+	 */
+	private DefaultListModel model = new DefaultListModel();
+	/**
+	 * The list component holding all layers.
+	 */
+	private JList layers = new JList(model);
+	/**
+	 * The invisible icon blended over invisible layers.
+	 */
+	private static final Icon invisible = ImageProvider.get("layer", "invisible");
+
+	/**
+	 * The merge action. This is only called, if the current selection and its
+	 * item below are editable datasets and the merge button is clicked. 
+	 */
+	private final JButton mergeButton = new JButton(ImageProvider.get("dialogs", "mergedown"));
+	/**
+	 * Button for moving layer up.
+	 */
+	private JButton upButton = new JButton(ImageProvider.get("dialogs", "up"));
+	/**
+	 * Button for moving layer down.
+	 */
+	private JButton downButton = new JButton(ImageProvider.get("dialogs", "down"));
+	/**
+	 * Button for delete layer.
+	 */
+	private JButton deleteButton = new JButton(ImageProvider.get("dialogs", "delete"));
+	
+	/**
+	 * Create an layerlist and attach it to the given mapView.
+	 */
+	public LayerList(MapFrame mapFrame) {
+		super(mapFrame, "Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers.");
+		setSize(250,256);
+		setMinimumSize(new Dimension(70,70));
+		add(new JScrollPane(layers), BorderLayout.CENTER);
+		layers.setBackground(UIManager.getColor("Button.background"));
+		layers.setCellRenderer(new DefaultListCellRenderer(){
+			@Override
+			public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+				Layer layer = (Layer)value;
+				JLabel label = (JLabel)super.getListCellRendererComponent(list, 
+						layer.getName(), index, isSelected, cellHasFocus);
+				Icon icon = layer.getIcon();
+				if (!layer.isVisible())
+					icon = ImageProvider.overlay(icon, invisible, ImageProvider.OverlayPosition.SOUTHEAST);
+				label.setIcon(icon);
+				return label;
+			}
+		});
+
+		final MapView mapView = mapFrame.mapView;
+		
+		Collection<Layer> data = mapView.getAllLayers();
+		for (Layer l : data)
+			model.addElement(l);
+
+		layers.setSelectedValue(mapView.getActiveLayer(), true);
+		layers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		layers.addListSelectionListener(new ListSelectionListener(){
+			public void valueChanged(ListSelectionEvent e) {
+				if (layers.getSelectedIndex() == -1)
+					layers.setSelectedIndex(e.getFirstIndex());
+				mapView.setActiveLayer((Layer)layers.getSelectedValue());
+			}
+		});
+		mapView.addLayerChangeListener(this);
+		
+		// Buttons
+		JPanel buttonPanel = new JPanel(new GridLayout(1, 5));
+
+		ActionListener upDown = new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				Layer l = (Layer)layers.getSelectedValue();
+				int sel = layers.getSelectedIndex();
+				int selDest = e.getActionCommand().equals("up") ? sel-1 : sel+1;
+				mapView.moveLayer(l, selDest);
+				model.set(sel, model.get(selDest));
+				model.set(selDest, l);
+				layers.setSelectedIndex(selDest);
+				updateButtonEnabled();
+				mapView.repaint();
+			}
+		};
+
+		upButton.setToolTipText("Move the selected layer one row up.");
+		upButton.addActionListener(upDown);
+		upButton.setActionCommand("up");
+		buttonPanel.add(upButton);
+		
+		downButton.setToolTipText("Move the selected layer one row down.");
+		downButton.addActionListener(upDown);
+		downButton.setActionCommand("down");
+		buttonPanel.add(downButton);
+		
+		JButton visible = new JButton(ImageProvider.get("dialogs", "showhide"));
+		visible.setToolTipText("Toggle visible state of the selected layer.");
+		visible.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				Layer l = (Layer)layers.getSelectedValue();
+				l.setVisible(!l.isVisible());
+				mapView.repaint();
+				layers.repaint();
+			}
+		});
+		buttonPanel.add(visible);
+
+		deleteButton.setToolTipText("Delete the selected layer.");
+		deleteButton.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				if (model.size() == 1) {
+					Main.main.setMapFrame(null, null);
+				} else {
+					int sel = layers.getSelectedIndex();
+					mapView.removeLayer((Layer)layers.getSelectedValue());
+					if (sel >= model.getSize())
+						sel = model.getSize()-1;
+					layers.setSelectedIndex(sel);
+				}
+			}
+		});
+		buttonPanel.add(deleteButton);
+
+		mergeButton.setToolTipText("Merge the selected layer into the layer directly below.");
+		mergeButton.addActionListener(new ActionListener(){
+				public void actionPerformed(ActionEvent e) {
+					Layer lFrom = (Layer)layers.getSelectedValue();
+					DataSet dsFrom = lFrom.getDataSet();
+					Layer lTo = (Layer)model.get(layers.getSelectedIndex()+1);
+					DataSet dsTo = lTo.getDataSet();
+					dsTo.mergeFrom(dsFrom, Main.pref.mergeNodes);
+					layers.setSelectedValue(lTo, true);
+					mapView.removeLayer(lFrom);
+				}
+			});		
+		buttonPanel.add(mergeButton);
+
+		add(buttonPanel, BorderLayout.SOUTH);
+		
+		updateButtonEnabled();
+	}
+
+	/**
+	 * Updates the state of the Buttons.
+	 */
+	private void updateButtonEnabled() {
+		int sel = layers.getSelectedIndex();
+		Layer l = (Layer)layers.getSelectedValue();
+		boolean enable = model.getSize() > 1;
+		enable = enable && sel < model.getSize()-1;
+		enable = enable && l.getDataSet() != null;
+		enable = enable && ((Layer)model.get(sel+1)).getDataSet() != null;
+		enable = enable && l.isEditable() == ((Layer)model.get(sel+1)).isEditable();
+		mergeButton.setEnabled(enable);
+		upButton.setEnabled(sel > 0);
+		downButton.setEnabled(sel < model.getSize()-1);
+		deleteButton.setEnabled(!model.isEmpty());
+	}
+
+	/**
+	 * Add the new layer to the list.
+	 */
+	public void layerAdded(Layer newLayer) {
+		model.add(0, newLayer);
+		updateButtonEnabled();
+	}
+
+	public void layerRemoved(Layer oldLayer) {
+		model.removeElement(oldLayer);
+		if (layers.getSelectedIndex() == -1)
+			layers.setSelectedIndex(0);
+		updateButtonEnabled();
+	}
+
+	/**
+	 * If the newLayer is not the actual selection, select it.
+	 */
+	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+		if (newLayer != layers.getSelectedValue())
+			layers.setSelectedValue(newLayer, true);
+		updateButtonEnabled();
+	}
+}
Index: src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 17)
@@ -21,8 +21,7 @@
 	/**
 	 * Create a new PropertiesDialog
-	 * @param frame The mapFrame, this dialog is attached to.
 	 */
-	public PropertiesDialog(final MapFrame frame) {
-		super("Properties of "+Main.main.getNameOfLoadedMapFrame(), "Properties Dialog", "properties", KeyEvent.VK_P, "Property page for this map.");
+	public PropertiesDialog(MapFrame mapFrame) {
+		super(mapFrame, "Properties of "+Main.main.getNameOfLoadedMapFrame(), "Properties Dialog", "properties", KeyEvent.VK_P, "Property page for this map.");
 		putValue(MNEMONIC_KEY, KeyEvent.VK_P);
 
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 17)
@@ -10,5 +10,4 @@
 import javax.swing.DefaultListCellRenderer;
 import javax.swing.DefaultListModel;
-import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JLabel;
@@ -21,5 +20,10 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor;
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.Layer;
 
 /**
@@ -30,5 +34,5 @@
  * @author imi
  */
-public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
+public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener, LayerChangeListener {
 
 	/**
@@ -43,13 +47,13 @@
 	 * The dataset, all selections are part of.
 	 */
-	private final DataSet dataSet;
+	private final MapView mapView;
 	
 	/**
 	 * Create a SelectionList dialog.
-	 * @param dataSet The dataset this dialog operates on.
+	 * @param mapView The mapView to get the dataset from.
 	 */
-	public SelectionListDialog(DataSet dataSet) {
-		super("Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window.");
-		this.dataSet = dataSet;
+	public SelectionListDialog(MapFrame mapFrame) {
+		super(mapFrame, "Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window.");
+		this.mapView = mapFrame.mapView;
 		setLayout(new BorderLayout());
 		setSize(300,400);
@@ -71,5 +75,6 @@
 		getContentPane().add(new JScrollPane(displaylist), BorderLayout.CENTER);
 
-		JButton button = new JButton("Select", new ImageIcon(Main.class.getResource("/images/mapmode/selection.png")));
+		JButton button = new JButton("Select", ImageProvider.get("mapmode", "selection"));
+		button.setToolTipText("Set the selected elements on the map to the selected items in the list above.");
 		button.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -79,5 +84,5 @@
 		getContentPane().add(button, BorderLayout.SOUTH);
 
-		selectionChanged(dataSet.getSelected());
+		selectionChanged(mapView.getActiveDataSet().getSelected());
 	}
 
@@ -85,8 +90,11 @@
 	public void setVisible(boolean b) {
 		if (b) {
-			dataSet.addSelectionChangedListener(this);
-			selectionChanged(dataSet.getSelected());
-		} else
-			dataSet.removeSelectionChangedListener(this);
+			mapView.addLayerChangeListener(this);
+			mapView.getActiveDataSet().addSelectionChangedListener(this);
+			selectionChanged(mapView.getActiveDataSet().getSelected());
+		} else {
+			mapView.removeLayerChangeListener(this);
+			mapView.getActiveDataSet().removeSelectionChangedListener(this);
+		}
 		super.setVisible(b);
 	}
@@ -110,9 +118,28 @@
 	 */
 	public void updateMap() {
-		dataSet.clearSelection();
+		DataSet ds = mapView.getActiveDataSet();
+		ds.clearSelection();
 		for (int i = 0; i < list.getSize(); ++i)
 			if (displaylist.isSelectedIndex(i))
-				((OsmPrimitive)list.get(i)).setSelected(true, dataSet);
+				((OsmPrimitive)list.get(i)).setSelected(true, ds);
 		Main.main.getMapFrame().repaint();
 	}
+
+	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+		DataSet ds = oldLayer.getDataSet();
+		if (ds != null)
+			ds.removeSelectionChangedListener(this);
+		ds = newLayer.getDataSet();
+		if (ds != null)
+			ds.addSelectionChangedListener(this);
+	}
+
+	/**
+	 * Does nothing. Only to satisfy LayerChangeListener
+	 */
+	public void layerAdded(Layer newLayer) {}
+	/**
+	 * Does nothing. Only to satisfy LayerChangeListener
+	 */
+	public void layerRemoved(Layer oldLayer) {}
 }
Index: src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 17)
@@ -2,5 +2,6 @@
 
 import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.HashMap;
 import java.util.Map;
@@ -8,9 +9,11 @@
 import javax.swing.AbstractButton;
 import javax.swing.Action;
-import javax.swing.ImageIcon;
+import javax.swing.JComponent;
 import javax.swing.JDialog;
 import javax.swing.KeyStroke;
 
+import org.openstreetmap.josm.gui.ImageProvider;
 import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.MapFrame;
 
 /**
@@ -26,11 +29,20 @@
 	 * @param title The title of the dialog.
 	 */
-	public ToggleDialog(String title, String name, String iconName, int mnemonic, String tooltip) {
+	public ToggleDialog(MapFrame mapFrame, String title, String name, String iconName, int mnemonic, String tooltip) {
 		super(Main.main, title, false);
-		putValue(SMALL_ICON, new ImageIcon(Main.class.getResource("/images/dialogs/"+iconName+".png")));
+		putValue(SMALL_ICON, ImageProvider.get("dialogs", iconName));
 		putValue(NAME, name);
 		putValue(MNEMONIC_KEY, mnemonic);
-		putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E,0));
-		putValue(LONG_DESCRIPTION, "Open a selection list window.");
+		KeyStroke ks = KeyStroke.getKeyStroke(mnemonic,0);
+		putValue(ACCELERATOR_KEY, ks);
+		mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this);
+		mapFrame.getActionMap().put(this, this);
+		putValue(LONG_DESCRIPTION, tooltip);
+		mapFrame.addPropertyChangeListener("visible", new PropertyChangeListener(){
+			public void propertyChange(PropertyChangeEvent evt) {
+				if (evt.getNewValue() == Boolean.FALSE)
+					setVisible(false);
+			}
+		});
 	}
 
Index: src/org/openstreetmap/josm/gui/engine/Engine.java
===================================================================
--- src/org/openstreetmap/josm/gui/engine/Engine.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/engine/Engine.java	(revision 17)
@@ -2,12 +2,8 @@
 
 import java.awt.Graphics;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 
-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.Track;
-import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.gui.MapView;
 
@@ -18,10 +14,6 @@
  * @author imi
  */
-abstract public class Engine implements PropertyChangeListener {
+abstract public class Engine {
 
-	/**
-	 * The projection method, this engine uses to render the graphics.
-	 */
-	protected Projection projection;
 	/**
 	 * The Graphics surface to draw on. This should be set before each painting
@@ -32,15 +24,6 @@
 	 * The mapView, this engine was created for.
 	 */
-	protected final MapView mv;
+	protected MapView mv;
 
-	
-	/**
-	 * Creates an Engine from an MapView it belongs to.
-	 * @param mapView The mapview this engine belongs to.
-	 */
-	public Engine(MapView mapView) {
-		mv = mapView;
-		mv.addPropertyChangeListener(this);
-	}
 	
 	/**
@@ -48,13 +31,8 @@
 	 * @param g
 	 */
-	public void init(Graphics g) {
+	public void init(Graphics g, MapView mv) {
 		this.g = g;
+		this.mv = mv;
 	}
-
-	/**
-	 * Draw the background. The coordinates are given as hint (e.g. to draw
-	 * an background image).
-	 */
-	abstract public void drawBackground(GeoPoint ul, GeoPoint lr);
 
 	/**
@@ -73,12 +51,3 @@
 	 */
 	abstract public void drawPendingLineSegment(LineSegment ls);
-
-	/**
-	 * Called when the projection method for the map changed. Subclasses with
-	 * caches depending on the projection should empty the cache now.
-	 */
-	public void propertyChange(PropertyChangeEvent e) {
-		if (e.getPropertyName().equals("projection"))
-			projection = (Projection)e.getNewValue();
-	}
 }
Index: src/org/openstreetmap/josm/gui/engine/RawGpsEngine.java
===================================================================
--- src/org/openstreetmap/josm/gui/engine/RawGpsEngine.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/engine/RawGpsEngine.java	(revision 17)
@@ -0,0 +1,79 @@
+package org.openstreetmap.josm.gui.engine;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+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.Main;
+
+/**
+ * This engine draws data from raw gps sources. It is to be in the backgound
+ * and give an editor a hint of where he walked.
+ * @author imi
+ */
+public class RawGpsEngine extends Engine implements PropertyChangeListener {
+
+	/**
+	 * Create a raw gps engine. The engine will register itself as listener on
+	 * the main preference settings to capture the drawRawGpsLines changes.
+	 */
+	public RawGpsEngine() {
+		Main.pref.addPropertyChangeListener(this);
+	}
+
+	/**
+	 * Draw nodes as small gray dots
+	 */
+	@Override
+	public void drawNode(Node n) {
+		Point p = mv.getScreenPoint(n.coor);
+		g.setColor(n.isSelected() ? Color.WHITE : Color.GRAY);
+		g.drawRect(p.x, p.y, 0, 0);
+	}
+
+	/**
+	 * Draw tracks by drawing all line segments as simple gray lines.
+	 * If the main preference "drawRawGpsLines" is set to false, nothing
+	 * is drawn.
+	 */
+	@Override
+	public void drawTrack(Track t) {
+		if (!Main.pref.isDrawRawGpsLines())
+			return;
+		for (LineSegment ls : t.segments())
+			drawLineSegment(ls, t.isSelected() ? Color.WHITE : Color.GRAY);
+	}
+
+	/**
+	 * Draw line segments as simple gray lines.
+	 */
+	@Override
+	public void drawPendingLineSegment(LineSegment ls) {
+		drawLineSegment(ls, Color.GRAY);
+	}
+
+	/**
+	 * Draw the line segment in the given color.
+	 * @param ls		The line segment to draw.
+	 * @param color		The color, the line segment should be drawn in.
+	 */
+	private void drawLineSegment(LineSegment ls, Color color) {
+		g.setColor(ls.isSelected() ? Color.WHITE : color);
+		Point p1 = mv.getScreenPoint(ls.getStart().coor);
+		Point p2 = mv.getScreenPoint(ls.getEnd().coor);
+		g.drawLine(p1.x, p1.y, p2.x, p2.y);
+	}
+
+
+	/**
+	 * Called when the some preferences are changed.
+	 */
+	public void propertyChange(PropertyChangeEvent e) {
+		if (e.getPropertyName().equals("drawRawGpsLines"))
+			mv.repaint();
+	}
+}
Index: src/org/openstreetmap/josm/gui/engine/SimpleEngine.java
===================================================================
--- src/org/openstreetmap/josm/gui/engine/SimpleEngine.java	(revision 16)
+++ src/org/openstreetmap/josm/gui/engine/SimpleEngine.java	(revision 17)
@@ -6,9 +6,7 @@
 import java.util.HashSet;
 
-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.Track;
-import org.openstreetmap.josm.gui.MapView;
 
 /**
@@ -22,17 +20,4 @@
 	private final static Color darkblue = new Color(0,0,128);
 	private final static Color darkgreen = new Color(0,128,0);
-
-	public SimpleEngine(MapView mapView) {
-		super(mapView);
-	}
-
-	/**
-	 * Draws black background.
-	 */
-	@Override
-	public void drawBackground(GeoPoint ulGeo, GeoPoint lrGeo) {
-		g.setColor(Color.BLACK);
-		g.fillRect(0,0,mv.getWidth(),mv.getHeight());
-	}
 
 	/**
Index: src/org/openstreetmap/josm/gui/layer/DataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/DataLayer.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/layer/DataLayer.java	(revision 17)
@@ -0,0 +1,82 @@
+package org.openstreetmap.josm.gui.layer;
+
+import java.awt.Graphics;
+
+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.Track;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.engine.Engine;
+
+/**
+ * Base class for all layer that depends on some DataSet.
+ * The dataset is final and so can not be changed later.
+ * 
+ * @author imi
+ */
+public abstract class DataLayer implements Layer {
+
+	/**
+	 * The dataSet this layer operates on.
+	 */
+	protected final DataSet dataSet;
+	/**
+	 * The engine used to draw the data.
+	 */
+	protected final Engine engine;
+	/**
+	 * The name of this layer.
+	 */
+	private final String name;
+	/**
+	 * The visibility state of the layer.
+	 */
+	private boolean visible = true;
+
+	/**
+	 * Construct the datalayer and fill the dataset.
+	 * @param name The name of this layer. Returned by getName.
+	 */
+	public DataLayer(DataSet dataSet, Engine engine, String name) {
+		if (dataSet == null || engine == null || name == null)
+			throw new NullPointerException();
+		this.name = name;
+		this.dataSet = dataSet;
+		this.engine = engine;
+	}
+
+	/**
+	 * Paint the dataset using the engine set.
+	 * @param mv The object that can translate GeoPoints to screen coordinates.
+	 */
+	public void paint(Graphics g, MapView mv) {
+		engine.init(g, mv);
+
+		for (Track t : dataSet.tracks())
+			engine.drawTrack(t);
+		for (LineSegment ls : dataSet.pendingLineSegments())
+			engine.drawPendingLineSegment(ls);
+		for (Node n : dataSet.nodes)
+			engine.drawNode(n);
+	}
+
+	/**
+	 * Return the data set behind this data layer.
+	 */
+	public DataSet getDataSet() {
+		return dataSet;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public boolean isVisible() {
+		return visible;
+	}
+
+	public void setVisible(boolean visible) {
+		this.visible = visible;
+	}
+}
Index: src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 17)
@@ -0,0 +1,68 @@
+package org.openstreetmap.josm.gui.layer;
+
+import java.awt.Graphics;
+
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.MapView;
+
+/**
+ * A layer encapsulates the gui componente of one dataset and its representation.
+ * 
+ * Some layers may display data directly importet from OSM server. Other only 
+ * display background images. Some can be edited, some not. Some are static and 
+ * other changes dynamically (auto-updated).
+ *
+ * Layers can be visible or not. Most actions the user can do applies only on
+ * selected layers. The available actions depend on the selected layers too.
+ * 
+ * All layers are managed by the MapView. They are displayed in a list to the 
+ * right of the screen.
+ * 
+ * @author imi
+ */
+public interface Layer {
+
+	/**
+	 * Draw the layer on the given Graphics. The state of the graphics object
+	 * can be changed (drawing color..)
+	 *
+	 * @param g The graphics to draw the layer on.
+	 * @param mv The MapView with information about the screen layout. 
+	 */
+	void paint(Graphics g, MapView mv);
+
+	/**
+	 * Return a representative small image for this layer. The image must not 
+	 * be larger than 64 pixel in any dimension.
+	 */
+	Icon getIcon();
+
+	/**
+	 * Provide a human readable name (may be in html format).
+	 */
+	String getName();
+	
+	/**
+	 * If the layer has a dataset it can provide, return it here.
+	 * @return The dataset for this layer or <code>null</code> if no dataset
+	 * 		is available.
+	 */
+	DataSet getDataSet();
+	
+	/**
+	 * @return <code>true</code>, if the map data can be edited.
+	 */
+	boolean isEditable();
+
+	/**
+	 * @return <code>true</code>, if the layer is visible
+	 */
+	boolean isVisible();
+	
+	/**
+	 * Set the visibility state of the layer.
+	 */
+	void setVisible(boolean visible);
+}
Index: src/org/openstreetmap/josm/gui/layer/LayerFactory.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/LayerFactory.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/layer/LayerFactory.java	(revision 17)
@@ -0,0 +1,24 @@
+package org.openstreetmap.josm.gui.layer;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+
+/**
+ * A factory class that create Layers.
+ *
+ * @author imi
+ */
+public class LayerFactory {
+
+	/**
+	 * Create a layer from a given DataSet. The DataSet cannot change over the
+	 * layers lifetime (but the data in the dataset may change)
+	 * 
+	 * @param dataSet The dataSet this layer displays.
+	 * @param rawGps  <code>true</code>, if the dataSet contain raw gps data.
+	 * @return The created layer instance. 
+	 */
+	public static Layer create(DataSet dataSet, String name, boolean rawGps) {
+		Layer layer = rawGps ? new RawGpsDataLayer(dataSet, name) : new OsmDataLayer(dataSet, name);
+		return layer;
+	}
+}
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 17)
@@ -0,0 +1,40 @@
+package org.openstreetmap.josm.gui.layer;
+
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.ImageProvider;
+import org.openstreetmap.josm.gui.engine.SimpleEngine;
+
+/**
+ * A layer holding data imported from the osm server.
+ * 
+ * The data can be fully edited.
+ * 
+ * @author imi
+ */
+public class OsmDataLayer extends DataLayer {
+
+	private static Icon icon;
+	
+	/**
+	 * Construct a OsmDataLayer.
+	 */
+	protected OsmDataLayer(DataSet dataSet, String name) {
+		super(dataSet, new SimpleEngine(), name);
+	}
+
+	/**
+	 * TODO: @return Return a dynamic drawn icon of the map data. The icon is
+	 * 		updated by a background thread to not disturb the running programm.
+	 */
+	public Icon getIcon() {
+		if (icon == null)
+			icon = ImageProvider.get("layer", "osmdata");
+		return icon;
+	}
+
+	public boolean isEditable() {
+		return true;
+	}
+}
Index: src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java	(revision 17)
+++ src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java	(revision 17)
@@ -0,0 +1,35 @@
+package org.openstreetmap.josm.gui.layer;
+
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.ImageProvider;
+import org.openstreetmap.josm.gui.engine.RawGpsEngine;
+
+/**
+ * A layer holding data from a gps source.
+ * The data is read only.
+ * 
+ * @author imi
+ */
+public class RawGpsDataLayer extends DataLayer {
+
+	private static Icon icon;
+
+	protected RawGpsDataLayer(DataSet dataSet, String name) {
+		super(dataSet, new RawGpsEngine(), name);
+	}
+
+	/**
+	 * Return a static icon.
+	 */
+	public Icon getIcon() {
+		if (icon == null)
+			icon = ImageProvider.get("layer", "rawgps");
+		return icon;
+	}
+
+	public boolean isEditable() {
+		return false;
+	}
+}
Index: src/org/openstreetmap/josm/io/GpxReader.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxReader.java	(revision 16)
+++ src/org/openstreetmap/josm/io/GpxReader.java	(revision 17)
@@ -40,11 +40,21 @@
 	 */
 	public Reader source;
+	/**
+	 * If <code>true</code>, only nodes and tracks are imported (but no key/value
+	 * pairs). That is to support background gps information as an hint for 
+	 * real OSM data.
+	 */
+	private final boolean rawGps;
 	
 	/**
 	 * Construct a parser from a specific data source.
 	 * @param source The data source, as example a FileReader to read from a file.
-	 */
-	public GpxReader(Reader source) {
+	 * @param rawGps Whether the gpx file describes raw gps data. Only very few
+	 * 		information (only nodes and line segments) imported for raw gps to 
+	 * 		save memory.
+	 */
+	public GpxReader(Reader source, boolean rawGps) {
 		this.source = source;
+		this.rawGps = rawGps;
 	}
 	
@@ -56,5 +66,4 @@
 			final SAXBuilder builder = new SAXBuilder();
 			Element root = builder.build(source).getRootElement();
-			System.out.println(root.getNamespacePrefix());
 			
 			// HACK, since the osm server seem to not provide a namespace.
@@ -85,4 +94,8 @@
 			Float.parseFloat(e.getAttributeValue("lat")),
 			Float.parseFloat(e.getAttributeValue("lon")));
+		
+		if (rawGps)
+			return data;
+		
 		for (Object o : e.getChildren()) {
 			Element child = (Element)o;
@@ -126,9 +139,6 @@
 		for (Object o : e.getChildren()) {
 			Element child = (Element)o;
-			if (child.getName().equals("extensions"))
-				parseKeyValueExtensions(track, child);
-			else if (child.getName().equals("link"))
-				parseKeyValueLink(track, child);
-			else if (child.getName().equals("trkseg")) {
+
+			if (child.getName().equals("trkseg")) {
 				Node start = null;
 				for (Object w : child.getChildren("trkpt", GPX)) {
@@ -139,10 +149,20 @@
 					else {
 						LineSegment lineSegment = new LineSegment(start, node);
-						parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX));
+						if (!rawGps)
+							parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX));
 						track.add(lineSegment);
 						start = null;
 					}
 				}
-			} else
+			}
+			
+			if (rawGps)
+				continue;
+			
+			if (child.getName().equals("extensions"))
+				parseKeyValueExtensions(track, child);
+			else if (child.getName().equals("link"))
+				parseKeyValueLink(track, child);
+			else
 				parseKeyValueTag(track, child);
 		}
@@ -156,4 +176,7 @@
 	 * to the node in the list (either the new added or the old found).
 	 * 
+	 * If reading raw gps data, mergeNodes are always on (To save memory. You
+	 * can't edit raw gps nodes anyway.)
+	 * 
 	 * @param data The DataSet to add the node to.
 	 * @param node The node that should be added.
@@ -161,7 +184,7 @@
 	 */
 	private Node addNode (DataSet data, Node node) {
-		if (Main.pref.mergeNodes)
+		if (Main.pref.mergeNodes || rawGps)
 			for (Node n : data.nodes)
-				if (node.coor.lat == n.coor.lat && node.coor.lon == n.coor.lon)
+				if (node.coor.equalsLatLon(n.coor))
 					return n;
 		data.nodes.add(node);
