Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 154)
+++ /src/org/openstreetmap/josm/Main.java	(revision 155)
@@ -8,4 +8,5 @@
 import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
 import java.io.File;
 import java.net.URI;
@@ -22,4 +23,5 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
+import javax.swing.JComponent;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
@@ -28,5 +30,5 @@
 import javax.swing.JSeparator;
 import javax.swing.JToolBar;
-import javax.swing.SwingUtilities;
+import javax.swing.KeyStroke;
 import javax.swing.UIManager;
 
@@ -37,4 +39,5 @@
 import org.openstreetmap.josm.actions.ExternalToolsAction;
 import org.openstreetmap.josm.actions.GpxExportAction;
+import org.openstreetmap.josm.actions.HelpAction;
 import org.openstreetmap.josm.actions.OpenAction;
 import org.openstreetmap.josm.actions.PreferencesAction;
@@ -104,4 +107,8 @@
 	 */
 	public static PleaseWaitDialog pleaseWaitDlg;
+	/**
+	 * The access to the help subsystem
+	 */
+	public HelpAction help;
 
 
@@ -192,4 +199,5 @@
 		final Action exitAction = new ExitAction();
 		final Action preferencesAction = new PreferencesAction();
+		help = new HelpAction();
 		final Action aboutAction = new AboutAction();
 
@@ -235,7 +243,8 @@
 		final JMenu helpMenu = new JMenu(tr("Help"));
 		helpMenu.setMnemonic('H');
+		helpMenu.add(help);
+		helpMenu.add(aboutAction);
+		helpMenu.addSeparator();
 		helpMenu.add(annotationTesterAction);
-		helpMenu.addSeparator();
-		helpMenu.add(aboutAction);
 		mainMenu.add(helpMenu);
 
@@ -256,8 +265,16 @@
 		contentPane.add(toolBar, BorderLayout.NORTH);
 
+        contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "Help");
+        contentPane.getActionMap().put("Help", help);
+
 		contentPane.updateUI();
