Index: src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 8)
@@ -130,7 +130,7 @@
 		if (start != end) {
 			// try to find a line segment
-			for (Track t : ds.tracks)
-				for (LineSegment ls : t.segments)
-					if (start == ls.start && end == ls.end) {
+			for (Track t : ds.tracks())
+				for (LineSegment ls : t.segments())
+					if (start == ls.getStart() && end == ls.getEnd()) {
 						JOptionPane.showMessageDialog(Main.main, "There is already an line segment with the same direction between the selected nodes.");
 						return;
@@ -142,14 +142,14 @@
 			if (((e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0)) {
 				// find a track for the new line segment
-				for (Track t : ds.tracks) {
+				for (Track t : ds.tracks()) {
 					if (t.getEndingNode() == start) {
-						t.segments.add(ls);
+						t.add(ls);
 						foundTrack = true;
 					}
 				}
 				if (!foundTrack) {
-					for (Track t : ds.tracks) {
+					for (Track t : ds.tracks()) {
 						if (t.getStartingNode() == end) {
-							t.segments.add(0,ls);
+							t.addStart(ls);
 							foundTrack = true;
 						}
@@ -158,5 +158,5 @@
 			}
 			if (!foundTrack)
-				ds.pendingLineSegments.add(ls);
+				ds.addPendingLineSegment(ls);
 		}
 		
Index: src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java	(revision 8)
@@ -80,5 +80,5 @@
 		Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
 		for (OsmPrimitive osm : selectionList)
-			osm.selected = !ctrl;
+			osm.setSelected(!ctrl, ds);
 
 		mv.repaint(); // from now on, the map has to be repainted.
@@ -95,12 +95,12 @@
 		for (OsmPrimitive osm : selection) {
 			if (osm instanceof Track)
-				lineSegments.addAll(((Track)osm).segments);
+				lineSegments.addAll(((Track)osm).segments());
 			else if (osm instanceof LineSegment)
 				lineSegments.add((LineSegment)osm);
 		}
 		Track t = new Track();
-		t.segments.addAll(lineSegments);
-		ds.tracks.add(t);
-		ds.pendingLineSegments.removeAll(lineSegments);
+		for (LineSegment ls : lineSegments)
+			ds.assignPendingLineSegment(ls, t, true);
+		ds.addTrack(t);
 		ds.clearSelection();
 	}
Index: src/org/openstreetmap/josm/actions/mapmode/CombineAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/CombineAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/CombineAction.java	(revision 8)
@@ -136,5 +136,5 @@
 			return;
 
-		if (first == null || second == null) {
+		if (first == null || second == null || first == second) {
 			first = null;
 			second = null;
@@ -160,10 +160,10 @@
 					t2 = (Track)first;
 				}
-				t1.segments.addAll(t2.segments);
+				t1.addAll(t2.segments());
 				if (t1.keys == null)
 					t1.keys = t2.keys;
 				else	
 					t1.keys.putAll(t2.keys);
-				ds.tracks.remove(t2);
+				ds.removeTrack(t2);
 			}
 		}
@@ -178,12 +178,8 @@
 	 */
 	private void combine(LineSegment ls, Track t) {
-		if (!ds.pendingLineSegments.contains(first))
+		if (!ds.pendingLineSegments().contains(ls))
 			throw new IllegalStateException("Should not be able to select non-pending line segments.");
 		
-		if (t.getStartingNode() == ls.end)
-			t.segments.add(0, ls);
-		else
-			t.segments.add(ls);
-		ds.pendingLineSegments.remove(ls);
+		ds.assignPendingLineSegment(ls, t, t.getStartingNode() != ls.getEnd());
 	}
 
@@ -203,5 +199,6 @@
 
 		Graphics g = mv.getGraphics();
-		g.setColor(draw ? Color.WHITE : Color.GRAY); // HACK
+		g.setColor(Color.BLACK);
+		g.setXORMode(Color.WHITE);
 		draw(g, first);
 		draw(g, second);
@@ -217,15 +214,12 @@
 		if (osm instanceof LineSegment) {
 			LineSegment ls = (LineSegment)osm;
-			Point start = mv.getScreenPoint(ls.start.coor);
-			Point end = mv.getScreenPoint(ls.end.coor);
-			if (mv.dataSet.pendingLineSegments.contains(osm) && g.getColor() == Color.GRAY) {
-				// HACK
-				g.setColor(Color.LIGHT_GRAY);
+			Point start = mv.getScreenPoint(ls.getStart().coor);
+			Point end = mv.getScreenPoint(ls.getEnd().coor);
+			if (mv.dataSet.pendingLineSegments().contains(osm) && g.getColor() == Color.GRAY)
 				g.drawLine(start.x, start.y, end.x, end.y);
-				g.setColor(Color.GRAY);
-			} else
+			else
 				g.drawLine(start.x, start.y, end.x, end.y);
 		} else if (osm instanceof Track) {
-			for (LineSegment ls : ((Track)osm).segments)
+			for (LineSegment ls : ((Track)osm).segments())
 				draw(g, ls);
 		}
Index: src/org/openstreetmap/josm/actions/mapmode/DebugAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DebugAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/DebugAction.java	(revision 8)
@@ -48,8 +48,8 @@
 		Graphics g = mapFrame.mapView.getGraphics();
 		g.setColor(Color.WHITE);
-		for (Track t :mapFrame.mapView.dataSet.tracks)
-			for (LineSegment ls : t.segments) {
-				Point A = mapFrame.mapView.getScreenPoint(ls.start.coor);
-				Point B = mapFrame.mapView.getScreenPoint(ls.end.coor);
+		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);
Index: src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 8)
@@ -5,5 +5,5 @@
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Map;
 
@@ -133,10 +133,10 @@
 		if (osm instanceof Node) {
 			// delete any track and line segment the node is in.
-			for (Track t : ds.tracks)
-				for (LineSegment ls : t.segments)
-					if (ls.start == osm || ls.end == osm)
+			for (Track t : ds.tracks())
+				for (LineSegment ls : t.segments())
+					if (ls.getStart() == osm || ls.getEnd() == osm)
 						tracksToDelete.add(t);
-			for (LineSegment ls : ds.pendingLineSegments)
-				if (ls.start == osm || ls.end == osm)
+			for (LineSegment ls : ds.pendingLineSegments())
+				if (ls.getStart() == osm || ls.getEnd() == osm)
 					lineSegmentsToDelete.add(ls);
 				
@@ -144,6 +144,6 @@
 			LineSegment lineSegment = (LineSegment)osm;
 			lineSegmentsToDelete.add(lineSegment);
-			for (Track t : ds.tracks)
-				for (LineSegment ls : t.segments)
+			for (Track t : ds.tracks())
+				for (LineSegment ls : t.segments())
 					if (lineSegment == ls)
 						tracksToDelete.add(t);
@@ -154,17 +154,19 @@
 		ArrayList<Node> checkUnreferencing = new ArrayList<Node>();
 		for (Track t : tracksToDelete) {
-			for (LineSegment ls : t.segments) {
-				checkUnreferencing.add(ls.start);
-				checkUnreferencing.add(ls.end);
+			for (LineSegment ls : t.segments()) {
+				checkUnreferencing.add(ls.getStart());
+				checkUnreferencing.add(ls.getEnd());
 			}
 		}
 		for (LineSegment ls : lineSegmentsToDelete) {
-			checkUnreferencing.add(ls.start);
-			checkUnreferencing.add(ls.end);
+			checkUnreferencing.add(ls.getStart());
+			checkUnreferencing.add(ls.getEnd());
 		}
 		
 		// delete tracks and areas
-		ds.tracks.removeAll(tracksToDelete);
-		ds.pendingLineSegments.removeAll(lineSegmentsToDelete);
+		for (Track t : tracksToDelete)
+			ds.removeTrack(t);
+		for (LineSegment ls : lineSegmentsToDelete)
+			ds.destroyPendingLineSegment(ls);
 
 		// removing all unreferenced nodes
@@ -198,14 +200,17 @@
 			ds.nodes.remove(n);
 		} else if (osm instanceof LineSegment) {
-			for (Iterator<Track> it = ds.tracks.iterator(); it.hasNext();) {
-				Track t = it.next();
-				t.segments.remove(osm);
-				if (t.segments.isEmpty())
-					it.remove();
-			}
-			ds.pendingLineSegments.remove(osm);
+			LinkedList<Track> tracksToDelete = new LinkedList<Track>();
+			for (Track t : ds.tracks()) {
+				t.remove((LineSegment)osm);
+				if (t.segments().isEmpty())
+					tracksToDelete.add(t);
+			}
+			for (Track t : tracksToDelete)
+				ds.removeTrack(t);
+			ds.destroyPendingLineSegment((LineSegment)osm);
 		} else if (osm instanceof Track) {
-			ds.tracks.remove(osm);
-			ds.pendingLineSegments.addAll(((Track)osm).segments);
+			ds.removeTrack((Track)osm);
+			for (LineSegment ls : ((Track)osm).segments())
+				ds.addPendingLineSegment(ls);
 		}
 	}
@@ -218,10 +223,10 @@
 	 */
 	private boolean isReferenced(Node n) {
-		for (Track t : ds.tracks)
-			for (LineSegment ls : t.segments)
-				if (ls.start == n || ls.end == n)
+		for (Track t : ds.tracks())
+			for (LineSegment ls : t.segments())
+				if (ls.getStart() == n || ls.getEnd() == n)
 					return true;
-		for (LineSegment ls : ds.pendingLineSegments)
-			if (ls.start == n || ls.end == n)
+		for (LineSegment ls : ds.pendingLineSegments())
+			if (ls.getStart() == n || ls.getEnd() == n)
 				return true;
 		// TODO areas
@@ -240,6 +245,6 @@
 	private String combine(Node n) {
 		// first, check for pending line segments
-		for (LineSegment ls : ds.pendingLineSegments)
-			if (n == ls.start || n == ls.end)
+		for (LineSegment ls : ds.pendingLineSegments())
+			if (n == ls.getStart() || n == ls.getEnd())
 				return "Node used by a line segment which is not part of any track. Remove this first."; 
 		
@@ -253,8 +258,8 @@
 		HashMap<ArrayList<LineSegment>, Track> lineSegments = new HashMap<ArrayList<LineSegment>, Track>();
 		
-		for (Track t : ds.tracks) {
+		for (Track t : ds.tracks()) {
 			ArrayList<LineSegment> current = new ArrayList<LineSegment>();
-			for (LineSegment ls : t.segments)
-				if (ls.start == n || ls.end == n)
+			for (LineSegment ls : t.segments())
+				if (ls.getStart() == n || ls.getEnd() == n)
 					current.add(ls);
 			if (!current.isEmpty()) {
@@ -262,8 +267,8 @@
 					return "Node used by more than two line segments.";
 				if (current.size() == 1 && 
-						(current.get(0) == t.segments.get(0) || current.get(0) == t.segments.get(t.segments.size()-1)))
+						(current.get(0) == t.getStartingSegment() || current.get(0) == t.getEndingSegment()))
 					pendingLineSegmentsForTrack.add(current.get(0));
-				else if (current.get(0).end != current.get(1).start &&
-						current.get(1).end != current.get(0).start)
+				else if (current.get(0).getEnd() != current.get(1).getStart() &&
+						current.get(1).getEnd() != current.get(0).getStart())
 					return "Node used by line segments that points together.";
 				else if (!current.get(0).keyPropertiesMergable(current.get(1)))
@@ -276,6 +281,6 @@
 		// try to combine tracks
 		ArrayList<Track> tracks = new ArrayList<Track>();
-		for (Track t : ds.tracks)
-			if (!t.segments.isEmpty() && (t.segments.get(0).start == n || t.segments.get(t.segments.size()-1).end == n))
+		for (Track t : ds.tracks())
+			if (t.getStartingNode() == n || t.getEndingNode() == n)
 				tracks.add(t);
 		if (!tracks.isEmpty()) {
@@ -286,8 +291,8 @@
 			Track t1 = tracks.get(0);
 			Track t2 = tracks.get(1);
-			if (t1.segments.get(0).start != t2.segments.get(t2.segments.size()-1).end &&
-					t2.segments.get(0).start != t1.segments.get(t1.segments.size()-1).end) {
-				if (t1.segments.get(0).start == t2.segments.get(t2.segments.size()-1).start ||
-						t1.segments.get(0).end == t2.segments.get(t2.segments.size()-1).end)
+			if (t1.getStartingNode() != t2.getEndingNode() &&
+					t2.getStartingNode() != t1.getEndingNode()) {
+				if (t1.getStartingNode() == t2.getStartingNode() ||
+						t1.getEndingNode() == t2.getEndingNode())
 					return "Node used by tracks that point together.";
 				return "Node used by tracks that cannot be combined.";
@@ -301,7 +306,7 @@
 			LineSegment l1 = pendingLineSegmentsForTrack.get(0);
 			LineSegment l2 = pendingLineSegmentsForTrack.get(1);
-			if (l1.start == l2.start || l1.end == l2.end)
+			if (l1.getStart() == l2.getStart() || l1.getEnd() == l2.getEnd())
 				return "Node used by line segments that points together.";
-			if (l1.start == l2.end || l2.start == l1.end)
+			if (l1.getStart() == l2.getEnd() || l2.getStart() == l1.getEnd())
 				pendingLineSegmentsForTrack.clear(); // resolved.
 		}
@@ -316,11 +321,11 @@
 			LineSegment first = list.get(0);
 			LineSegment second = list.get(1);
-			if (first.start == second.end) {
+			if (first.getStart() == second.getEnd()) {
 				first = second;
 				second = list.get(0);
 			}
-			first.end = second.end;
+			first.setEnd(second.getEnd());
 			first.keys = mergeKeys(first.keys, second.keys);
-			lineSegments.get(list).segments.remove(second);
+			lineSegments.get(list).remove(second);
 		}
 		
@@ -329,17 +334,17 @@
 			Track first = tracks.get(0);
 			Track second = tracks.get(1);
-			if (first.segments.get(0).start == second.segments.get(second.segments.size()-1).end) {
+			if (first.getStartingNode() == second.getEndingNode()) {
 				first = second;
 				second = tracks.get(0);
 			}
 			// concatenate the line segments.
-			LineSegment lastOfFirst = first.segments.get(first.segments.size()-1);
-			LineSegment firstOfSecond = second.segments.get(0);
-			lastOfFirst.end = firstOfSecond.end;
+			LineSegment lastOfFirst = first.getEndingSegment();
+			LineSegment firstOfSecond = second.getStartingSegment();
+			lastOfFirst.setEnd(firstOfSecond.getEnd());
 			lastOfFirst.keys = mergeKeys(lastOfFirst.keys, firstOfSecond.keys);
-			second.segments.remove(firstOfSecond);
+			second.remove(firstOfSecond);
 			// move the remaining line segments to first track.
-			first.segments.addAll(second.segments);
-			ds.tracks.remove(second);
+			first.addAll(second.segments());
+			ds.removeTrack(second);
 		}
 		
Index: src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 8)
@@ -113,5 +113,5 @@
 			OsmPrimitive osm = mv.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0);
 			if (osm != null)
-				osm.selected = true;
+				osm.setSelected(true, ds);
 			singleOsmPrimitive = osm;
 			mv.repaint();
@@ -131,5 +131,5 @@
 		mv.setCursor(oldCursor);
 		if (singleOsmPrimitive != null) {
-			singleOsmPrimitive.selected = false;
+			singleOsmPrimitive.setSelected(false, ds);
 			mv.repaint();
 		}
Index: src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 7)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 8)
@@ -91,5 +91,5 @@
 		Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
 		for (OsmPrimitive osm : selectionList)
-			osm.selected = !ctrl;
+			osm.setSelected(!ctrl, ds);
 		mv.repaint();
 	}
Index: src/org/openstreetmap/josm/data/SelectionChangedListener.java
===================================================================
--- src/org/openstreetmap/josm/data/SelectionChangedListener.java	(revision 8)
+++ src/org/openstreetmap/josm/data/SelectionChangedListener.java	(revision 8)
@@ -0,0 +1,25 @@
+package org.openstreetmap.josm.data;
+
+import java.util.Collection;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ * This is a listener for selection changes through the dataset's data. Whenever
+ * a selection of any data meber changes, the dataSet gets informed about this
+ * and fire a selectionChanged event.
+ * 
+ * Note, that these events get not fired immediately but are inserted in the
+ * Swing-event queue and packed together. So only one selection changed event
+ * are issued within one message dispatch routine.
+ * 
+ * @author imi
+ */
+public interface SelectionChangedListener {
+
+	/**
+	 * Informs the listener that the selection in the dataset has changed.
+	 * @param newSelection The new selection.
+	 */
+	public void selectionChanged(Collection<OsmPrimitive> newSelection);
+}
Index: src/org/openstreetmap/josm/data/SelectionTracker.java
===================================================================
--- src/org/openstreetmap/josm/data/SelectionTracker.java	(revision 8)
+++ src/org/openstreetmap/josm/data/SelectionTracker.java	(revision 8)
@@ -0,0 +1,110 @@
+package org.openstreetmap.josm.data;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ * This class is to help the DataSet collecting and fire selectionChanged events.
+ * For more, @see org.openstreetmap.josm.data.SelectionChangedListener
+ * 
+ * @author imi
+ */
+abstract public class SelectionTracker {
+
+	/**
+	 * Collects the selction changed events. The first collector that runs in 
+	 * one queue, starts the purger.
+	 * @author imi
+	 */
+	private final class Collector implements Runnable {
+		public void run() {
+			switch (state) {
+			case WAITING:
+				throw new IllegalStateException();
+			case COLLECTING:
+				state = SelectionEventState.PURGING;
+				SwingUtilities.invokeLater(new Purger());
+				break;
+			case PURGING:
+				break; // still purging events.
+			}
+		}
+	}
+
+	/**
+	 * Informs the listener clients and go back to waiting state.
+	 * @author imi
+	 */
+	private final class Purger implements Runnable {
+		public void run() {
+			if (state != SelectionEventState.PURGING)
+				throw new IllegalStateException();
+			state = SelectionEventState.WAITING;
+			Collection<OsmPrimitive> sel = getSelected();
+			for (SelectionChangedListener l : listeners)
+				l.selectionChanged(sel);
+		}
+	}
+
+	/**
+	 * The event state for the selection dispatching. WAITING means we are
+	 * waiting for any fireSelectionChanged event. COLLECTING means, we have
+	 * already some events in the EventQueue and are now collecting more events.
+	 * PURGING means, the collecting phase is over and we wait now for the finish
+	 * event to just contact the listeners.
+	 * @author imi
+	 */
+	private enum SelectionEventState {WAITING, COLLECTING, PURGING};
+
+	/**
+	 * The state, regarding to the selection changing that we are in.
+	 */
+	transient private SelectionEventState state = SelectionEventState.WAITING;
+
+	/**
+	 * A list of listeners to selection changed events.
+	 */
+	transient private Collection<SelectionChangedListener> listeners = new LinkedList<SelectionChangedListener>();
+
+	
+	/**
+	 * Add a listener to the selection changed listener list. If <code>null</code>
+	 * is passed, nothing happens.
+	 * @param listener The listener to add to the list.
+	 */
+	public void addSelectionChangedListener(SelectionChangedListener listener) {
+		if (listener != null)
+			listeners.add(listener);
+	}
+	
+	/**
+	 * Remove a listener from the selection changed listener list. 
+	 * If <code>null</code> is passed, nothing happens.
+	 * @param listener The listener to remove from the list.
+	 */
+	public void removeSelectionChangedListener(SelectionChangedListener listener) {
+		if (listener != null)
+			listeners.remove(listener);
+	}
+	
+	/**
+	 * Remember to fire an selection changed event. A call to this will not fire
+	 * the event immediately. For more, @see SelectionChangedListener
+	 */
+	public void fireSelectionChanged() {
+		if (state == SelectionEventState.WAITING) {
+			state = SelectionEventState.COLLECTING;
+			SwingUtilities.invokeLater(new Collector());
+		}
+	}
+	
+	/**
+	 * This function is needed by the Purger to get the actual selection.
+	 * @return The selected primitives.
+	 */
+	abstract public Collection<OsmPrimitive> getSelected();
+}
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 8)
@@ -2,8 +2,10 @@
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedList;
 
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.SelectionTracker;
 
 /**
@@ -17,5 +19,5 @@
  * @author imi
  */
-public class DataSet implements Cloneable {
+public class DataSet extends SelectionTracker implements Cloneable {
 
 	/**
@@ -30,5 +32,5 @@
 	 * are in this list but are in no track.
 	 */
-	public Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
+	private Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
 
 	/**
@@ -39,5 +41,60 @@
 	 * track list.
 	 */
-	public Collection<Track> tracks;
+	private Collection<Track> tracks = new LinkedList<Track>();
+
+	/**
+	 * Add the track to the tracklist.
+	 */
+	public void addTrack(Track t) {
+		tracks.add(t);
+	}
+	/**
+	 * Remove the track from the tracklist.
+	 */
+	public void removeTrack(Track t) {
+		t.destroy();
+		tracks.remove(t);
+	}
+	/**
+	 * Return a read-only collection of all tracks
+	 */
+	public Collection<Track> tracks() {
+		return Collections.unmodifiableCollection(tracks);
+	}
+
+	/**
+	 * Add a newly created line segment to the pending lines list.
+	 */
+	public void addPendingLineSegment(LineSegment ls) {
+		pendingLineSegments.add(ls);
+	}
+	/**
+	 * Remove a line segment from the pending lines list, because it has been
+	 * assigned to the track.
+	 * @param ls The line segment from the pending list
+	 * @param t The track, that will hold the line segment
+	 * @param end <code>true</code> to attach on the end. <code>false</code>
+	 * 		to attach on the beginning.
+	 */
+	public void assignPendingLineSegment(LineSegment ls, Track t, boolean end) {
+		pendingLineSegments.remove(ls);
+		if (end)
+			t.add(ls);
+		else
+			t.addStart(ls);
+	}
+	/**
+	 * Delete the pending line segment without moving it anywhere.
+	 */
+	public void destroyPendingLineSegment(LineSegment ls) {
+		pendingLineSegments.remove(ls);
+		ls.destroy();
+	}
+	/**
+	 * Return an read-only iterator over all pending line segments.
+	 */
+	public Collection<LineSegment> pendingLineSegments() {
+		return Collections.unmodifiableCollection(pendingLineSegments);
+	}
 
 	/**
@@ -73,24 +130,4 @@
 
 	/**
-	 * Return all tracks that contain the node. If nothing found, an empty array
-	 * is returned.
-	 * 
-	 * @param node This node is searched.
-	 * @return All tracks, that reference the node in one of its line segments.
-	 */
-	public Collection<Track> getReferencedTracks(Node n) {
-		Collection<Track> all = new LinkedList<Track>();
-		for (Track t : tracks) {
-			for (LineSegment ls : t.segments) {
-				if (ls.start == n || ls.end == n) {
-					all.add(t);
-					break;
-				}
-			}
-		}
-		return all;
-	}
-	
-	/**
 	 * Return the bounds of this DataSet, depending on lat/lon values.
 	 * The min of the return value is the upper left GeoPoint, the max the lower
@@ -131,5 +168,5 @@
 		clearSelection(tracks);
 		for (Track t : tracks)
-			clearSelection(t.segments);
+			clearSelection(t.segments());
 	}
 
@@ -138,4 +175,5 @@
 	 * @return List of all selected objects.
 	 */
+	@Override
 	public Collection<OsmPrimitive> getSelected() {
 		Collection<OsmPrimitive> sel = getSelected(nodes);
@@ -143,8 +181,8 @@
 		sel.addAll(getSelected(tracks));
 		for (Track t : tracks)
-			sel.addAll(getSelected(t.segments));
+			sel.addAll(getSelected(t.segments()));
 		return sel;
 	}
-	
+
 	/**
 	 * Remove the selection from every value in the collection.
@@ -155,5 +193,5 @@
 			return;
 		for (OsmPrimitive osm : list) {
-			osm.selected = false;
+			osm.setSelected(false, this);
 			if (osm.keys != null)
 				clearSelection(osm.keys.keySet());
@@ -170,5 +208,5 @@
 			return sel;
 		for (OsmPrimitive osm : list) {
-			if (osm.selected)
+			if (osm.isSelected())
 				sel.add(osm);
 			if (osm.keys != null)
Index: src/org/openstreetmap/josm/data/osm/Key.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Key.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/Key.java	(revision 8)
@@ -2,5 +2,9 @@
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
 
@@ -15,6 +19,34 @@
 	 * The key's name
 	 */
-	public String name;
+	public final String name;
 
+	/**
+	 * All keys are stored here.
+	 */
+	private static Map<String, Key> allKeys = new HashMap<String, Key>();
+	
+	/**
+	 * Generate a key with the given name. You cannot call this directly but
+	 * have to use the static constructor. This makes sure, you get every key
+	 * only once.
+	 */
+	private Key(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Get an instance of the key with the given name.
+	 * @param name	The name of the key to get.
+	 * @return An shared instance of the key with the given name. 
+	 */
+	public static Key get(String name) {
+		Key key = allKeys.get(name);
+		if (key == null) {
+			key = new Key(name);
+			allKeys.put(name, key);
+		}
+		return key;
+	}
+	
 	/**
 	 * Return an empty list, since keys cannot have nodes. 
@@ -39,3 +71,8 @@
 		return name.hashCode();
 	}
+
+	@Override
+	public void visit(Visitor visitor) {
+		visitor.visit(this);
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/LineSegment.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/LineSegment.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/LineSegment.java	(revision 8)
@@ -2,5 +2,8 @@
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
+
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
 
@@ -13,4 +16,19 @@
 
 	/**
+	 * The starting node of the line segment
+	 */
+	private Node start;
+	
+	/**
+	 * The ending node of the line segment
+	 */
+	private Node end;
+
+	/**
+	 * The tracks, this line segment is part of.
+	 */
+	transient Collection<Track> parent = new LinkedList<Track>();
+
+	/**
 	 * Create an line segment from the given starting and ending node
 	 * @param start	Starting node of the line segment.
@@ -20,15 +38,39 @@
 		this.start = start;
 		this.end = end;
+		start.parentSegment.add(this);
+		end.parentSegment.add(this);
 	}
 
 	/**
-	 * The starting node of the line segment
+	 * Return all parent tracks this line segment is part of. The list is readonly.
 	 */
-	public Node start;
-	
+	public Collection<Track> getParents() {
+		return Collections.unmodifiableCollection(parent);
+	}
+
+	public void setStart(Node start) {
+		this.start.parentSegment.remove(this);
+		this.start = start;
+		start.parentSegment.add(this);
+	}
+	public Node getStart() {
+		return start;
+	}
+	public void setEnd(Node end) {
+		this.end.parentSegment.remove(this);
+		this.end = end;
+		end.parentSegment.add(this);
+	}
+	public Node getEnd() {
+		return end;
+	}
+
 	/**
-	 * The ending node of the line segment
+	 * The LineSegment is going to be destroyed. Unlink all back references.
 	 */
-	public Node end;
+	void destroy() {
+		start.parentSegment.remove(this);
+		end.parentSegment.remove(this);
+	}
 
 	/**
@@ -38,6 +80,6 @@
 	public Collection<Node> getAllNodes() {
 		LinkedList<Node> nodes = new LinkedList<Node>();
-		nodes.add(start);
-		nodes.add(end);
+		nodes.add(getStart());
+		nodes.add(getEnd());
 		return nodes;
 	}
@@ -52,11 +94,16 @@
 			return false;
 		return super.equals(obj) && 
-			start.equals(((LineSegment)obj).start) &&
-			end.equals(((LineSegment)obj).end);
+			getStart().equals(((LineSegment)obj).getStart()) &&
+			getEnd().equals(((LineSegment)obj).getEnd());
 	}
 
 	@Override
 	public int hashCode() {
-		return super.hashCode() + start.hashCode() + end.hashCode();
+		return super.hashCode() + getStart().hashCode() + getEnd().hashCode();
+	}
+
+	@Override
+	public void visit(Visitor visitor) {
+		visitor.visit(this);
 	}
 }	
Index: src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Node.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/Node.java	(revision 8)
@@ -2,7 +2,9 @@
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
 
 import org.openstreetmap.josm.data.GeoPoint;
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
 
@@ -19,4 +21,17 @@
 	public GeoPoint coor;
 
+	/**
+	 * The list of line segments, this node is part of.
+	 */
+	transient Collection<LineSegment> parentSegment = new LinkedList<LineSegment>();
+
+	/**
+	 * Returns a read-only list of all segments this node is in.
+	 * @return A list of all segments. Readonly.
+	 */
+	public Collection<LineSegment> getParentSegments() {
+		return Collections.unmodifiableCollection(parentSegment);
+	}
+	
 	/**
 	 * Nodes are equal when their coordinates are equal.
@@ -49,5 +64,8 @@
 		return nodes;
 	}
-	
-	
+
+	@Override
+	public void visit(Visitor visitor) {
+		visitor.visit(this);
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 8)
@@ -3,4 +3,6 @@
 import java.util.Collection;
 import java.util.Map;
+
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
 
@@ -26,12 +28,20 @@
 	 * If set to true, this object is currently selected.
 	 */
-	transient public boolean selected = false;
+	transient private boolean selected = false;
 
 	/**
 	 * Return a list of all nodes, this osmPrimitive consists of. Does return
 	 * an empty list, if it is an primitive that cannot have nodes (e.g. Key)
+	 * TODO replace with visitor
 	 */
 	abstract public Collection<Node> getAllNodes();
 
+	/**
+	 * Implementation of the visitor scheme. Subclases have to call the correct
+	 * visitor function.
+	 * @param visitor The visitor from which the visit() function must be called.
+	 */
+	abstract public void visit(Visitor visitor);
+	
 	/**
 	 * Return <code>true</code>, if either <code>this.keys</code> and 
@@ -79,3 +89,22 @@
 		return keys == null ? 0 : keys.hashCode();
 	}
+
+	/**
+	 * Mark the primitive as selected or not selected and fires a selection 
+	 * changed later, if the value actualy changed.
+	 * @param selected Whether the primitive should be selected or not.
+	 * @param ds The dataSet, this primitive is in.
+	 */
+	public void setSelected(boolean selected, DataSet ds) {
+		if (selected != this.selected)
+			ds.fireSelectionChanged();
+		this.selected = selected;
+	}
+
+	/**
+	 * @return Return whether the primitive is selected on screen.
+	 */
+	public boolean isSelected() {
+		return selected;
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/Track.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Track.java	(revision 7)
+++ src/org/openstreetmap/josm/data/osm/Track.java	(revision 8)
@@ -3,5 +3,8 @@
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
 /**
@@ -15,5 +18,52 @@
 	 * All track segments in this track
 	 */
-	public final List<LineSegment> segments = new ArrayList<LineSegment>();
+	private final List<LineSegment> segments = new ArrayList<LineSegment>();
+
+	
+	/**
+	 * Add the line segment to the track.
+	 */
+	public void add(LineSegment ls) {
+		segments.add(ls);
+		ls.parent.add(this);
+	}
+
+	/**
+	 * Add the line segment at first position to the track. First position means,
+	 * the line segment's start becomes the starting node.
+	 * @param ls The line segment to add at starting position.
+	 * @see #getStartingNode()
+	 */
+	public void addStart(LineSegment ls) {
+		segments.add(ls);
+		ls.parent.add(this);
+	}
+
+	/**
+	 * Add all LineSegment's to the list of segments. 
+	 * @param lineSegments The line segments to add.
+	 */
+	public void addAll(Collection<? extends LineSegment> lineSegments) {
+		segments.addAll(lineSegments);
+		for (LineSegment ls : lineSegments)
+			ls.parent.add(this);
+	}
+	
+	/**
+	 * Remove the line segment from the track.
+	 */
+	public void remove(LineSegment ls) {
+		if (segments.remove(ls))
+			if (!ls.parent.remove(this))
+				throw new IllegalStateException("Parent violation detected.");
+	}
+
+	/**
+	 * Return an read-only collection. Do not alter the object returned.
+	 * @return The read-only Collection of all segments.
+	 */
+	public Collection<LineSegment> segments() {
+		return Collections.unmodifiableCollection(segments);
+	}
 
 	/**
@@ -26,4 +76,15 @@
 			nodes.addAll(ls.getAllNodes());
 		return nodes;
+	}
+	/**
+	 * The track is going to be destroyed. Unlink all back references.
+	 */
+	void destroy() {
+		for (LineSegment ls : segments) {
+			ls.parent.remove(this);
+			if (ls.parent.isEmpty())
+				ls.destroy();
+		}
+		segments.clear();
 	}
 
@@ -67,5 +128,15 @@
 		if (segments.isEmpty())
 			return null;
-		return segments.get(segments.size()-1).end;
+		return segments.get(segments.size()-1).getEnd();
+	}
+	
+	/**
+	 * Return the last segment.
+	 * @see #getEndingNode()
+	 */
+	public LineSegment getEndingSegment() {
+		if (segments.isEmpty())
+			return null;
+		return segments.get(segments.size()-1);
 	}
 
@@ -82,5 +153,20 @@
 		if (segments.isEmpty())
 			return null;
-		return segments.get(0).start;
+		return segments.get(0).getStart();
+	}
+	
+	/**
+	 * Return the first segment.
+	 * @see #getStartingNode()
+	 */
+	public LineSegment getStartingSegment() {
+		if (segments.isEmpty())
+			return null;
+		return segments.get(0);
+	}
+
+	@Override
+	public void visit(Visitor visitor) {
+		visitor.visit(this);
 	}
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 8)
+++ src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 8)
@@ -0,0 +1,107 @@
+
+package org.openstreetmap.josm.data.osm.visitor;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.data.osm.Key;
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Track;
+
+/**
+ * Able to create a name and an icon for each data element.
+ * 
+ * @author imi
+ */
+public class SelectionComponentVisitor extends Visitor {
+
+	/**
+	 * The name of this item.
+	 */
+	public String name;
+	/**
+	 * The icon of this item.
+	 */
+	public Icon icon;
+	
+	
+	/**
+	 * A key icon and the name of the key.
+	 */
+	@Override
+	public void visit(Key k) {
+		name = k.name;
+		icon = new ImageIcon("images/data/key.png");
+	}
+
+	/**
+	 * If the line segment has a key named "name", its value is displayed. 
+	 * Otherwise, if it has "id", this is used. If none of these available, 
+	 * "(x1,y1) -> (x2,y2)" is displayed with the nodes coordinates.
+	 */
+	@Override
+	public void visit(LineSegment ls) {
+		String name = getName(ls.keys);
+		if (name == null)
+			name = "("+ls.getStart().coor.lat+","+ls.getStart().coor.lon+") -> ("+ls.getEnd().coor.lat+","+ls.getEnd().coor.lon+")";
+			
+		this.name = name;
+		icon = new ImageIcon("images/data/linesegment.png");
+	}
+
+	/**
+	 * If the node has a name-key or id-key, this is displayed. If not, (lat,lon)
+	 * is displayed.
+	 */
+	@Override
+	public void visit(Node n) {
+		String name = getName(n.keys);
+		if (name == null)
+			name = "("+n.coor.lat+","+n.coor.lon+")";
+		
+		this.name = name;
+		icon = new ImageIcon("images/data/node.png");
+	}
+
+	/**
+	 * If the track has a name-key or id-key, this is displayed. If not, (x nodes)
+	 * is displayed with x beeing the number of nodes in the track.
+	 */
+	@Override
+	public void visit(Track t) {
+		String name = getName(t.keys);
+		if (name == null) {
+			Set<Node> nodes = new HashSet<Node>();
+			for (LineSegment ls : t.segments()) {
+				nodes.add(ls.getStart());
+				nodes.add(ls.getEnd());
+			}
+			name = "("+nodes.size()+" nodes)";
+		}
+		
+		this.name = name;
+		icon = new ImageIcon("images/data/track.png");
+	}
+
+	
+	/**
+	 * Try to read a name from the given properties.
+	 * @param keys The properties to search for a name. Can be <code>null</code>.
+	 * @return If a name could be found, return it here.
+	 */
+	public String getName(Map<Key, String> keys) {
+		String name = null;
+		if (keys != null) {
+			name = keys.get(Key.get("name"));
+			if (name == null)
+				name = keys.get(Key.get("id"));
+		}
+		return name;
+	}
+	
+}
Index: src/org/openstreetmap/josm/data/osm/visitor/Visitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/Visitor.java	(revision 8)
+++ src/org/openstreetmap/josm/data/osm/visitor/Visitor.java	(revision 8)
@@ -0,0 +1,19 @@
+package org.openstreetmap.josm.data.osm.visitor;
+
+import org.openstreetmap.josm.data.osm.Key;
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Track;
+
+/**
+ * Implementation of the visitor scheme. Every OsmPrimitive can be visited by
+ * several different visitors.
+ * 
+ * @author imi
+ */
+abstract public class Visitor {
+	public void visit(Node n) {}
+	public void visit(LineSegment ls) {}
+	public void visit(Track t) {}
+	public void visit(Key k) {}
+}
Index: src/org/openstreetmap/josm/gui/IconToggleButton.java
===================================================================
--- src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 7)
+++ src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 8)
@@ -43,5 +43,5 @@
 
 	public void propertyChange(PropertyChangeEvent evt) {
-		if (evt.getPropertyName() == "active")
+		if (evt.getPropertyName().equals("active"))
 			setSelected((Boolean)evt.getNewValue());
 	}
Index: src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapFrame.java	(revision 7)
+++ src/org/openstreetmap/josm/gui/MapFrame.java	(revision 8)
@@ -3,25 +3,14 @@
 import java.awt.BorderLayout;
 import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 
-import javax.swing.AbstractAction;
 import javax.swing.AbstractButton;
-import javax.swing.BorderFactory;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
-import javax.swing.ImageIcon;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JToggleButton;
 import javax.swing.JToolBar;
-import javax.swing.border.Border;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 
 import org.openstreetmap.josm.actions.mapmode.AddLineSegmentAction;
@@ -35,7 +24,7 @@
 import org.openstreetmap.josm.actions.mapmode.SelectionAction;
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
-import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.dialogs.PropertiesDialog;
+import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
 
 /**
@@ -46,64 +35,4 @@
  */
 public class MapFrame extends JPanel {
-
-	/**
-	 * Open the properties page
-	 * @author imi
-	 */
-	public class PropertiesAction extends AbstractAction {
-		private JDialog dlg;
-		public PropertiesAction() {
-			super("Properties", new ImageIcon("images/properties.png"));
-			putValue(MNEMONIC_KEY, KeyEvent.VK_P);
-		}
-		public void actionPerformed(ActionEvent e) {
-			if (dlg != null) {
-				dlg.setVisible(true);
-				dlg.requestFocus();
-				return;
-			}
-			dlg = new JDialog(Main.main, "Properties of "+Main.main.getNameOfLoadedMapFrame(), false);
-			final Border panelBorder = BorderFactory.createEmptyBorder(5,0,0,0);
-			Box panel = Box.createVerticalBox();
-
-			// making an array of all projections and the current one within
-			Projection[] allProjections = Preferences.allProjections.clone();
-			for (int i = 0; i < allProjections.length; ++i)
-				if (allProjections[i].getClass() == mapView.getProjection().getClass())
-					allProjections[i] = mapView.getProjection();
-			
-			// projection
-			Box projectionPanel = Box.createHorizontalBox();
-			projectionPanel.setBorder(panelBorder);
-			projectionPanel.add(new JLabel("Projection"));
-			final JComboBox projectionCombo = new JComboBox(allProjections);
-			projectionPanel.add(projectionCombo);
-			panel.add(projectionPanel);
-			final JPanel configurationPanel = new JPanel();
-			configurationPanel.setLayout(new BoxLayout(configurationPanel, BoxLayout.X_AXIS));
-			
-			// projections details
-			projectionCombo.addActionListener(new ActionListener(){
-				public void actionPerformed(ActionEvent e) {
-					configurationPanel.removeAll();
-					mapView.setProjection((Projection)projectionCombo.getSelectedItem());
-					JComponent panel = mapView.getProjection().getConfigurationPanel();
-					if (panel != null) {
-						panel.setBorder(panelBorder);
-						configurationPanel.add(panel);
-					}
-					dlg.pack();
-				}
-			});
-			panel.add(configurationPanel);
-			projectionCombo.setSelectedItem(mapView.getProjection());
-			
-			panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
-			dlg.setContentPane(panel);
-			dlg.pack();
-			dlg.setResizable(false);
-			dlg.setVisible(true);
-		}
-	}
 
 	/**
@@ -155,12 +84,24 @@
 		autoScaleButton.setText(null);
 		autoScaleButton.setSelected(mapView.isAutoScale());
-		mapView.addChangeListener(new ChangeListener(){
-			public void stateChanged(ChangeEvent e) {
-				autoScaleButton.setSelected(mapView.isAutoScale());
+		mapView.addPropertyChangeListener(new PropertyChangeListener(){
+			public void propertyChange(PropertyChangeEvent evt) {
+				if (evt.getPropertyName().equals("autoScale"))
+					autoScaleButton.setSelected(mapView.isAutoScale());
 			}
 		});
 
 		// properties
-		toolBarActions.add(new IconToggleButton(this, new PropertiesAction()));
+		toolBarActions.add(new IconToggleButton(this, new PropertiesDialog(this)));
+		
+		// selection dialog
+		SelectionListDialog selectionList = new SelectionListDialog(dataSet);
+		final IconToggleButton buttonSelection = new IconToggleButton(this, selectionList);
+		selectionList.addWindowListener(new WindowAdapter(){
+			@Override
+			public void windowClosing(WindowEvent e) {
+				buttonSelection.setSelected(false);
+			}
+		});
+		toolBarActions.add(buttonSelection);
 	}
 
Index: src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapView.java	(revision 7)
+++ src/org/openstreetmap/josm/gui/MapView.java	(revision 8)
@@ -1,5 +1,4 @@
 package org.openstreetmap.josm.gui;
 
-import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Point;
@@ -8,8 +7,4 @@
 import java.awt.event.ComponentListener;
 import java.awt.event.KeyEvent;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
 
 import javax.swing.AbstractAction;
@@ -27,4 +22,6 @@
 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;
 
 /**
@@ -81,4 +78,8 @@
 	public final DataSet dataSet;
 
+	/**
+	 * The drawing engine.
+	 */
+	private Engine engine;
 	
 	/**
@@ -94,4 +95,7 @@
 		// initialize the projection
 		setProjection(Main.pref.projection.clone());
+		
+		// initialize the engine
+		engine = new SimpleEngine(this);
 	}
 
@@ -136,5 +140,7 @@
 			projection.latlon2xy(p);
 		}
-		return new Point(toScreenX(p.x), toScreenY(p.y));
+		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);
 	}
 
@@ -179,7 +185,7 @@
 		
 		// pending line segments
-		for (LineSegment ls : dataSet.pendingLineSegments) {
-			Point A = getScreenPoint(ls.start.coor);
-			Point B = getScreenPoint(ls.end.coor);
+		for (LineSegment ls : dataSet.pendingLineSegments()) {
+			Point A = getScreenPoint(ls.getStart().coor);
+			Point B = getScreenPoint(ls.getEnd().coor);
 			double c = A.distanceSq(B);
 			double a = p.distanceSq(B);
@@ -194,8 +200,8 @@
 		// tracks & line segments
 		minDistanceSq = Double.MAX_VALUE;
-		for (Track t : dataSet.tracks) {
-			for (LineSegment ls : t.segments) {
-				Point A = getScreenPoint(ls.start.coor);
-				Point B = getScreenPoint(ls.end.coor);
+		for (Track t : dataSet.tracks()) {
+			for (LineSegment ls : t.segments()) {
+				Point A = getScreenPoint(ls.getStart().coor);
+				Point B = getScreenPoint(ls.getEnd().coor);
 				double c = A.distanceSq(B);
 				double a = p.distanceSq(B);
@@ -213,5 +219,4 @@
 		// TODO areas
 		
-		
 		return null; // nothing found
 	}
@@ -224,4 +229,8 @@
 	 */
 	public void zoomTo(GeoPoint newCenter, double scale) {
+		boolean oldAutoScale = autoScale;
+		GeoPoint oldCenter = center;
+		double oldScale = this.scale;
+		
 		autoScale = false;
 		center = newCenter.clone();
@@ -229,5 +238,10 @@
 		this.scale = scale;
 		recalculateCenterScale();
-		fireStateChanged(); // in case of autoScale, recalculate fired.
+
+		firePropertyChange("center", oldCenter, center);
+		if (oldAutoScale != autoScale)
+			firePropertyChange("autoScale", oldAutoScale, autoScale);
+		if (oldScale != scale)
+			firePropertyChange("scale", oldScale, scale);
 	}
 	
@@ -254,4 +268,9 @@
 				h = 20;
 			Bounds bounds = dataSet.getBoundsXY();
+			
+			boolean oldAutoScale = autoScale;
+			GeoPoint oldCenter = center;
+			double oldScale = this.scale;
+			
 			if (bounds == null) {
 				// no bounds means standard scale and center 
@@ -266,5 +285,10 @@
 				scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
 			}
-			fireStateChanged();
+
+			firePropertyChange("center", oldCenter, center);
+			if (oldAutoScale != autoScale)
+				firePropertyChange("autoScale", oldAutoScale, autoScale);
+			if (oldScale != scale)
+				firePropertyChange("scale", oldScale, scale);
 		}
 		repaint();
@@ -283,96 +307,15 @@
 	@Override
 	public void paint(Graphics g) {
-		// empty out everything
-		g.setColor(Color.BLACK);
-		g.fillRect(0,0,getWidth(),getHeight());
-
-		// draw tracks
-		if (dataSet.tracks != null)
-			for (Track track : dataSet.tracks)
-				for (LineSegment ls : track.segments) {
-					g.setColor(ls.selected || track.selected ? Color.WHITE : Color.GRAY);
-					g.drawLine(toScreenX(ls.start.coor.x), toScreenY(ls.start.coor.y),
-							toScreenX(ls.end.coor.x), toScreenY(ls.end.coor.y));
-				}
-
-		// draw pending line segments
-		for (LineSegment ls : dataSet.pendingLineSegments) {
-			g.setColor(ls.selected ? Color.WHITE : Color.LIGHT_GRAY);
-			g.drawLine(toScreenX(ls.start.coor.x), toScreenY(ls.start.coor.y),
-					toScreenX(ls.end.coor.x), toScreenY(ls.end.coor.y));
-		}
-
-		// draw nodes
-		Set<Integer> alreadyDrawn = new HashSet<Integer>();
-		int width = getWidth();
-		for (Node w : dataSet.nodes) {
-			g.setColor(w.selected ? Color.WHITE : Color.RED);
-			int x = toScreenX(w.coor.x);
-			int y = toScreenY(w.coor.y);
-			int size = 3;
-			if (alreadyDrawn.contains(y*width+x)) {
-				size = 7;
-				x -= 2;
-				y -= 2;
-			} else
-				alreadyDrawn.add(y*width+x);
-			g.drawArc(x, y, size, size, 0, 360);
-		}
-	}
-
-	/**
-	 * Return the x-screen coordinate for the given point.
-	 * @param x The X-position (easting) of the desired point
-	 * @return The screen coordinate for the point.
-	 */
-	public int toScreenX(double x) {
-		return (int)Math.round((x-center.x) / scale + getWidth()/2);
-	}
-
-	/**
-	 * Return the y-screen coordinate for the given point.
-	 * @param y The Y-position (northing) of the desired point
-	 * @return The screen coordinate for the point.
-	 */
-	public int toScreenY(double y) {
-		return (int)Math.round((center.y-y) / scale + getHeight()/2);
-	}
-
-
-	// Event handling functions and data
-	
-	/**
-	 * The event list with all state chaned listener
-	 */
-	List<ChangeListener> listener = new LinkedList<ChangeListener>();
-	/**
-	 * Add an event listener to the state changed event queue. If passed 
-	 * <code>null</code>, nothing happens.
-	 */
-	public final void addChangeListener(ChangeListener l) {
-		if (l != null)
-			listener.add(l);
-	}
-	/**
-	 * Remove an event listener from the event queue. If passed 
-	 * <code>null</code>, nothing happens.
-	 */
-	public final void removeChangeListener(ChangeListener l) {
-		listener.remove(l);
-	}
-	/**
-	 * Fires an ChangeEvent. Occours, when an non-data value changed, as example
-	 * the autoScale - state or the center. Is not fired, dataSet internal things
-	 * changes.
-	 */
-	public final void fireStateChanged() {
-		ChangeEvent e = null;
-		for(ChangeListener l : listener) {
-			if (e == null)
-				e = new ChangeEvent(this);
-			l.stateChanged(e);
-		}
-	}
-	
+		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);
+	}
+
 	/**
 	 * Notify from the projection, that something has changed.
@@ -393,9 +336,14 @@
 		if (projection == this.projection)
 			return;
+
+		Projection oldProjection = this.projection;
+		
 		if (this.projection != null)
 			this.projection.removeChangeListener(this);
 		this.projection = projection;
 		projection.addChangeListener(this);
+		
 		stateChanged(new ChangeEvent(this));
+		firePropertyChange("projection", oldProjection, projection);
 	}
 
@@ -421,5 +369,5 @@
 		if (this.autoScale != autoScale) {
 			this.autoScale = autoScale;
-			fireStateChanged();
+			firePropertyChange("autoScale", !autoScale, autoScale);
 		}
 	}
Index: src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 7)
+++ src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 8)
@@ -137,9 +137,6 @@
 	 */
 	public void mousePressed(MouseEvent e) {
-		if (e.getButton() == MouseEvent.BUTTON1) {
-			mousePosStart = e.getPoint();
-			mousePos = e.getPoint();
-			paintRect();
-		}
+		if (e.getButton() == MouseEvent.BUTTON1)
+			mousePosStart = mousePos = e.getPoint();
 	}
 
