Index: /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSet.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSet.java	(revision 2018)
+++ /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSet.java	(revision 2019)
@@ -7,9 +7,21 @@
 import java.util.HashMap;
 import java.util.NoSuchElementException;
+import java.util.concurrent.CopyOnWriteArrayList;
 
+/**
+ * A data set holding histories of OSM primitives.
+ * 
+ *
+ */
 public class HistoryDataSet {
 
+    /** the unique instance */
     private static HistoryDataSet historyDataSet;
 
+    /**
+     * Replies the unique instance of the history data set
+     * 
+     * @return the unique instance of the history data set
+     */
     public static HistoryDataSet getInstance() {
         if (historyDataSet == null) {
@@ -19,11 +31,47 @@
     }
 
+    /** the history data */
     private HashMap<Long, ArrayList<HistoryOsmPrimitive>> data;
+    private CopyOnWriteArrayList<HistoryDataSetListener> listeners;
 
     public HistoryDataSet() {
         data = new HashMap<Long, ArrayList<HistoryOsmPrimitive>>();
+        listeners = new CopyOnWriteArrayList<HistoryDataSetListener>();
     }
 
-    public HistoryOsmPrimitive get(long id, long version) {
+    public void addHistoryDataSetListener(HistoryDataSetListener listener) {
+        synchronized(listeners) {
+            if (!listeners.contains(listener)) {
+                listeners.add(listener);
+            }
+        }
+    }
+
+    public void removeHistoryDataSetListener(HistoryDataSetListener listener) {
+        synchronized(listeners) {
+            if (listeners.contains(listener)) {
+                listeners.remove(listener);
+            }
+        }
+    }
+
+    protected void fireHistoryUpdated(long id) {
+        for (HistoryDataSetListener l : listeners) {
+            l.historyUpdated(this, id);
+        }
+    }
+
+    /**
+     * Replies the history primitive for the primitive with id <code>id</code>
+     * and version <code>version</code>
+     * 
+     * @param id the id of the primitive
+     * @param version the version of the primitive
+     * @return the history primitive for the primitive with id <code>id</code>
+     * and version <code>version</code>
+     * @throws NoSuchElementException thrown if this dataset doesn't include the respective
+     * history primitive
+     */
+    public HistoryOsmPrimitive get(long id, long version) throws NoSuchElementException{
         ArrayList<HistoryOsmPrimitive> versions = data.get(id);
         if (versions == null)
@@ -37,4 +85,9 @@
     }
 
+    /**
+     * Adds a history primitive to the data set
+     * 
+     * @param primitive  the history primitive to add
+     */
     public void put(HistoryOsmPrimitive primitive) {
         if (data.get(primitive.getId()) == null) {
@@ -42,4 +95,5 @@
         }
         data.get(primitive.getId()).add(primitive);
+        fireHistoryUpdated(primitive.getId());
     }
 
@@ -66,8 +120,7 @@
             return;
         for (Long id : other.data.keySet()) {
-            if (!this.data.keySet().contains(id)) {
-                this.data.put(id, other.data.get(id));
-            }
+            this.data.put(id, other.data.get(id));
         }
+        fireHistoryUpdated(0);
     }
 }
Index: /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSetListener.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSetListener.java	(revision 2019)
+++ /trunk/src/org/openstreetmap/josm/data/osm/history/HistoryDataSetListener.java	(revision 2019)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm.history;
+
+public interface HistoryDataSetListener {
+    void historyUpdated(HistoryDataSet source, long primitiveId);
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 2018)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 2019)
@@ -44,7 +44,10 @@
 import org.openstreetmap.josm.data.osm.history.History;
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.history.HistoryBrowserDialog;
+import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
+import org.openstreetmap.josm.gui.history.HistoryLoadTask;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmApiException;
@@ -67,45 +70,5 @@
  * @author imi
  */