-
-		// Plugins
-		if (Main.pref.hasKey("plugins")) {
+	}
+
+	/**
+	 * Load all plugins specified in preferences. Has to be called after the complete
+	 * GUI has been set up. (post-constructor)
+	 */
+	public void loadPlugins() {
+	    if (Main.pref.hasKey("plugins")) {
 			for (String pluginName : Main.pref.get("plugins").split(",")) {
 				try {
@@ -273,9 +290,5 @@
 			}
 		}
-
-		SwingUtilities.updateComponentTreeUI(parent);
-		for (DownloadTask task : downloadAction.downloadTasks)
-			task.getCheckBox().updateUI();
-	}
+    }
 
 	/**
Index: /src/org/openstreetmap/josm/actions/AutoScaleAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 154)
+++ /src/org/openstreetmap/josm/actions/AutoScaleAction.java	(revision 155)
@@ -27,5 +27,5 @@
 
 	private static final String[] modes = {
-		marktr("data"), 
+		marktr("data"),
 		marktr("selection"),
 		marktr("layer"),
@@ -39,4 +39,6 @@
 		public Action(String mode) {
 			super(tr("Auto Scale: {0}", tr(mode)), ImageProvider.get("dialogs/autoscale/"+mode));
+			String modeHelp = Character.toUpperCase(mode.charAt(0))+mode.substring(1);
+			putValue("help", "Action/AutoScale/"+modeHelp);
 			putValue(SHORT_DESCRIPTION, tr("Auto zoom the view (to {0}. Disabled if the view is moved)", tr(mode)));
 			this.mode = mode;
@@ -73,5 +75,5 @@
 		} else if (mode.equals("layer"))
 			mapFrame.mapView.getActiveLayer().visitBoundingBox(v);
-		else if (mode.equals("selection") || mode.equals("conflict")) { 
+		else if (mode.equals("selection") || mode.equals("conflict")) {
 			Collection<OsmPrimitive> sel = mode.equals("selection") ? Main.ds.getSelected() : mapFrame.conflictDialog.conflicts.keySet();
 			for (OsmPrimitive osm : sel)
Index: /src/org/openstreetmap/josm/actions/HelpAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/HelpAction.java	(revision 155)
+++ /src/org/openstreetmap/josm/actions/HelpAction.java	(revision 155)
@@ -0,0 +1,181 @@
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.AbstractButton;
+import javax.swing.Action;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.OpenBrowser;
+import org.openstreetmap.josm.tools.WikiReader;
+
+/**
+ * Open a help browser and displays lightweight online help.
+ *
+ * @author imi
+ */
+public class HelpAction extends AbstractAction {
+
+	public interface Helpful {
+		String helpTopic();
+    }
+
+	private JFrame helpBrowser = new JFrame("JOSM Online Help");
+	private String baseurl = Main.pref.get("help.baseurl", "http://josm.eigenheimstrasse.de");
+	private JEditorPane help = new JEditorPane();
+	private WikiReader reader = new WikiReader(baseurl);
+	private String url;
+
+	public HelpAction() {
+		super(tr("Help"), ImageProvider.get("help"));
+		help.setEditable(false);
+		help.addHyperlinkListener(new HyperlinkListener(){
+			public void hyperlinkUpdate(HyperlinkEvent e) {
+				if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED)
+					return;
+				if (e.getURL() == null)
+					help.setText("<html>404 not found</html>");
+				else if (e.getURL().toString().startsWith(WikiReader.JOSM_EXTERN))
+					OpenBrowser.displayUrl("http://"+e.getURL().toString().substring(WikiReader.JOSM_EXTERN.length())+"?action=edit");
+				else
+					setHelpUrl(e.getURL().toString());
+			}
+		});
+		help.setContentType("text/html");
+
+		JPanel p = new JPanel(new BorderLayout());
+		helpBrowser.setContentPane(p);
+
+		p.add(new JScrollPane(help), BorderLayout.CENTER);
+		String[] bounds = Main.pref.get("help.window.bounds", "0,0,800,600").split(",");
+		helpBrowser.setBounds(
+				Integer.parseInt(bounds[0]),
+				Integer.parseInt(bounds[1]),
+				Integer.parseInt(bounds[2]),
+				Integer.parseInt(bounds[3]));
+
+		JPanel buttons = new JPanel();
+		p.add(buttons, BorderLayout.SOUTH);
+		createButton(buttons, "Open in Browser");
+		createButton(buttons, "Edit");
+		createButton(buttons, "Reload");
+
+		helpBrowser.addWindowListener(new WindowAdapter(){
+			@Override public void windowClosing(WindowEvent e) {
+				closeHelp();
+			}
+		});
+
+        help.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Close");
+        help.getActionMap().put("Close", new AbstractAction(){
+			public void actionPerformed(ActionEvent e) {
+				closeHelp();
+            }
+        });
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		if ("Open in Browser".equals(e.getActionCommand())) {
+			OpenBrowser.displayUrl(url);
+		} else if ("Edit".equals(e.getActionCommand())) {
+			if (!url.startsWith(baseurl)) {
+				JOptionPane.showMessageDialog(Main.parent, tr("Can only edit help pages from JOSM Online Help"));
+				return;
+			}
+			OpenBrowser.displayUrl(url+"?action=edit");
+		} else if ("Reload".equals(e.getActionCommand())) {
+			setHelpUrl(url);
+		} else if (e.getActionCommand() == null) {
+			String topic = null;
+			Point mouse = Main.parent.getMousePosition();
+			if (mouse != null)
+				topic = contextSensitiveHelp(SwingUtilities.getDeepestComponentAt(Main.parent, mouse.x, mouse.y));
+			if (topic == null) {
+				helpBrowser.setVisible(false);
+				setHelpUrl(baseurl+"/wiki/Help");
+			} else
+				help(topic);
+		} else {
+			helpBrowser.setVisible(false);
+			setHelpUrl(baseurl+"/wiki/Help");
+		}
+	}
+
+	/**
+	 * @return The topic of the help. <code>null</code> for "don't know"
+	 */
+	private String contextSensitiveHelp(Object c) {
+		if (c instanceof Helpful)
+			return ((Helpful)c).helpTopic();
+		if (c instanceof JMenu)
+			return "Menu/"+((JMenu)c).getText();
+		if (c instanceof AbstractButton) {
+			AbstractButton b = (AbstractButton)c;
+			if (b.getClientProperty("help") != null)
+				return (String)b.getClientProperty("help");
+			return contextSensitiveHelp(((AbstractButton)c).getAction());
+		}
+		if (c instanceof Action)
+			return (String)((Action)c).getValue("help");
+		if (c instanceof Component)
+			return contextSensitiveHelp(((Component)c).getParent());
+		return null;
+    }
+
+	/**
+	 * Displays the help (or browse on the already open help) to the online page
+	 * with the given help topic. Use this for larger help descriptions.
+	 */
+	public void help(String topic) {
+		helpBrowser.setVisible(false);
+		setHelpUrl(baseurl+"/wiki/Help/"+topic);
+	}
+
+	/**
+	 * Set the content of the help window to a specific text (in html format)
+	 * @param url The url this content is the representation of
+	 */
+	public void setHelpUrl(String url) {
+		this.url = url;
+		help.setText(reader.read(url));
+		helpBrowser.setVisible(true);
+	}
+
+	/**
+	 * Closes the help window
+	 */
+	public void closeHelp() {
+		String bounds = helpBrowser.getX()+","+helpBrowser.getY()+","+helpBrowser.getWidth()+","+helpBrowser.getHeight();
+		Main.pref.put("help.window.bounds", bounds);
+		helpBrowser.setVisible(false);
+	}
+
+	private void createButton(JPanel buttons, String name) {
+		JButton b = new JButton(tr(name));
+		b.setActionCommand(name);
+		b.addActionListener(this);
+		buttons.add(b);
+	}
+}
Index: /src/org/openstreetmap/josm/actions/JosmAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/JosmAction.java	(revision 154)
+++ /src/org/openstreetmap/josm/actions/JosmAction.java	(revision 155)
@@ -18,5 +18,5 @@
 	/**
 	 * Construct the action as menu action entry.
-	 * 
+	 *
 	 * @param name		Name of the action (entry name in menu)
 	 * @param iconName	Name of the icon (without extension)
@@ -33,7 +33,6 @@
 	public JosmAction(String name, String iconName, String tooltip, int shortCut, int modifier) {
 		super(name, ImageProvider.get(iconName));
+		setHelpId();
 		putValue(SHORT_DESCRIPTION, "<html>"+tooltip+" <font size='-2'>"+ShortCutLabel.name(shortCut, modifier)+"</font>&nbsp;</html>");
-		//Main.panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortCut, name);
-        //Main.panel.getActionMap().put(name, this);
         Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(shortCut, modifier), name);
         Main.contentPane.getActionMap().put(name, this);
@@ -41,4 +40,13 @@
 
 	public JosmAction() {
+		setHelpId();
+	}
+
+
+	private void setHelpId() {
+		String helpId = "Action/"+getClass().getName().substring(getClass().getName().lastIndexOf('.')+1);
+		if (helpId.endsWith("Action"))
+			helpId = helpId.substring(0, helpId.length()-6);
+		putValue("help", helpId);
 	}
 }
Index: /src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 154)
+++ /src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 155)
@@ -29,8 +29,8 @@
  * This mode adds a new node to the dataset. The user clicks on a place to add
  * and there is it. Nothing more, nothing less.
- * 
- * Newly created nodes are selected. Shift modifier does not cancel the old 
+ *
+ * Newly created nodes are selected. Shift modifier does not cancel the old
  * selection as usual.
- * 
+ *
  * @author imi
  *
@@ -44,4 +44,5 @@
 		public AddNodeGroup(MapFrame mf) {
 			super(KeyEvent.VK_N,0);
+			putValue("help", "Action/AddNode");
 			actions.add(new AddNodeAction(mf,tr("Add node"), Mode.node, tr("Add a new node to the map")));
 			actions.add(new AddNodeAction(mf, tr("Add node into segment"), Mode.nodesegment,tr( "Add a node into an existing segment")));
@@ -53,4 +54,5 @@
 		super(name, "node/"+mode, desc, mapFrame, ImageProvider.getCursor("crosshair", "node"));
 		this.mode = mode;
+		putValue("help", "Action/AddNode/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1));
 	}
 
@@ -70,5 +72,5 @@
 	 * If user clicked with the left button, add a node at the current mouse
 	 * position.
-	 * 
+	 *
 	 * If in nodesegment mode, add the node to the line segment by splitting the
 	 * segment. The new created segment will be inserted in every way the segment
@@ -102,5 +104,5 @@
 				n.coor = Main.proj.eastNorth2latlon(n.eastNorth);
 			}
-			
+
 			Collection<Command> cmds = new LinkedList<Command>();
 			cmds.add(c);
Index: /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 154)
+++ /src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 155)
@@ -24,11 +24,11 @@
 /**
  * This MapMode enables the user to easy make a selection of different objects.
- * 
+ *
  * The selected objects are drawn in a different style.
- * 
- * Holding and dragging the left mouse button draws an selection rectangle. 
- * When releasing the left mouse button, all objects within the rectangle get 
- * selected. 
- * 
+ *
+ * Holding and dragging the left mouse button draws an selection rectangle.
+ * When releasing the left mouse button, all objects within the rectangle get
+ * selected.
+ *
  * When releasing the left mouse button while the right mouse button pressed,
  * nothing happens (the selection rectangle will be cleared, however).
@@ -36,12 +36,12 @@
  * When releasing the mouse button and one of the following keys was hold:
  *
- * If Alt key was hold, select all objects that are touched by the 
- * selection rectangle. If the Alt key was not hold, select only those objects 
- * completly within (e.g. for ways mean: only if all nodes of the way are 
- * within).  
+ * If Alt key was hold, select all objects that are touched by the
+ * selection rectangle. If the Alt key was not hold, select only those objects
+ * completly within (e.g. for ways mean: only if all nodes of the way are
+ * within).
  *
  * If Shift key was hold, the objects are added to the current selection. If
  * Shift key wasn't hold, the current selection get replaced.
- * 
+ *
  * If Ctrl key was hold, remove all objects under the current rectangle from
  * the active selection (if there were any). Nothing is added to the current
@@ -51,11 +51,11 @@
  * If both are pressed, nothing happens when releasing the mouse button.
  *
- * The user can also only click on the map. All total movements of 2 or less 
+ * The user can also only click on the map. All total movements of 2 or less
  * pixel are considered "only click". If that happens, the nearest Node will
  * be selected if there is any within 10 pixel range. If there is no Node within
  * 10 pixel, the nearest Segment (or Street, if user hold down the Alt-Key)
  * within 10 pixel range is selected. If there is no Segment within 10 pixel
- * and the user clicked in or 10 pixel away from an area, this area is selected. 
- * If there is even no area, nothing is selected. Shift and Ctrl key applies to 
+ * and the user clicked in or 10 pixel away from an area, this area is selected.
+ * If there is even no area, nothing is selected. Shift and Ctrl key applies to
  * this as usual. For more, @see MapView#getNearest(Point, boolean)
  *
@@ -70,4 +70,5 @@
 		public Group(MapFrame mf) {
 			super(KeyEvent.VK_S,0);
+			putValue("help", "Action/Selection");
 			actions.add(new SelectionAction(mf, tr("Selection"), Mode.select, tr("Select objects by dragging or clicking.")));
 			actions.add(new SelectionAction(mf, tr("Straight line"), Mode.straight, tr("Select objects in a straight line.")));
@@ -96,4 +97,5 @@
 		super(name, "selection/"+mode, desc, mapFrame, ImageProvider.getCursor("normal", "selection"));
 		this.mode = mode;
+		putValue("help", "Action/Selection/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1));
 		this.selectionManager = new SelectionManager(this, false, mapFrame.mapView);
 	}
@@ -149,5 +151,5 @@
 			curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
 		else
-			curSel = Main.ds.getSelected(); 
+			curSel = Main.ds.getSelected();
 
 		Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
@@ -196,5 +198,5 @@
 
 	/**
-	 * Get the shortest path by stepping through the node with a common segment with start 
+	 * Get the shortest path by stepping through the node with a common segment with start
 	 * and nearest to the end (greedy algorithm).
 	 */