@@ -150,10 +147,8 @@
 		int buttonPressed = e.getModifiersEx() & (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK); 
 
+		
 		if (buttonPressed != 0) {
-			if (mousePosStart == null) {
-				mousePosStart = e.getPoint();
-				mousePos = e.getPoint();
-				paintRect();
-			}
+			if (mousePosStart == null)
+				mousePosStart = mousePos = e.getPoint();
 			paintRect();
 		}
@@ -176,4 +171,7 @@
 		if (e.getButton() != MouseEvent.BUTTON1)
 			return;
+		if (mousePos == null || mousePosStart == null)
+			return; // injected release from outside
+			
 		// disable the selection rect
 		paintRect();
@@ -195,4 +193,6 @@
 	 */
 	private void paintRect() {
+		if (mousePos == null || mousePosStart == null || mousePos == mousePosStart)
+			return;
 		Graphics g = mv.getGraphics();
 		g.setColor(Color.BLACK);
@@ -244,5 +244,5 @@
 	 */
 	public void propertyChange(PropertyChangeEvent evt) {
-		if (evt.getPropertyName() == "active" && !(Boolean)evt.getNewValue() && mousePosStart != null) {
+		if (evt.getPropertyName().equals("active") && !(Boolean)evt.getNewValue() && mousePosStart != null) {
 			paintRect();
 			mousePosStart = null;
@@ -277,12 +277,12 @@
 			
 			// pending line segments
-			for (LineSegment ls : mv.dataSet.pendingLineSegments)
+			for (LineSegment ls : mv.dataSet.pendingLineSegments())
 				if (rectangleContainLineSegment(r, alt, ls))
 					selection.add(ls);
 
 			// tracks
-			for (Track t : mv.dataSet.tracks) {
-				boolean wholeTrackSelected = t.segments.size() > 0;
-				for (LineSegment ls : t.segments)
+			for (Track t : mv.dataSet.tracks()) {
+				boolean wholeTrackSelected = !t.segments().isEmpty();
+				for (LineSegment ls : t.segments())
 					if (rectangleContainLineSegment(r, alt, ls))
 						selection.add(ls);
@@ -309,11 +309,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 = mv.getScreenPoint(ls.getStart().coor);
+			Point p2 = mv.getScreenPoint(ls.getEnd().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(mv.getScreenPoint(ls.getStart().coor))
+					&& r.contains(mv.getScreenPoint(ls.getEnd().coor)))
 				return true;
 		}
Index: src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 8)
+++ src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 8)
@@ -0,0 +1,77 @@
+package org.openstreetmap.josm.gui.dialogs;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.Border;
+
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+
+/**
+ * Open a Property dialog for the current visible map. When saving to own josm-
+ * data format, the properties are saved along.
+ * 
+ * @author imi
+ */
+public class PropertiesDialog extends ToggleDialog {
+
+	/**
+	 * 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.");
+		putValue(MNEMONIC_KEY, KeyEvent.VK_P);
+
+		final Border panelBorder = BorderFactory.createEmptyBorder(5,0,0,0);
+		Box panel = Box.createVerticalBox();
+
+		// making an array of all projections and the current one within
+		Projection[] allProjections = Preferences.allProjections.clone();
+		for (int i = 0; i < allProjections.length; ++i)
+			if (allProjections[i].getClass() == frame.mapView.getProjection().getClass())
+				allProjections[i] = frame.mapView.getProjection();
+		
+		// projection
+		Box projectionPanel = Box.createHorizontalBox();
+		projectionPanel.setBorder(panelBorder);
+		projectionPanel.add(new JLabel("Projection"));
+		final JComboBox projectionCombo = new JComboBox(allProjections);
+		projectionPanel.add(projectionCombo);
+		panel.add(projectionPanel);
+		final JPanel configurationPanel = new JPanel();
+		configurationPanel.setLayout(new BoxLayout(configurationPanel, BoxLayout.X_AXIS));
+		
+		// projections details
+		projectionCombo.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				configurationPanel.removeAll();
+				frame.mapView.setProjection((Projection)projectionCombo.getSelectedItem());
+				JComponent panel = frame.mapView.getProjection().getConfigurationPanel();
+				if (panel != null) {
+					panel.setBorder(panelBorder);
+					configurationPanel.add(panel);
+				}
+				pack();
+			}
+		});
+		panel.add(configurationPanel);
+		projectionCombo.setSelectedItem(frame.mapView.getProjection());
+		
+		panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+		setContentPane(panel);
+		pack();
+		setResizable(false);
+	}
+}
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 8)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 8)
@@ -0,0 +1,118 @@
+package org.openstreetmap.josm.gui.dialogs;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+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.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor;
+import org.openstreetmap.josm.gui.Main;
+
+/**
+ * A small tool dialog for displaying the current selection. The selection manager
+ * respects clicks into the selection list. Ctrl-click will remove entries from
+ * the list while single click will make the clicked entry the only selection.
+ * 
+ * @author imi
+ */
+public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
+
+	/**
+	 * The selection's list data.
+	 */
+	private final DefaultListModel list = new DefaultListModel();
+	/**
+	 * The display list.
+	 */
+	private JList displaylist = new JList(list);
+	/**
+	 * The dataset, all selections are part of.
+	 */
+	private final DataSet dataSet;
+	
+	/**
+	 * Create a SelectionList dialog.
+	 * @param dataSet The dataset this dialog operates on.
+	 */
+	public SelectionListDialog(DataSet dataSet) {
+		super("Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window.");
+		this.dataSet = dataSet;
+		setLayout(new BorderLayout());
+		setSize(300,400);
+		displaylist.setCellRenderer(new DefaultListCellRenderer(){
+			private SelectionComponentVisitor visitor = new SelectionComponentVisitor();
+			@Override
+			public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+				Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+				if (c instanceof JLabel && value != null) {
+					((OsmPrimitive)value).visit(visitor);
+					((JLabel)c).setText(visitor.name);
+					((JLabel)c).setIcon(visitor.icon);
+				}
+				return c;
+			}
+		});
+		displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+
+		getContentPane().add(new JScrollPane(displaylist), BorderLayout.CENTER);
+
+		JButton button = new JButton("Select", new ImageIcon("images/mapmode/selection.png"));
+		button.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				updateMap();
+			}
+		});
+		getContentPane().add(button, BorderLayout.SOUTH);
+
+		selectionChanged(dataSet.getSelected());
+	}
+
+	@Override
+	public void setVisible(boolean b) {
+		if (b) {
+			dataSet.addSelectionChangedListener(this);
+			selectionChanged(dataSet.getSelected());
+		} else
+			dataSet.removeSelectionChangedListener(this);
+		super.setVisible(b);
+	}
+
+
+
+	/**
+	 * Called when the selection in the dataset changed.
+	 * @param newSelection The new selection array.
+	 */
+	public void selectionChanged(Collection<OsmPrimitive> newSelection) {
+		list.removeAllElements();
+		list.setSize(newSelection.size());
+		int i = 0;
+		for (OsmPrimitive osm : newSelection)
+			list.setElementAt(osm, i++);
+	}
+
+	/**
+	 * Sets the selection of the map to the current selected items.
+	 */
+	public void updateMap() {
+		dataSet.clearSelection();
+		for (int i = 0; i < list.getSize(); ++i)
+			if (displaylist.isSelectedIndex(i))
+				((OsmPrimitive)list.get(i)).setSelected(true, dataSet);
+		Main.main.getMapFrame().repaint();
+	}
+}
Index: src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 8)
+++ src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 8)
@@ -0,0 +1,56 @@
+package org.openstreetmap.josm.gui.dialogs;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.AbstractButton;
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JDialog;
+import javax.swing.KeyStroke;
+
+import org.openstreetmap.josm.gui.Main;
+
+/**
+ * This class is a toggle dialog that can be turned on and off. It is attached
+ * to a ButtonModel.
+ * 
+ * @author imi
+ */
+public class ToggleDialog extends JDialog implements Action {
+
+	/**
+	 * Create a new ToggleDialog.
+	 * @param title The title of the dialog.
+	 */
+	public ToggleDialog(String title, String name, String iconName, int mnemonic, String tooltip) {
+		super(Main.main, title, false);
+		putValue(SMALL_ICON, new ImageIcon("images/dialogs/"+iconName+".png"));
+		putValue(NAME, name);
+		putValue(MNEMONIC_KEY, mnemonic);
+		putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E,0));
+		putValue(LONG_DESCRIPTION, "Open a selection list window.");
+	}
+
+	/**
+	 * Show this if not shown. Else request the focus.
+	 */
+	public void actionPerformed(ActionEvent e) {
+		boolean show = !isVisible();
+		if (e.getSource() instanceof AbstractButton)
+			show = ((AbstractButton)e.getSource()).isSelected();
+		setVisible(show);
+	}
+
+	// to satisfy Action interface
+
+	private Map<String, Object> properties = new HashMap<String, Object>();
+	public Object getValue(String key) {
+		return properties.get(key);
+	}
+	public void putValue(String key, Object value) {
+		properties.put(key, value);
+	}
+}
Index: src/org/openstreetmap/josm/gui/engine/Engine.java
===================================================================
--- src/org/openstreetmap/josm/gui/engine/Engine.java	(revision 8)
+++ src/org/openstreetmap/josm/gui/engine/Engine.java	(revision 8)
@@ -0,0 +1,84 @@
+package org.openstreetmap.josm.gui.engine;
+
+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;
+
+/**
+ * Subclasses of Engine are able to draw map data on the screen. The layout and
+ * colors depend only on the engine used, but it may have an configuration panel.
+ *
+ * @author imi
+ */
+abstract public class Engine implements PropertyChangeListener {
+
+	/**
+	 * 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
+	 * sequence.
+	 */
+	protected Graphics g;
+	/**
+	 * The mapView, this engine was created for.
+	 */
+	protected final 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);
+	}
+	
+	/**
+	 * Called to initialize the Engine for a new drawing sequence.
+	 * @param g
+	 */
+	public void init(Graphics g) {
+		this.g = g;
+	}
+
+	/**
+	 * Draw the background. The coordinates are given as hint (e.g. to draw
+	 * an background image).
+	 */
+	abstract public void drawBackground(GeoPoint ul, GeoPoint lr);
+
+	/**
+	 * Draw the node.
+	 */
+	abstract public void drawNode(Node n);
+	
+	/**
+	 * Draw the track.
+	 */
+	abstract public void drawTrack(Track t);
+	
+	/**
+	 * Draw the pending line segment. Non-pending line segments must be drawn
+	 * within drawTrack.
+	 */
+	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/SimpleEngine.java
===================================================================
--- src/org/openstreetmap/josm/gui/engine/SimpleEngine.java	(revision 8)
+++ src/org/openstreetmap/josm/gui/engine/SimpleEngine.java	(revision 8)
@@ -0,0 +1,128 @@
+package org.openstreetmap.josm.gui.engine;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.util.Collection;
+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;
+
+/**
+ * A simple graphic engine that draws rather symbolic images to easy identify
+ * the different types on the screen. This is optimized for expert editors.
+ * 
+ * @author imi
+ */
+public class SimpleEngine extends Engine {
+
+	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());
+	}
+
+	/**
+	 * Draw a small rectangle. 
+	 * 
+	 * - White if selected (as always)
+	 * - Yellow, if not used by any tracks or areas.
+	 * - Green, if only used by pending line segments.
+	 * - Darkblue, if used in tracks but are only as inbound node. Inbound are
+	 *   all nodes, that have only line segments of the same track and
+	 *   at least two different line segments attached.
+	 * - Red otherwise (means, this is a dead end or is part of more than
+	 *   one track).
+	 * 
+	 * @param n The node to draw.
+	 */
+	@Override
+	public void drawNode(Node n) {
+		if (n.isSelected()) {
+			drawNode(n, Color.WHITE); // selected
+			return;
+		}
+
+		Collection<LineSegment> lineSegments = n.getParentSegments();
+		if (lineSegments.isEmpty()) {
+			drawNode(n, Color.YELLOW); // single waypoint only
+			return;
+		}
+		
+		HashSet<Track> tracks = new HashSet<Track>();
+		for (LineSegment ls : lineSegments)
+			tracks.addAll(ls.getParents());
+		if (tracks.isEmpty()) {
+			drawNode(n, Color.GREEN); // pending line
+			return;
+		}
+		if (tracks.size() > 1) {
+			drawNode(n, Color.RED); // more than one track
+			return;
+		}
+		int segmentUsed = 0;
+		for (LineSegment ls : tracks.iterator().next().segments())
+			if (n == ls.getStart() || n == ls.getEnd())
+				++segmentUsed;
+		drawNode(n, segmentUsed > 1 ? darkblue : Color.RED);
+	}
+
+	/**
+	 * Draw a darkblue line for all line segments.
+	 * @param t The track to draw.
+	 */
+	@Override
+	public void drawTrack(Track t) {
+		for (LineSegment ls : t.segments())
+			drawLineSegment(ls, t.isSelected() ? Color.WHITE : darkblue);
+	}
+
+
+	/**
+	 * Draw the pending line as darkgreen line.
+	 * @param ls The line segment to draw.
+	 */
+	@Override
+	public void drawPendingLineSegment(LineSegment ls) {
+		drawLineSegment(ls, darkgreen);
+	}
+
+
+	/**
+	 * 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);
+	}
+
+	/**
+	 * Drat the node as small rectangle with the given color.
+	 *
+	 * @param n		The node to draw.
+	 * @param color The color of the node.
+	 */
+	private void drawNode(Node n, Color color) {
+		Point p = mv.getScreenPoint(n.coor);
+		g.setColor(color);
+		g.drawRect(p.x-1, p.y-1, 2, 2);
+	}
+}
+
Index: src/org/openstreetmap/josm/io/GpxReader.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxReader.java	(revision 7)
+++ src/org/openstreetmap/josm/io/GpxReader.java	(revision 8)
@@ -3,5 +3,4 @@
 import java.io.IOException;
 import java.io.Reader;
-import java.util.ArrayList;
 
 import org.jdom.Element;
@@ -46,5 +45,5 @@
 	}
 
-	
+
 	/**
 	 * Read one node (waypoint).
@@ -83,12 +82,10 @@
 					else {
 						LineSegment lineSegment = new LineSegment(start, node);
-						track.segments.add(lineSegment);
+						track.add(lineSegment);
 						start = null;
 					}
 				}
 			}
-			if (data.tracks == null)
-				data.tracks = new ArrayList<Track>();
-			data.tracks.add(track);
+			data.addTrack(track);
 		}
 