-public class HistoryDialog extends ToggleDialog {
-
-    /** the registry of history browser dialogs which are currently displaying */
-    static private HashMap<Long, HistoryBrowserDialog> historyBrowserDialogs;
-
-    /**
-     * registers a {@see HistoryBrowserDialog}
-     * @param id the id of the primitive dialog shows the history for
-     * @param dialog the dialog
-     */
-    public static void registerHistoryBrowserDialog(long id, HistoryBrowserDialog dialog) {
-        if (historyBrowserDialogs == null) {
-            historyBrowserDialogs = new HashMap<Long, HistoryBrowserDialog>();
-        }
-        historyBrowserDialogs.put(id, dialog);
-    }
-
-    /**
-     * unregisters a {@see HistoryBrowserDialog}
-     * @param id the id of the primitive whose history dialog is to be unregistered
-     *
-     */
-    public static void unregisterHistoryBrowserDialog(long id) {
-        if (historyBrowserDialogs == null)
-            return;
-        historyBrowserDialogs.remove(id);
-    }
-
-    /**
-     * replies the history dialog for the primitive with id <code>id</code>; null, if
-     * no such {@see HistoryBrowserDialog} is currently showing
-     *
-     * @param id the id of the primitive
-     * @return the dialog; null, if no such dialog is showing
-     */
-    public static HistoryBrowserDialog getHistoryBrowserDialog(long id) {
-        if (historyBrowserDialogs == null)
-            return null;
-        return historyBrowserDialogs.get(id);
-    }
-
+public class HistoryDialog extends ToggleDialog implements HistoryDataSetListener {
 
     /** the table model */
@@ -197,12 +160,11 @@
         build();
         DataSet.selListeners.add(model);
-    }
-
-    /**
-     * refreshes the current list of history items; reloads history information from the server
-     */
-    protected void refresh() {
-        HistoryLoadTask task = new HistoryLoadTask();
-        Main.worker.execute(task);
+        HistoryDataSet.getInstance().addHistoryDataSetListener(this);
+    }
+
+
+
+    public void historyUpdated(HistoryDataSet source, long primitiveId) {
+        model.refresh();
     }
 
@@ -216,46 +178,12 @@
         if (h == null)
             throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "h"));
-        HistoryBrowserDialog dialog = getHistoryBrowserDialog(h.getId());
-        if (dialog == null) {
-            dialog = new HistoryBrowserDialog(h);
-        }
-        dialog.setVisible(true);
-    }
-
-    /**
-     * invoked after the asynchronous {@see HistoryLoadTask} is finished.
-     *
-     * @param task the task which is calling back.
-     */
-    protected void postRefresh(HistoryLoadTask task) {
-        model.refresh();
-        if (task.isCancelled())
-            return;
-        if (task.getLastException() != null) {
-            task.getLastException().printStackTrace();
-            String msg = null;
-            if (task.getLastException() instanceof OsmApiException) {
-                msg = ((OsmApiException)task.getLastException()).getErrorBody();
-                if (msg == null) {
-                    msg = ((OsmApiException)task.getLastException()).getErrorHeader();
-                }
-            }
-            if (msg == null) {
-                msg = task.getLastException().getMessage();
-            }
-            if (msg == null) {
-                msg = task.getLastException().toString();
-            }
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr(
-                            "<html>Failed to load history from the server. Details:<br>{0}</html>",
-                            msg.replaceAll("&", "&amp;").replaceAll(">", "&gt;").replaceAll("<", "&lt;")
-                    ),
-                    tr("Error"),
-                    JOptionPane.ERROR_MESSAGE
-            );
-        }
-    }
+        if (HistoryBrowserDialogManager.getInstance().existsDialog(h.getId())) {
+            HistoryBrowserDialogManager.getInstance().show(h.getId());
+        } else {
+            HistoryBrowserDialog dialog = new HistoryBrowserDialog(h);
+            HistoryBrowserDialogManager.getInstance().show(h.getId(), dialog);
+        }
+    }
+
 
     /**
@@ -340,7 +268,7 @@
             String msg = "";
             switch(h.getEarliest().getType()) {
-            case NODE:  msg = marktr("Node {0}"); break;
-            case WAY: msg = marktr("Way {0}"); break;
-            case RELATION: msg = marktr("Relation {0}"); break;
+                case NODE:  msg = marktr("Node {0}"); break;
+                case WAY: msg = marktr("Way {0}"); break;
+                case RELATION: msg = marktr("Relation {0}"); break;
             }
             setText(tr(msg,h.getId()));
@@ -381,77 +309,4 @@
 
     /**
-     * The asynchronous task which loads history information for  the currently selected
-     * primitives from the server.
-     *
-     */
-    class HistoryLoadTask extends PleaseWaitRunnable {
-
-        private boolean cancelled = false;
-        private Exception lastException  = null;
-
-        public HistoryLoadTask() {
-            super(tr("Load history"), true);
-        }
-
-        @Override
-        protected void cancel() {
-            OsmApi.getOsmApi().cancel();
-            cancelled = true;
-        }
-
-        @Override
-        protected void finish() {
-            postRefresh(this);
-        }
-
-        @Override
-        protected void realRun() throws SAXException, IOException, OsmTransferException {
-            Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelected();
-            Iterator<OsmPrimitive> it = selection.iterator();
-            try {
-                while(it.hasNext()) {
-                    OsmPrimitive primitive = it.next();
-                    if (cancelled) {
-                        break;
-                    }
-                    if (primitive.id == 0) {
-                        continue;
-                    }
-                    String msg = "";
-                    switch(OsmPrimitiveType.from(primitive)) {
-                    case NODE: msg = marktr("Loading history for node {0}"); break;
-                    case WAY: msg = marktr("Loading history for way {0}"); break;
-                    case RELATION: msg = marktr("Loading history for relation {0}"); break;
-                    }
-                    progressMonitor.indeterminateSubTask(tr(msg,
-                            Long.toString(primitive.id)));
-                    OsmServerHistoryReader reader = null;
-                    HistoryDataSet ds = null;
-                    try {
-                        reader = new OsmServerHistoryReader(OsmPrimitiveType.from(primitive), primitive.id);
-                        ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
-                    } catch(OsmTransferException e) {
-                        if (cancelled)
-                            return;
-                        throw e;
-                    }
-                    HistoryDataSet.getInstance().mergeInto(ds);
-                }
-            } catch(OsmTransferException e) {
-                lastException = e;
-                return;
-            }
-        }
-
-        public boolean isCancelled() {
-            return cancelled;
-        }
-
-        public Exception getLastException() {
-            return lastException;
-        }
-    }
-
-    /**
      * The action for reloading history information of the currently selected primitives.
      *
@@ -464,5 +319,7 @@
 
         public void actionPerformed(ActionEvent e) {
-            refresh();
+            HistoryLoadTask task = new HistoryLoadTask();
+            task.add(Main.main.getCurrentDataSet().getSelected());
+            Main.worker.execute(task);
         }
 
@@ -473,5 +330,4 @@
                 setEnabled(Main.main.getCurrentDataSet().getSelected().size() > 0);
             }
-
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialog.java	(revision 2018)
+++ /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialog.java	(revision 2019)
@@ -8,7 +8,8 @@
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 
 import javax.swing.AbstractAction;
-import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JOptionPane;
@@ -17,5 +18,9 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.history.History;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
+import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.HistoryDialog;
+import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -24,5 +29,5 @@
  * 
  */