Index: /src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MainApplication.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/MainApplication.java	(revision 155)
@@ -172,4 +172,5 @@
 		Main.parent = mainFrame;
 		Main main = new MainApplication(mainFrame);
+		main.loadPlugins();
 
 		mainFrame.setVisible(true);
Index: /src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 155)
@@ -29,5 +29,5 @@
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
 import org.openstreetmap.josm.gui.dialogs.HistoryDialog;
-import org.openstreetmap.josm.gui.dialogs.LayerList;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.PropertiesDialog;
 import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
@@ -118,5 +118,5 @@
 		toggleDialogs.setLayout(new BoxLayout(toggleDialogs, BoxLayout.Y_AXIS));
 
-		addIconToggle(toggleDialogs, new LayerList(this));
+		addIconToggle(toggleDialogs, new LayerListDialog(this));
 		addIconToggle(toggleDialogs, new PropertiesDialog(this));
 		addIconToggle(toggleDialogs, new HistoryDialog());
Index: /src/org/openstreetmap/josm/gui/MapScaler.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapScaler.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/MapScaler.java	(revision 155)
@@ -7,7 +7,8 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.tools.ColorHelper;
 
-public class MapScaler extends JComponent {
+public class MapScaler extends JComponent implements Helpful {
 
 	private final MapView mv;
@@ -29,3 +30,7 @@
 		g.drawString(text, (int)(50-bound.getWidth()/2), 23);
     }
+
+	public String helpTopic() {
+	    return "MapView/Scaler";
+    }
 }
Index: /src/org/openstreetmap/josm/gui/MapSlider.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapSlider.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/MapSlider.java	(revision 155)
@@ -10,7 +10,8 @@
 import javax.swing.event.ChangeListener;
 
+import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.EastNorth;
 
-class MapSlider extends JSlider implements PropertyChangeListener, ChangeListener {
+class MapSlider extends JSlider implements PropertyChangeListener, ChangeListener, Helpful {
 	
     private final MapView mv;
@@ -49,3 +50,7 @@
 			this.mv.zoomTo(this.mv.center, pos.north()*2/(this.mv.getHeight()-20));
 	}
+
+	public String helpTopic() {
+	    return "MapView/Slider";
+    }
 }
Index: /src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapStatus.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/MapStatus.java	(revision 155)
@@ -27,4 +27,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -36,17 +37,17 @@
  * It keeps a status line below the map up to date and displays some tooltip
  * information if the user hold the mouse long enough at some point.
- * 
+ *
  * All this is done in background to not disturb other processes.
- * 
+ *
  * The background thread does not alter any data of the map (read only thread).
  * Also it is rather fail safe. In case of some error in the data, it just do
  * nothing instead of whining and complaining.
- * 
+ *
  * @author imi
  */
-public class MapStatus extends JPanel {
-
-	/**
-	 * The MapView this status belongs. 
+public class MapStatus extends JPanel implements Helpful {
+
+	/**
+	 * The MapView this status belongs.
 	 */
 	final MapView mv;
@@ -63,5 +64,5 @@
 	 * The collector class that waits for notification and then update
 	 * the display objects.
-	 * 
+	 *
 	 * @author imi
 	 */
@@ -107,5 +108,5 @@
 				// This try/catch is a hack to stop the flooding bug reports about this.
 				// The exception needed to handle with in the first place, means that this
-				// access to the data need to be restarted, if the main thread modifies 
+				// access to the data need to be restarted, if the main thread modifies
 				// the data.
 				try {
@@ -242,3 +243,7 @@
 		}, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
 	}
+
+	public String helpTopic() {
+	    return "Statusline";
+    }
 }
Index: /src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- /src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 155)
@@ -8,4 +8,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -19,8 +20,8 @@
  * An component that can be navigated by a mapmover. Used as map view and for the
  * zoomer in the download dialog.
- * 
+ *
  * @author imi
  */
-public class NavigatableComponent extends JComponent {
+public class NavigatableComponent extends JComponent implements Helpful {
 
 
@@ -29,5 +30,5 @@
 	/**
 	 * The scale factor in x or y-units per pixel. This means, if scale = 10,
-	 * every physical pixel on screen are 10 x or 10 y units in the 
+	 * every physical pixel on screen are 10 x or 10 y units in the
 	 * northing/easting space of the projection.
 	 */
@@ -53,5 +54,5 @@
 		return 32;
 	}
-	
+
 	/**
 	 * Return the current scale value.
@@ -73,5 +74,5 @@
 	 * @param x X-Pixelposition to get coordinate from
 	 * @param y Y-Pixelposition to get coordinate from
-	 * 
+	 *
 	 * @return Geographic coordinates from a specific pixel coordination
 	 * 		on the screen.
@@ -86,5 +87,5 @@
 	 * @param x X-Pixelposition to get coordinate from
 	 * @param y Y-Pixelposition to get coordinate from
-	 * 
+	 *
 	 * @return Geographic unprojected coordinates from a specific pixel coordination
 	 * 		on the screen.
@@ -164,5 +165,5 @@
 					minPrimitive = w;
 				}
-			}			
+			}
 		}
 		return minPrimitive;
@@ -195,20 +196,20 @@
 	/**
 	 * Return the object, that is nearest to the given screen point.
-	 * 
+	 *
 	 * First, a node will be searched. If a node within 10 pixel is found, the
 	 * nearest node is returned.
-	 * 
+	 *
 	 * If no node is found, search for pending segments.
-	 * 
-	 * If no such segment is found, and a non-pending segment is 
-	 * within 10 pixel to p, this segment is returned, except when 
-	 * <code>wholeWay</code> is <code>true</code>, in which case the 
+	 *
+	 * If no such segment is found, and a non-pending segment is
+	 * within 10 pixel to p, this segment is returned, except when
+	 * <code>wholeWay</code> is <code>true</code>, in which case the
 	 * corresponding Way is returned.
-	 * 
+	 *
 	 * If no segment is found and the point is within an area, return that
 	 * area.
-	 * 
+	 *
 	 * If no area is found, return <code>null</code>.
-	 * 
+	 *
 	 * @param p				 The point on screen.
 	 * @param segmentInsteadWay Whether the segment (true) or only the whole
@@ -226,17 +227,17 @@
 
 	/**
-	 * @return A list of all objects that are nearest to 
-	 * the mouse. To do this, first the nearest object is 
+	 * @return A list of all objects that are nearest to
+	 * the mouse. To do this, first the nearest object is
 	 * determined.
-	 * 
+	 *
 	 * If its a node, return all segments and
 	 * streets the node is part of, as well as all nodes
 	 * (with their segments and ways) with the same
 	 * location.
-	 * 
-	 * If its a segment, return all ways this segment 
+	 *
+	 * If its a segment, return all ways this segment
 	 * belongs to as well as all segments that are between
 	 * the same nodes (in both direction) with all their ways.
-	 * 
+	 *
 	 * @return A collection of all items or <code>null</code>
 	 * 		if no item under or near the point. The returned
@@ -258,5 +259,5 @@
 				if (!ls.deleted && !ls.incomplete && (c.contains(ls.from) || c.contains(ls.to)))
 					c.add(ls);
-		} 
+		}
 		if (osm instanceof Segment) {
 			Segment line = (Segment)osm;
@@ -286,3 +287,8 @@
 		return Main.proj;
 	}
+
+	public String helpTopic() {
+	    String n = getClass().getName();
+	    return n.substring(n.lastIndexOf('.')+1);
+    }
 }
Index: /src/org/openstreetmap/josm/gui/WorldChooser.java
===================================================================
--- /src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 155)
@@ -44,5 +44,5 @@
 	 */
 	private double scaleMax;
-	
+
 	/**
 	 * Mark this rectangle (lat/lon values) when painting.
@@ -51,5 +51,5 @@
 
 	private Projection projection;
-	
+
 	/**
 	 * Create the chooser component.
Index: /src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/dialogs/ConflictDialog.java	(revision 155)
@@ -68,4 +68,5 @@
 			}
 		});
+		button.putClientProperty("help", "Dialog/Conflict/Resolve");
 		buttonPanel.add(button);
 
@@ -80,4 +81,5 @@
 			}
 		});
+		button.putClientProperty("help", "Dialog/Conflict/Select");
 		buttonPanel.add(button);
 
@@ -132,5 +134,5 @@
 				model.addElement(osm);
 	}
-	
+
 	public final void add(Map<OsmPrimitive, OsmPrimitive> conflicts) {
 		this.conflicts.putAll(conflicts);
@@ -139,5 +141,5 @@
 
 	/**
-	 * Paint all conflicts that can be expressed on the main window. 
+	 * Paint all conflicts that can be expressed on the main window.
 	 */
 	public void paintConflicts(final Graphics g, final NavigatableComponent nc) {
Index: /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 155)
@@ -38,12 +38,12 @@
 /**
  * History dialog works like follows:
- * 
+ *
  * There is a history cache hold in the back for primitives of the last refresh.
  * When the user refreshes, this cache is cleared and all currently selected items
  * are reloaded.
- * If the user has selected at least one primitive not in the cache, the list 
+ * If the user has selected at least one primitive not in the cache, the list
  * is not displayed. Elsewhere, the list of all changes of all currently selected
  * objects are displayed.
- * 
+ *
  * @author imi
  */
@@ -130,4 +130,5 @@
 		});
 		reloadButton.setToolTipText(tr("Reload all currently selected objects and refresh the list."));
+		reloadButton.putClientProperty("help", "Dialog/History/Reload");
 		revertButton.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
@@ -136,4 +137,5 @@
 		});
 		revertButton.setToolTipText(tr("Revert the state of all currently selected objects to the version selected in the history list."));
+		revertButton.putClientProperty("help", "Dialog/History/Revert");
 	}
 