-public class HistoryBrowserDialog extends JDialog {
+public class HistoryBrowserDialog extends JDialog implements HistoryDataSetListener{
 
     /** the embedded browser */
@@ -37,7 +42,7 @@
         String title = "";
         switch(h.getEarliest().getType()) {
-        case NODE:  title = marktr("History for node {0}"); break;
-        case WAY: title = marktr("History for way {0}"); break;
-        case RELATION:  title = marktr("History for relation {0}"); break;
+            case NODE:  title = marktr("History for node {0}"); break;
+            case WAY: title = marktr("History for way {0}"); break;
+            case RELATION:  title = marktr("History for relation {0}"); break;
         }
         setTitle(tr(
@@ -57,7 +62,11 @@
 
         JPanel pnl = new JPanel();
-        pnl.setLayout(new FlowLayout(FlowLayout.RIGHT));
+        pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
 
-        JButton btn = new JButton(new CloseAction());
+        SideButton btn = new SideButton(new ReloadAction());
+        btn.setName("btn.reload");
+        pnl.add(btn);
+
+        btn = new SideButton(new CloseAction());
         btn.setName("btn.close");
         pnl.add(btn);
@@ -77,4 +86,6 @@
         setHistory(history);
         renderTitle(history);
+        HistoryDataSet.getInstance().addHistoryDataSetListener(this);
+        addWindowListener(new WindowClosingAdapter());
     }
 
@@ -87,31 +98,10 @@
     }
 
-    /**
-     * registers this dialog with the registry of history dialogs
-     * 
-     * @see HistoryDialog#registerHistoryBrowserDialog(long, HistoryBrowserDialog)
-     */
-    protected void register() {
-        HistoryDialog.registerHistoryBrowserDialog(browser.getHistory().getId(), this);
-    }
-
-    /**
-     * unregisters this dialog from the registry of history dialogs
-     * 
-     * @see HistoryDialog#unregisterHistoryBrowserDialog(long)
-     */
-    protected void unregister() {
-        HistoryDialog.unregisterHistoryBrowserDialog(browser.getHistory().getId());
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        if (visible) {
-            register();
-            toFront();
-        } else {
-            unregister();
+    public void historyUpdated(HistoryDataSet source, long primitiveId) {
+        if (primitiveId == browser.getHistory().getId()) {
+            browser.populate(source.getHistory(primitiveId));
+        } else if (primitiveId == 0) {
+            browser.populate(source.getHistory(browser.getHistory().getId()));
         }
-        super.setVisible(visible);
     }
 
@@ -120,8 +110,32 @@
             putValue(NAME, tr("Close"));
             putValue(SHORT_DESCRIPTION, tr("Close the dialog"));
+            putValue(SMALL_ICON, ImageProvider.get("ok"));
         }
 
         public void actionPerformed(ActionEvent e) {
-            setVisible(false);
+            HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
+            HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this);
+        }
+    }
+
+    class ReloadAction extends AbstractAction {
+        public ReloadAction() {
+            putValue(NAME, tr("Reload"));
+            putValue(SHORT_DESCRIPTION, tr("Reload the history from the server"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            HistoryLoadTask task = new HistoryLoadTask();
+            task.add(browser.getHistory());
+            Main.worker.submit(task);
+        }
+    }
+
+    class WindowClosingAdapter extends WindowAdapter {
+        @Override
+        public void windowClosing(WindowEvent e) {
+            HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
+            HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this);
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java	(revision 2019)
+++ /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java	(revision 2019)
@@ -0,0 +1,81 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.history;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.tools.WindowGeometry;
+
+public class HistoryBrowserDialogManager {
+    static private HistoryBrowserDialogManager instance;
+    static public HistoryBrowserDialogManager getInstance() {
+        if (instance == null) {
+            instance = new HistoryBrowserDialogManager();
+        }
+        return instance;
+    }
+
+    private Map<Long, HistoryBrowserDialog> dialogs;
+
+    protected HistoryBrowserDialogManager() {
+        dialogs = new HashMap<Long, HistoryBrowserDialog>();
+    }
+
+    public boolean existsDialog(long id) {
+        return dialogs.containsKey(id);
+    }
+
+    public void show(long id, HistoryBrowserDialog dialog) {
+        if (dialogs.values().contains(dialog)) {
+            show(id);
+        } else {
+            placeOnScreen(dialog);
+            dialog.setVisible(true);
+            dialogs.put(id, dialog);
+        }
+    }
+
+    public void show(long id) {
+        if (dialogs.keySet().contains(id)) {
+            dialogs.get(id).toFront();
+        }
+    }
+
+    protected boolean hasDialogWithCloseUpperLeftCorner(Point p) {
+        for (HistoryBrowserDialog dialog: dialogs.values()) {
+            Point corner = dialog.getLocation();
+            if (p.x >= corner.x -5 && corner.x + 5 >= p.x
+                    && p.y >= corner.y -5 && corner.y + 5 >= p.y)
+                return true;
+        }
+        return false;
+    }
+
+    public void placeOnScreen(HistoryBrowserDialog dialog) {
+        WindowGeometry geometry = WindowGeometry.centerOnScreen(new Dimension(800,500));
+        geometry.apply(dialog);
+        Point p = dialog.getLocation();
+        while(hasDialogWithCloseUpperLeftCorner(p)) {
+            p.x +=20;
+            p.y += 20;
+        }
+        dialog.setLocation(p);
+    }
+
+    public void hide(HistoryBrowserDialog dialog) {
+        long id = 0;
+        for (long i: dialogs.keySet()) {
+            if (dialogs.get(i) == dialog) {
+                id = i;
+                break;
+            }
+        }
+        if (id > 0) {
+            dialogs.remove(id);
+        }
+        dialog.setVisible(false);
+        dialog.dispose();
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 2018)
+++ /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 2019)
@@ -103,4 +103,5 @@
         setChanged();
         notifyObservers();
+        versionTableModel.fireTableDataChanged();
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/history/HistoryLoadTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/history/HistoryLoadTask.java	(revision 2019)
+++ /trunk/src/org/openstreetmap/josm/gui/history/HistoryLoadTask.java	(revision 2019)
@@ -0,0 +1,146 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.history;
+
+import static org.openstreetmap.josm.tools.I18n.marktr;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.history.History;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
+import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
+import org.openstreetmap.josm.gui.ExceptionDialogUtil;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.io.OsmServerHistoryReader;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.xml.sax.SAXException;
+
+public class HistoryLoadTask extends PleaseWaitRunnable {
+
+    private boolean cancelled = false;
+    private Exception lastException  = null;
+    private Map<Long, OsmPrimitiveType> toLoad;
+    private HistoryDataSet loadedData;
+
+    public HistoryLoadTask() {
+        super(tr("Load history"), true);
+        toLoad = new HashMap<Long, OsmPrimitiveType>();
+    }
+
+    public HistoryLoadTask add(long id, OsmPrimitiveType type) {
+        if (id <= 0)
+            throw new IllegalArgumentException(tr("id > 0 expected, got {0}", id));
+        if (type == null)
+            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "type"));
+        if (!toLoad.containsKey(id)) {
+            toLoad.put(id, type);
+        }
+        return this;
+    }
+
+    public HistoryLoadTask add(HistoryOsmPrimitive primitive) {
+        if (primitive == null)
+            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "primitive"));
+        if (!toLoad.containsKey(primitive.getId())) {
+            toLoad.put(primitive.getId(), primitive.getType());
+        }
+        return this;
+    }
+
+    public HistoryLoadTask add(History history) {
+        if (history == null)
+            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "history"));
+        if (!toLoad.containsKey(history.getId())) {
+            toLoad.put(history.getId(), history.getEarliest().getType());
+        }
+        return this;
+    }
+
+    public HistoryLoadTask add(OsmPrimitive primitive) {
+        if (primitive == null)
+            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "primitive"));
+        return add(primitive.id, OsmPrimitiveType.from(primitive));
+    }
+
+    public HistoryLoadTask add(Collection<? extends OsmPrimitive> primitives) {
+        if (primitives == null)
+            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "primitives"));
+        for (OsmPrimitive primitive: primitives) {
+            if (primitive == null) {
+                continue;
+            }
+            add(primitive);
+        }
+        return this;
+    }
+
+    @Override
+    protected void cancel() {
+        OsmApi.getOsmApi().cancel();
+        cancelled = true;
+    }
+
+    @Override
+    protected void finish() {
+        if (isCancelled())
+            return;
+        if (lastException != null) {
+            ExceptionDialogUtil.explainException(lastException);
+            return;
+        }
+        HistoryDataSet.getInstance().mergeInto(loadedData);
+    }
+
+    @Override
+    protected void realRun() throws SAXException, IOException, OsmTransferException {
+        loadedData = new HistoryDataSet();
+        try {
+            for(Map.Entry<Long, OsmPrimitiveType> entry: toLoad.entrySet()) {
+                if (cancelled) {
+                    break;
+                }
+                if (entry.getKey() == 0) {
+                    continue;
+                }
+                String msg = "";
+                switch(entry.getValue()) {
+                    case NODE: msg = marktr("Loading history for node {0}"); break;
+                    case WAY: msg = marktr("Loading history for way {0}"); break;
+                    case RELATION: msg = marktr("Loading history for relation {0}"); break;
+                }
+                progressMonitor.indeterminateSubTask(tr(msg,
+                        Long.toString(entry.getKey())));
+                OsmServerHistoryReader reader = null;
+                HistoryDataSet ds = null;
+                try {
+                    reader = new OsmServerHistoryReader(entry.getValue(), entry.getKey());
+                    ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
+                } catch(OsmTransferException e) {
+                    if (cancelled)
+                        return;
+                    throw e;
+                }
+                loadedData.mergeInto(ds);
+            }
+        } catch(OsmTransferException e) {
+            lastException = e;
+            return;
+        }
+    }
+
+    public boolean isCancelled() {
+        return cancelled;
+    }
+
+    public Exception getLastException() {
+        return lastException;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 2018)
+++ /trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 2019)
@@ -56,5 +56,5 @@
         public void mouseClicked(MouseEvent e) {
             switch(e.getClickCount()) {
-            case 2: handleDoubleClick(e); break;
+                case 2: handleDoubleClick(e); break;
             }
         }