Index: c/org/openstreetmap/josm/gui/dialogs/LayerList.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 154)
+++ 	(revision )
@@ -1,265 +1,0 @@
-package org.openstreetmap.josm.gui.dialogs;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.Collection;
-
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-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.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;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.ImageProvider.OverlayPosition;
-
-/**
- * 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 last layerlist created. Used to update the list in the Show/Hide and Delete actions.
-	 * TODO: Replace with Listener-Pattern.
-	 */
-	static JList instance;
-
-	public final static class DeleteLayerAction extends AbstractAction {
-
-		private final Layer layer;
-
-		public DeleteLayerAction(Layer layer) {
-			super(tr("Delete"), ImageProvider.get("dialogs", "delete"));
-			putValue(SHORT_DESCRIPTION, tr("Delete the selected layer."));
-			this.layer = layer;
-		}
-
-		public void actionPerformed(ActionEvent e) {
-			int sel = instance.getSelectedIndex();
-			if (layer != null)
-				Main.main.removeLayer(layer);
-			else
-				Main.main.removeLayer((Layer)instance.getSelectedValue());
-			if (sel >= instance.getModel().getSize())
-				sel = instance.getModel().getSize()-1;
-			if (instance.getSelectedValue() == null)
-				instance.setSelectedIndex(sel);
-		}
-	}
-
-	public final static class ShowHideLayerAction extends AbstractAction {
-		private final Layer layer;
-
-		public ShowHideLayerAction(Layer layer) {
-			super(tr("Show/Hide"), ImageProvider.get("dialogs", "showhide"));
-			putValue(SHORT_DESCRIPTION, tr("Toggle visible state of the selected layer."));
-			this.layer = layer;
-		}
-
-		public void actionPerformed(ActionEvent e) {
-			Layer l = layer == null ? (Layer)instance.getSelectedValue() : layer;
-			l.visible = !l.visible;
-			Main.map.mapView.repaint();
-			instance.repaint();
-		}
-	}
-
-	/**
-	 * The data model for the list component.
-	 */
-	DefaultListModel model = new DefaultListModel();
-	/**
-	 * 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 Action deleteAction = new DeleteLayerAction(null);
-
-	/**
-	 * Create an layerlist and attach it to the given mapView.
-	 */
-	public LayerList(MapFrame mapFrame) {
-		super(tr("Layers"), "layerlist", tr("Open a list of all loaded layers."), KeyEvent.VK_L, 100);
-		instance = new JList(model);
-		add(new JScrollPane(instance), BorderLayout.CENTER);
-		instance.setBackground(UIManager.getColor("Button.background"));
-		instance.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.name, index, isSelected, cellHasFocus);
-				Icon icon = layer.getIcon();
-				if (!layer.visible)
-					icon = ImageProvider.overlay(icon, "overlay/invisible", OverlayPosition.SOUTHEAST);
-				label.setIcon(icon);
-				label.setToolTipText(layer.getToolTipText());
-				return label;
-			}
-		});
-
-		final MapView mapView = mapFrame.mapView;
-
-		Collection<Layer> data = mapView.getAllLayers();
-		for (Layer l : data)
-			model.addElement(l);
-
-		instance.setSelectedValue(mapView.getActiveLayer(), true);
-		instance.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-		instance.addListSelectionListener(new ListSelectionListener(){
-			public void valueChanged(ListSelectionEvent e) {
-				if (instance.getModel().getSize() == 0)
-					return;
-				if (instance.getSelectedIndex() == -1)
-					instance.setSelectedIndex(e.getFirstIndex());
-				mapView.setActiveLayer((Layer)instance.getSelectedValue());
-			}
-		});
-		mapView.addLayerChangeListener(this);
-
-		instance.addMouseListener(new MouseAdapter(){
-			private void openPopup(MouseEvent e) {
-				int index = instance.locationToIndex(e.getPoint());
-				Layer layer = (Layer)instance.getModel().getElementAt(index);
-				LayerListPopup menu = new LayerListPopup(instance, layer);
-				menu.show(LayerList.this, e.getX(), e.getY());
-			}
-			@Override public void mousePressed(MouseEvent e) {
-				if (e.isPopupTrigger())
-					openPopup(e);
-			}
-			@Override public void mouseReleased(MouseEvent e) {
-				if (e.isPopupTrigger())
-					openPopup(e);
-			}
-		});
-
-
-		// Buttons
-		JPanel buttonPanel = new JPanel(new GridLayout(1, 5));
-
-		ActionListener upDown = new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				Layer l = (Layer)instance.getSelectedValue();
-				int sel = instance.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);
-				instance.setSelectedIndex(selDest);
-				updateButtonEnabled();
-				mapView.repaint();
-			}
-		};
-
-		upButton.setToolTipText(tr("Move the selected layer one row up."));
-		upButton.addActionListener(upDown);
-		upButton.setActionCommand("up");
-		buttonPanel.add(upButton);
-
-		downButton.setToolTipText(tr("Move the selected layer one row down."));
-		downButton.addActionListener(upDown);
-		downButton.setActionCommand("down");
-		buttonPanel.add(downButton);
-
-		JButton showHideButton = new JButton(new ShowHideLayerAction(null));
-		showHideButton.setText("");
-		buttonPanel.add(showHideButton);
-
-		JButton deleteButton = new JButton(deleteAction);
-		deleteButton.setText("");
-		buttonPanel.add(deleteButton);
-
-		mergeButton.setToolTipText(tr("Merge the selected layer into the layer directly below."));
-		mergeButton.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				Layer lFrom = (Layer)instance.getSelectedValue();
-				Layer lTo = (Layer)model.get(instance.getSelectedIndex()+1);
-				lTo.mergeFrom(lFrom);
-				instance.setSelectedValue(lTo, true);
-				mapView.removeLayer(lFrom);
-			}
-		});		
-		buttonPanel.add(mergeButton);
-
-		add(buttonPanel, BorderLayout.SOUTH);
-
-		updateButtonEnabled();
-	}
-
-	/**
-	 * Updates the state of the Buttons.
-	 */
-	void updateButtonEnabled() {
-		int sel = instance.getSelectedIndex();
-		Layer l = (Layer)instance.getSelectedValue();
-		boolean enable = model.getSize() > 1;
-		enable = enable && sel < model.getSize()-1;
-		enable = enable && l.isMergable((Layer)model.get(sel+1));
-		mergeButton.setEnabled(enable);
-		upButton.setEnabled(sel > 0);
-		downButton.setEnabled(sel < model.getSize()-1);
-		deleteAction.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 (instance.getSelectedIndex() == -1)
-			instance.setSelectedIndex(0);
-		updateButtonEnabled();
-	}
-
-	/**
-	 * If the newLayer is not the actual selection, select it.
-	 */
-	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-		if (newLayer != instance.getSelectedValue())
-			instance.setSelectedValue(newLayer, true);
-		updateButtonEnabled();
-	}
-
-	public void layerMoved(Layer layer, int newPosition) {}
-}
Index: /src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 155)
+++ /src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 155)
@@ -0,0 +1,270 @@
+package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Collection;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+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.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;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.OverlayPosition;
+
+/**
+ * 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 LayerListDialog extends ToggleDialog implements LayerChangeListener {
+
+	/**
+	 * The last layerlist created. Used to update the list in the Show/Hide and Delete actions.
+	 * TODO: Replace with Listener-Pattern.
+	 */
+	static JList instance;
+
+	public final static class DeleteLayerAction extends AbstractAction {
+
+		private final Layer layer;
+
+		public DeleteLayerAction(Layer layer) {
+			super(tr("Delete"), ImageProvider.get("dialogs", "delete"));
+			putValue(SHORT_DESCRIPTION, tr("Delete the selected layer."));
+			putValue("help", "Dialog/LayerList/Delete");
+			this.layer = layer;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			int sel = instance.getSelectedIndex();
+			if (layer != null)
+				Main.main.removeLayer(layer);
+			else
+				Main.main.removeLayer((Layer)instance.getSelectedValue());
+			if (sel >= instance.getModel().getSize())
+				sel = instance.getModel().getSize()-1;
+			if (instance.getSelectedValue() == null)
+				instance.setSelectedIndex(sel);
+		}
+	}
+
+	public final static class ShowHideLayerAction extends AbstractAction {
+		private final Layer layer;
+
+		public ShowHideLayerAction(Layer layer) {
+			super(tr("Show/Hide"), ImageProvider.get("dialogs", "showhide"));
+			putValue(SHORT_DESCRIPTION, tr("Toggle visible state of the selected layer."));
+			putValue("help", "Dialog/LayerList/ShowHide");
+			this.layer = layer;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			Layer l = layer == null ? (Layer)instance.getSelectedValue() : layer;
+			l.visible = !l.visible;
+			Main.map.mapView.repaint();
+			instance.repaint();
+		}
+	}
+
+	/**
+	 * The data model for the list component.
+	 */
+	DefaultListModel model = new DefaultListModel();
+	/**
+	 * 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 Action deleteAction = new DeleteLayerAction(null);
+
+	/**
+	 * Create an layerlist and attach it to the given mapView.
+	 */
+	public LayerListDialog(MapFrame mapFrame) {
+		super(tr("Layers"), "layerlist", tr("Open a list of all loaded layers."), KeyEvent.VK_L, 100);
+		instance = new JList(model);
+		add(new JScrollPane(instance), BorderLayout.CENTER);
+		instance.setBackground(UIManager.getColor("Button.background"));
+		instance.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.name, index, isSelected, cellHasFocus);
+				Icon icon = layer.getIcon();
+				if (!layer.visible)
+					icon = ImageProvider.overlay(icon, "overlay/invisible", OverlayPosition.SOUTHEAST);
+				label.setIcon(icon);
+				label.setToolTipText(layer.getToolTipText());
+				return label;
+			}
+		});
+
+		final MapView mapView = mapFrame.mapView;
+
+		Collection<Layer> data = mapView.getAllLayers();
+		for (Layer l : data)
+			model.addElement(l);
+
+		instance.setSelectedValue(mapView.getActiveLayer(), true);
+		instance.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		instance.addListSelectionListener(new ListSelectionListener(){
+			public void valueChanged(ListSelectionEvent e) {
+				if (instance.getModel().getSize() == 0)
+					return;
+				if (instance.getSelectedIndex() == -1)
+					instance.setSelectedIndex(e.getFirstIndex());
+				mapView.setActiveLayer((Layer)instance.getSelectedValue());
+			}
+		});
+		mapView.addLayerChangeListener(this);
+
+		instance.addMouseListener(new MouseAdapter(){
+			private void openPopup(MouseEvent e) {
+				int index = instance.locationToIndex(e.getPoint());
+				Layer layer = (Layer)instance.getModel().getElementAt(index);
+				LayerListPopup menu = new LayerListPopup(instance, layer);
+				menu.show(LayerListDialog.this, e.getX(), e.getY());
+			}
+			@Override public void mousePressed(MouseEvent e) {
+				if (e.isPopupTrigger())
+					openPopup(e);
+			}
+			@Override public void mouseReleased(MouseEvent e) {
+				if (e.isPopupTrigger())
+					openPopup(e);
+			}
+		});
+
+
+		// Buttons
+		JPanel buttonPanel = new JPanel(new GridLayout(1, 5));
+
+		ActionListener upDown = new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				Layer l = (Layer)instance.getSelectedValue();
+				int sel = instance.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);
+				instance.setSelectedIndex(selDest);
+				updateButtonEnabled();
+				mapView.repaint();
+			}
+		};
+
+		upButton.setToolTipText(tr("Move the selected layer one row up."));
+		upButton.addActionListener(upDown);
+		upButton.setActionCommand("up");
+		upButton.putClientProperty("help", "Dialog/LayerList/Up");
+		buttonPanel.add(upButton);
+
+		downButton.setToolTipText(tr("Move the selected layer one row down."));
+		downButton.addActionListener(upDown);
+		downButton.setActionCommand("down");
+		downButton.putClientProperty("help", "Dialog/LayerList/Down");
+		buttonPanel.add(downButton);
+
+		JButton showHideButton = new JButton(new ShowHideLayerAction(null));
+		showHideButton.setText("");
+		buttonPanel.add(showHideButton);
+
+		JButton deleteButton = new JButton(deleteAction);
+		deleteButton.setText("");
+		buttonPanel.add(deleteButton);
+
+		mergeButton.setToolTipText(tr("Merge the selected layer into the layer directly below."));
+		mergeButton.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				Layer lFrom = (Layer)instance.getSelectedValue();
+				Layer lTo = (Layer)model.get(instance.getSelectedIndex()+1);
+				lTo.mergeFrom(lFrom);
+				instance.setSelectedValue(lTo, true);
+				mapView.removeLayer(lFrom);
+			}
+		});
+		mergeButton.putClientProperty("help", "Dialog/LayerList/Merge");
+		buttonPanel.add(mergeButton);
+
+		add(buttonPanel, BorderLayout.SOUTH);
+
+		updateButtonEnabled();
+	}
+
+	/**
+	 * Updates the state of the Buttons.
+	 */
+	void updateButtonEnabled() {
+		int sel = instance.getSelectedIndex();
+		Layer l = (Layer)instance.getSelectedValue();
+		boolean enable = model.getSize() > 1;
+		enable = enable && sel < model.getSize()-1;
+		enable = enable && l.isMergable((Layer)model.get(sel+1));
+		mergeButton.setEnabled(enable);
+		upButton.setEnabled(sel > 0);
+		downButton.setEnabled(sel < model.getSize()-1);
+		deleteAction.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 (instance.getSelectedIndex() == -1)
+			instance.setSelectedIndex(0);
+		updateButtonEnabled();
+	}
+
+	/**
+	 * If the newLayer is not the actual selection, select it.
+	 */
+	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+		if (newLayer != instance.getSelectedValue())
+			instance.setSelectedValue(newLayer, true);
+		updateButtonEnabled();
+	}
+
+	public void layerMoved(Layer layer, int newPosition) {}
+}
Index: /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 155)
@@ -54,6 +54,6 @@
 /**
  * This dialog displays the properties of the current selected primitives.
- * 
- * If no object is selected, the dialog list is empty. 
+ *
+ * If no object is selected, the dialog list is empty.
  * If only one is selected, all properties of this object are selected.
  * If more than one object are selected, the sum of all properties are displayed. If the
@@ -61,10 +61,10 @@
  * different values, all of them are put in a combo box and the string "&lt;different&gt;"
  * is displayed in italic.
- * 
- * Below the list, the user can click on an add, modify and delete property button to 
+ *
+ * Below the list, the user can click on an add, modify and delete property button to
  * edit the table selection value.
- * 
+ *
  * The command is applied to all selected entries.
- * 
+ *
  * @author imi
  */
@@ -91,5 +91,5 @@
 	/**
 	 * Edit the value in the table row
-	 * @param row 	The row of the table, from which the value is edited. 
+	 * @param row 	The row of the table, from which the value is edited.
 	 */
 	void edit(int row) {
@@ -138,5 +138,5 @@
 		if (value == null)
 			selectionChanged(sel); // update whole table
-		
+
 		Main.parent.repaint(); // repaint all - drawing could have been changed
 	}
@@ -330,4 +330,5 @@
 		b.setToolTipText(tooltip);
 		b.setMnemonic(mnemonic);
+		b.putClientProperty("help", "Dialog/Properties/"+name);
 		return b;
 	}
Index: /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 155)
@@ -126,25 +126,17 @@
 		JPanel buttonPanel = new JPanel(new GridLayout(1,2));
 
-		JButton button = new JButton(tr("Select"), ImageProvider.get("mapmode/selection/select"));
-		button.setToolTipText(tr("Set the selected elements on the map to the selected items in the list above."));
-		button.addActionListener(new ActionListener(){
+		buttonPanel.add(createButton("Select", "mapmode/selection/select", "Set the selected elements on the map to the selected items in the list above.", new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				updateMap();
 			}
-		});
-		buttonPanel.add(button);
-
-		button = new JButton(tr("Reload"), ImageProvider.get("dialogs", "refresh"));
-		button.setToolTipText(tr("Refresh the selection list."));
-		button.addActionListener(new ActionListener(){
+		}));
+
+		buttonPanel.add(createButton("Reload", "dialogs/refresh", "Refresh the selection list.", new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
 				selectionChanged(Main.ds.getSelected());
-			}
-		});
-		buttonPanel.add(button);
-
-		button = new JButton(tr("Search"), ImageProvider.get("dialogs", "search"));
-		button.setToolTipText(tr("Search for objects."));
-		button.addActionListener(new ActionListener(){
+            }
+		}));
+
+		buttonPanel.add(createButton("Search", "dialogs/search", "Search for objects.", new ActionListener(){
 			private String lastSearch = "";
 			public void actionPerformed(ActionEvent e) {
@@ -185,9 +177,16 @@
 				search(lastSearch, mode);
 			}
-		});
-		buttonPanel.add(button);
+		}));
 
 		add(buttonPanel, BorderLayout.SOUTH);
 		selectionChanged(Main.ds.getSelected());
+	}
+
+	private JButton createButton(String name, String icon, String tooltip, ActionListener action) {
+		JButton button = new JButton(tr(name), ImageProvider.get(icon));
+		button.setToolTipText(tr(tooltip));
+		button.addActionListener(action);
+		button.putClientProperty("help", "Dialog/SelectionList/"+name);
+		return button;
 	}
 
Index: /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 155)
@@ -13,12 +13,13 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.actions.HelpAction.Helpful;
 
 /**
  * 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 JPanel {
+public class ToggleDialog extends JPanel implements Helpful {
 
 	public final class ToggleDialogAction extends JosmAction {
@@ -49,4 +50,6 @@
 		setPreferredSize(new Dimension(330,preferredHeight));
 		action = new ToggleDialogAction(name, "dialogs/"+iconName, tooltip, shortCut, KeyEvent.ALT_MASK, iconName);
+		String helpId = "Dialog/"+getClass().getName().substring(getClass().getName().lastIndexOf('.')+1);
+		action.putValue("help", helpId.substring(0, helpId.length()-6));
 		setLayout(new BorderLayout());
 		add(new JLabel(name), BorderLayout.NORTH);
@@ -54,3 +57,9 @@
 		setBorder(BorderFactory.createEtchedBorder());
 	}
+
+	public String helpTopic() {
+		String help = getClass().getName();
+		help = help.substring(help.lastIndexOf('.')+1, help.length()-6);
+	    return "Dialog/"+help;
+    }
 }
Index: /src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 155)
@@ -56,5 +56,5 @@
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.dialogs.LayerList;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
@@ -360,6 +360,6 @@
 		});
 		return new Component[]{
-				new JMenuItem(new LayerList.ShowHideLayerAction(this)),
-				new JMenuItem(new LayerList.DeleteLayerAction(this)),
+				new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
+				new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
 				new JSeparator(),
 				sync,
Index: /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 155)
@@ -40,5 +40,5 @@
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
-import org.openstreetmap.josm.gui.dialogs.LayerList;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.tools.GBC;
@@ -327,6 +327,6 @@
 	@Override public Component[] getMenuEntries() {
 		return new Component[]{
-				new JMenuItem(new LayerList.ShowHideLayerAction(this)),
-				new JMenuItem(new LayerList.DeleteLayerAction(this)),
+				new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
+				new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
 				new JSeparator(),
 				new JMenuItem(new SaveAction()),
Index: /src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 154)
+++ /src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 155)
@@ -40,5 +40,5 @@
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.dialogs.LayerList;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.tools.ColorHelper;
@@ -277,6 +277,6 @@
 		
 		return new Component[]{
-				new JMenuItem(new LayerList.ShowHideLayerAction(this)),
-				new JMenuItem(new LayerList.DeleteLayerAction(this)),
+				new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
+				new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
 				new JSeparator(),
 				new JMenuItem(new GpxExportAction(this)),
Index: c/org/openstreetmap/josm/tools/TileCache.java
===================================================================
--- /src/org/openstreetmap/josm/tools/TileCache.java	(revision 154)
+++ 	(revision )
@@ -1,203 +1,0 @@
-package org.openstreetmap.josm.tools;
-
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-
-/**
- * A tile cache utility class to calculate tiles from lat/lon values.
- * 
- * One tile is a prerendered image of 512x512 pixels in size. The Zoom level of
- * a tile means, how big is the partion of the world, this tile occupy. On Mercator,
- * zoom=0 is exact the whole world, while zoom=1 is one quarter, zoom=2 is one of 
- * sixteen and so on.
- * 
- * The tile identifier is an 32-bit integer whose bits are ordered in pairs of two.
- * If bit0 (the LSB) is 0, then the tile is right of the equator (0 grad). If bit1 
- * is 0, it is in the northern hemisphere. The next two bits representing the 
- * quarter within the first quarter, so bit2 equals to 0 means, it is in the right 
- * half of the quarter, represented by bit0 and bit1.
- */
-public class TileCache {
-
-    public static final int TILESIZE = 512;
-    
-    /**
-     * This is the dimension of the world on x or y axis (both are the same).  Calculated in the constructor from the current projection, so that the  tiles are square.
-     */
-    public static final double worldDimension;
-    
-    static {
-        EastNorth en = Main.proj.latlon2eastNorth(new LatLon(0,180));
-        worldDimension = en.east();
-    }
-    
-    
-	public static class TileInformation {
-    	/**
-    	 * The encoded tile id for that point
-    	 */
-    	public final int tileId;
-    	/**
-    	 * Offset of the point within the tile (after projection)
-    	 */
-    	public final double offsetX, offsetY;
-    	/**
-    	 * OSM zoom factor (0 = earth, 1=quarter of earth, 2=sixteenth of earth...)
-    	 */
-    	public final int zoom;
-    	/**
-    	 * Projected point 
-    	 */
-    	public final EastNorth pos;
-    	/**
-    	 * Unprojected lower left corner of the tile
-    	 */
-    	public final LatLon min;
-    	/**
-    	 * Unprojected upper right corner of the tile
-    	 */
-    	public final LatLon max;
-    	
-    	public TileInformation(int id, double x, double y, int z, EastNorth p, LatLon mi, LatLon ma) {
-    		tileId = id; offsetX = x; offsetY = y; zoom = z; pos = p; min = mi; max = ma;
-    	}
-    }
-
-	private final static Image loading = ImageProvider.get("loading.jpg").getImage();
-    
-    private Map<Integer, Map<Integer, Image>> cache = new TreeMap<Integer, Map<Integer, Image>>();
-    private final String urlBase;
-
-    
-    private Vector<Integer> currentlyLoading = new Vector<Integer>();
-
-
-	public TileCache(String urlBase) {
-        this.urlBase = urlBase;
-	}
-    
-    
-    /**
-     * Get the tile's information where the coordinate is in.
-     */
-    public static TileInformation pos2tile(EastNorth pos, int zoom) {
-        int id = 0;
-        double pivotE = 0, pivotN = 0;
-        double size = worldDimension;
-        int bit = 1;
-        for (int i = 0; i < zoom; ++i) {
-            size /= 2;
-
-            if (pos.east() < pivotE) {
-                id |= bit;
-                pivotE -= size;
-            } else
-                pivotE += size;
-            bit *= 2;
-
-            if (pos.north() < pivotN) {
-                id |= bit;
-                pivotN -= size;
-            } else
-                pivotN += size;
-            bit *= 2;
-        }
-        return new TileCache.TileInformation(id, pos.east()-pivotE, pos.north()-pivotN, zoom, pos, Main.proj.eastNorth2latlon(new EastNorth(pivotE-size, pivotN-size)), Main.proj.eastNorth2latlon(new EastNorth(pivotE+size, pivotN+size)));
-    }
-
-    /**
-     * Get the surrounding bounds of the tile.
-     */
-    public static Bounds tile2pos(int tileId, int zoom) {
-        int id = 0;
-        double pivotE = 0, pivotN = 0;
-        double size = worldDimension;
-        int bit = 1;
-        for (int i = 0; i < zoom; ++i) {
-            size /= 2;
-            
-            if ((id | bit) != 0)
-                pivotE += size;
-            else
-                pivotE -= size;
-            bit *= 2;
-            
-            if ((id | bit) != 0)
-                pivotN += size;
-            else
-                pivotN -= size;
-            bit *= 2;
-        }
-        return new Bounds(
-                Main.proj.eastNorth2latlon(new EastNorth(pivotE-size, pivotN-size)),
-                Main.proj.eastNorth2latlon(new EastNorth(pivotE+size, pivotN+size)));
-    }
-
-    /**
-     * Get the image for the specified tile.
-     */
-    public synchronized Image get(final int tileId, final int zoom) {
-        final File cacheDir = new File(Main.pref.get("cache.directory", Main.pref.getPreferencesDir()+"cache")+"/"+Main.proj.getCacheDirectoryName()+"/"+zoom);
-        if (!cache.containsKey(zoom)) {
-            HashMap<Integer, Image> map = new HashMap<Integer, Image>();
-            if (!cacheDir.exists())
-                cacheDir.mkdirs();
-            for (File f : cacheDir.listFiles())
-                map.put(Integer.parseInt(f.getName()), loading);
-            cache.put(zoom, map);
-        }
-        final Map<Integer, Image> map = cache.get(zoom);
-        Image img = map.get(tileId);
-        if (img == loading) {
-            // load from disk
-            System.out.println("loading from disk "+cacheDir.getPath()+"/"+tileId);
-            img = Toolkit.getDefaultToolkit().createImage(cacheDir.getPath()+"/"+tileId);
-            map.put(tileId, img);
-        } else if (img == null) {
-            img = loading;
-            if (!currentlyLoading.contains(tileId*256+zoom)) {
-                currentlyLoading.add(tileId*256+zoom);
-                // load from network
-                Main.worker.execute(new Runnable(){
-                    public void run() {
-                        try {
-                            Bounds b = tile2pos(tileId, zoom);
-                            URL url = new URL(urlBase+"bbox="+b.min.lon()+","+b.min.lat()+","+b.max.lon()+","+b.max.lat());
-                            System.out.println("loading from net "+url);
-                            InputStream in = url.openStream();
-                            OutputStream out = new FileOutputStream(cacheDir+"/"+tileId);
-                            byte[] buf = new byte[8192];
-                            for (int read = in.read(buf); read > 0; read = in.read(buf))
-                                out.write(buf, 0, read);
-                            in.close();
-                            out.close();
-                            map.put(tileId, loading);
-                            currentlyLoading.remove(tileId*256+zoom);
-                            Main.map.repaint();
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        }        
-                    }
-                });
-            }
-        } else {
-            System.out.println("providing from cache "+img.getWidth(null));
-        }
-        System.out.println(img.getWidth(null));
-        return img;
-    }
-}
Index: /src/org/openstreetmap/josm/tools/WikiReader.java
===================================================================
--- /src/org/openstreetmap/josm/tools/WikiReader.java	(revision 155)
+++ /src/org/openstreetmap/josm/tools/WikiReader.java	(revision 155)
@@ -0,0 +1,81 @@
+package org.openstreetmap.josm.tools;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Read a trac-wiki page.
+ *
+ * @author imi
+ */
+public class WikiReader {
+
+	public static final String JOSM_EXTERN = "http://josm-extern.";
+	private final String baseurl;
+
+	public WikiReader(String baseurl) {
+		this.baseurl = baseurl;
+    }
+
+	/**
+	 * Read the page specified by the url and return the content.
+	 *
+	 * If the url is within the baseurl path, parse it as an trac wikipage and
+	 * replace relative pathes etc..
+	 *
+	 * @return Either the string of the content of the wiki page or <code>null</code>
+	 * if the page could not be read.
+	 */
+	public String read(String url) {
+		try {
+	        BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
+	        if (url.startsWith(baseurl))
+	        	return readFromTrac(in, url);
+	        return readNormal(in);
+        } catch (MalformedURLException e) {
+        	throw new RuntimeException(e);
+        } catch (IOException e) {
+        	return null;
+        }
+	}
+
+	private String readNormal(BufferedReader in) throws IOException {
+		StringBuilder b = new StringBuilder("<html>");
+		for (String line = in.readLine(); line != null; line = in.readLine()) {
+			line = adjustText(line);
+			b.append(line);
+			b.append("\n");
+		}
+		return b.toString();
+    }
+
+	private String readFromTrac(BufferedReader in, String url) throws IOException {
+        boolean inside = false;
+        StringBuilder b = new StringBuilder("<html>");
+        for (String line = in.readLine(); line != null; line = in.readLine()) {
+        	if (line.contains("<div id=\"searchable\">"))
+        		inside = true;
+        	else if (line.contains("<div class=\"buttons\">"))
+        		inside = false;
+        	if (inside) {
+        		line = line.replaceAll("<img src=\"/", "<img src=\""+baseurl+"/");
+        		line = line.replaceAll("href=\"/", "href=\""+baseurl+"/");
+        		if (!line.contains("$"))
+        			line = line.replaceAll("<p>Describe \"([^\"]+)\" here</p>", "<p>Describe \"$1\" <a href=\""+JOSM_EXTERN+url.substring(7)+"\">here</a></p>");
+        		line = adjustText(line);
+        		b.append(line);
+        		b.append("\n");
+        	}
+        }
+        b.append("</html>");
+        return b.toString();
+    }
+
+	private String adjustText(String text) {
+	    text = text.replaceAll(" />", ">");
+	    return text;
+    }
+}
