Index: /trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/Main.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/Main.java	(revision 1811)
@@ -13,5 +13,4 @@
 import java.net.URISyntaxException;
 import java.util.Collection;
-import java.util.Locale;
 import java.util.Map;
 import java.util.StringTokenizer;
@@ -42,5 +41,4 @@
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
 import org.openstreetmap.josm.gui.SplashScreen;
 import org.openstreetmap.josm.gui.download.DownloadDialog.DownloadTask;
@@ -99,5 +97,5 @@
      * The dialog that gets displayed during background task execution.
      */
-    public static PleaseWaitDialog pleaseWaitDlg;
+    //public static PleaseWaitDialog pleaseWaitDlg;
 
     /**
@@ -230,5 +228,5 @@
      * exists. Replies null, if the currently active layer isn't an instance
      * of {@see OsmDataLayer}.
-     * 
+     *
      * @return the current edit layer
      */
@@ -242,5 +240,5 @@
     /**
      * Replies true if this map view has an edit layer
-     * 
+     *
      * @return true if this map view has an edit layer
      */
@@ -352,13 +350,7 @@
             bounds = !args.containsKey("no-maximize") ? new Rectangle(0,0,screenDimension.width,screenDimension.height) : new Rectangle(1000,740);
         }
-
-        // preinitialize a wait dialog for all early downloads (e.g. via command line)
-        pleaseWaitDlg = new PleaseWaitDialog(null);
     }
 
     public void postConstructorProcessCmdLine(Map<String, Collection<String>> args) {
-        // initialize the pleaseWaitDialog with the application as parent to handle focus stuff
-        pleaseWaitDlg = new PleaseWaitDialog(parent);
-
         if (args.containsKey("download")) {
             for (String s : args.get("download")) {
@@ -426,5 +418,5 @@
                 //DownloadTask osmTask = main.menu.download.downloadTasks.get(0);
                 DownloadTask osmTask = new DownloadOsmTask();
-                osmTask.download(main.menu.download, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon());
+                osmTask.download(main.menu.download, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon(), null);
             }
             return;
@@ -444,5 +436,5 @@
             try {
                 DownloadTask task = rawGps ? new DownloadGpsTask() : new DownloadOsmTask();
-                task.download(main.menu.download, Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));
+                task.download(main.menu.download, Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), null);
                 return;
             } catch (final NumberFormatException e) {
Index: /trunk/src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 1811)
@@ -60,5 +60,5 @@
                     Main.pref.put("download."+task.getPreferencesSuffix(), task.getCheckBox().isSelected());
                     if (task.getCheckBox().isSelected()) {
-                        task.download(this, dialog.minlat, dialog.minlon, dialog.maxlat, dialog.maxlon);
+                        task.download(this, dialog.minlat, dialog.minlon, dialog.maxlat, dialog.maxlon, null);
                         finish = true;
                     }
Index: /trunk/src/org/openstreetmap/josm/actions/DownloadReferrersAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/DownloadReferrersAction.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/DownloadReferrersAction.java	(revision 1811)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.EventQueue;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -23,4 +22,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmServerBackreferenceReader;
@@ -32,5 +32,5 @@
  * This action loads the set of primitives referring to the current selection from the OSM
  * server.
- * 
+ *
  *
  */
@@ -49,5 +49,5 @@
      * Downloads the primitives referring to the primitives in <code>primitives</code>.
      * Does nothing if primitives is null or empty.
-     * 
+     *
      * @param primitives the collection of primitives.
      */
@@ -68,5 +68,5 @@
     /**
      * The asynchronous task for downloading referring primitives
-     * 
+     *
      */
     class DownloadReferrersTask extends PleaseWaitRunnable {
@@ -76,14 +76,4 @@
         private Collection<OsmPrimitive> primitives;
         private DataSet parents;
-
-        protected void setIndeterminateEnabled(final boolean enabled) {
-            EventQueue.invokeLater(
-                    new Runnable() {
-                        public void run() {
-                            Main.pleaseWaitDlg.setIndeterminate(enabled);
-                        }
-                    }
-            );
-        }
 
         public DownloadReferrersTask(Collection<OsmPrimitive> primitives) {
@@ -140,5 +130,5 @@
                             JOptionPane.WARNING_MESSAGE
             );
-            JDialog dialog = op.createDialog(Main.pleaseWaitDlg, tr("Conflicts in data"));
+            JDialog dialog = op.createDialog(null, tr("Conflicts in data"));
             dialog.setAlwaysOnTop(true);
             dialog.setModal(true);
@@ -147,7 +137,7 @@
         }
 
-        protected void downloadParents(OsmPrimitive primitive) throws OsmTransferException{
+        protected void downloadParents(OsmPrimitive primitive, ProgressMonitor progressMonitor) throws OsmTransferException{
             OsmServerBackreferenceReader reader = new OsmServerBackreferenceReader(primitive);
-            DataSet ds = reader.parseOsm();
+            DataSet ds = reader.parseOsm(progressMonitor);
             MergeVisitor visitor = new MergeVisitor(parents, ds);
             visitor.merge();
@@ -156,13 +146,12 @@
         @Override
         protected void realRun() throws SAXException, IOException, OsmTransferException {
-            setIndeterminateEnabled(true);
             try {
+                progressMonitor.setTicksCount(primitives.size());
                 int i=1;
                 for (OsmPrimitive primitive: primitives) {
                     if (cancelled)
                         return;
-                    String title = tr("({0}/{1}) Loading parents of primitive {2}", i+1,primitives.size(), primitive.getName());
-                    Main.pleaseWaitDlg.setTitle(title);
-                    downloadParents(primitive);
+                    progressMonitor.subTask(tr("({0}/{1}) Loading parents of primitive {2}", i+1,primitives.size(), primitive.getName()));
+                    downloadParents(primitive, progressMonitor.createSubTaskMonitor(1, false));
                     i++;
                 }
@@ -171,6 +160,4 @@
                     return;
                 lastException = e;
-            } finally {
-                setIndeterminateEnabled(false);
             }
         }
@@ -179,5 +166,5 @@
     /**
      * Refreshes the enabled state
-     * 
+     *
      */
     protected void refreshEnabled() {
Index: /trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java	(revision 1811)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.EventQueue;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -21,4 +20,6 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
 import org.openstreetmap.josm.io.OsmApi;
@@ -29,5 +30,5 @@
 /**
  * This action synchronizes a set of primitives with their state on the server.
- * 
+ *
  *
  */
@@ -36,5 +37,5 @@
     /**
      * handle an exception thrown because a primitive was deleted on the server
-     * 
+     *
      * @param id the primitive id
      */
@@ -44,5 +45,5 @@
         DataSet ds = null;
         try {
-            ds = reader.parseOsm();
+            ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
         } catch(Exception e) {
             handleUpdateException(e);
@@ -55,5 +56,5 @@
     /**
      * handle an exception thrown during updating a primitive
-     * 
+     *
      * @param id the id of the primitive
      * @param e the exception
@@ -72,5 +73,5 @@
      * handles an exception case: primitive with id <code>id</code> is not in the current
      * data set
-     * 
+     *
      * @param id the primitive id
      */
@@ -87,7 +88,7 @@
      * Updates the data for for the {@see OsmPrimitive}s in <code>selection</code>
      * with the data currently kept on the server.
-     * 
+     *
      * @param selection a collection of {@see OsmPrimitive}s to update
-     * 
+     *
      */
     public void updatePrimitives(final Collection<OsmPrimitive> selection) {
@@ -102,14 +103,4 @@
             Exception lastException;
 
-            protected void setIndeterminateEnabled(final boolean enabled) {
-                EventQueue.invokeLater(
-                        new Runnable() {
-                            public void run() {
-                                Main.pleaseWaitDlg.setIndeterminate(enabled);
-                            }
-                        }
-                );
-            }
-
             public UpdatePrimitiveTask() {
                 super("Update primitives", false /* don't ignore exception*/);
@@ -151,15 +142,13 @@
             @Override
             protected void realRun() throws SAXException, IOException, OsmTransferException {
-                setIndeterminateEnabled(true);
+                progressMonitor.indeterminateSubTask("");
                 try {
                     MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
                     reader.append(selection);
-                    ds = reader.parseOsm();
+                    ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
                 } catch(Exception e) {
                     if (cancelled)
                         return;
                     lastException = e;
-                } finally {
-                    setIndeterminateEnabled(false);
                 }
             }
@@ -172,7 +161,7 @@
      * Updates the data for for the {@see OsmPrimitive}s with id <code>id</code>
      * with the data currently kept on the server.
-     * 
+     *
      * @param id  the id of a primitive in the {@see DataSet} of the current edit layser
-     * 
+     *
      */
     public void updatePrimitive(long id) {
@@ -202,5 +191,5 @@
     /**
      * Refreshes the enabled state
-     * 
+     *
      */
     protected void refreshEnabled() {
Index: /trunk/src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 1811)
@@ -31,4 +31,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmApiException;
@@ -161,5 +162,5 @@
     /**
      * Refreshes the enabled state
-     * 
+     *
      */
     protected void refreshEnabled() {
@@ -230,5 +231,5 @@
             @Override protected void realRun() throws SAXException, IOException {
                 try {
-                    server.uploadOsm(Main.ds.version, all);
+                    server.uploadOsm(Main.ds.version, all, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
                     Main.main.createOrGetEditLayer().cleanData(server.processed, !add.isEmpty());
                 } catch (Exception sxe) {
Index: /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 1811)
@@ -16,4 +16,5 @@
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.xml.sax.SAXException;
@@ -26,17 +27,13 @@
         private GpxData rawData;
         private final boolean newLayer;
-        private String msg = "";
 
-        public Task(boolean newLayer, BoundingBoxDownloader reader, boolean silent, String msg) {
+        public Task(boolean newLayer, BoundingBoxDownloader reader, ProgressMonitor progressMonitor) {
             super(tr("Downloading GPS data"));
-            this.msg = msg;
             this.reader = reader;
             this.newLayer = newLayer;
-            this.silent = silent;
         }
 
         @Override public void realRun() throws IOException, SAXException {
-            Main.pleaseWaitDlg.setCustomText(msg);
-            rawData = reader.parseRawGps();
+            rawData = reader.parseRawGps(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
         }
 
@@ -52,6 +49,4 @@
             else
                 x.mergeFrom(layer);
-
-            Main.pleaseWaitDlg.setCustomText("");
         }
 
@@ -72,5 +67,4 @@
             if (reader != null)
                 reader.cancel();
-            Main.pleaseWaitDlg.cancel.setEnabled(false);
         }
     }
@@ -79,14 +73,7 @@
 
     public void download(DownloadAction action, double minlat, double minlon,
-            double maxlat, double maxlon) {
-        download(action, minlat, minlon, maxlat, maxlon, false, "");
-    }
-
-    public void download(DownloadAction action, double minlat, double minlon,
-            double maxlat, double maxlon, boolean silent, String message) {
+            double maxlat, double maxlon, ProgressMonitor progressMonitor) {
         Task t = new Task(action.dialog.newLayer.isSelected(),
-                new BoundingBoxDownloader(minlat, minlon, maxlat, maxlon),
-                silent,
-                message);
+                new BoundingBoxDownloader(minlat, minlon, maxlat, maxlon), progressMonitor);
         // We need submit instead of execute so we can wait for it to finish and get the error
         // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
@@ -116,7 +103,7 @@
         try {
             Task t = task.get();
-            return t.errorMessage == null
+            return t.getProgressMonitor().getErrorMessage() == null
                 ? ""
-                : t.errorMessage;
+                : t.getProgressMonitor().getErrorMessage();
         } catch (Exception e) {
             return "";
Index: /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 1811)
@@ -18,4 +18,6 @@
 import org.openstreetmap.josm.gui.download.DownloadDialog.DownloadTask;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
@@ -38,17 +40,13 @@
         private DataSet dataSet;
         private boolean newLayer;
-        private String msg = "";
 
-        public Task(boolean newLayer, OsmServerReader reader, boolean silent, String msg) {
-            super(tr("Downloading data"));
-            this.msg = msg;
+        public Task(boolean newLayer, OsmServerReader reader, ProgressMonitor progressMonitor) {
+            super(tr("Downloading data"), progressMonitor, false);
             this.reader = reader;
             this.newLayer = newLayer;
-            this.silent = silent;
         }
 
         @Override public void realRun() throws IOException, SAXException, OsmTransferException {
-            Main.pleaseWaitDlg.setCustomText(msg);
-            dataSet = reader.parseOsm();
+            dataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
         }
 
@@ -63,8 +61,5 @@
                 return; // user canceled download or error occurred
             if (dataSet.allPrimitives().isEmpty()) {
-                // If silent is set to true, we don't want to see information messages
-                if(!silent) {
-                    errorMessage = tr("No data imported.");
-                }
+                progressMonitor.setErrorMessage(tr("No data imported."));
                 // need to synthesize a download bounds lest the visual indication of downloaded
                 // area doesn't work
@@ -78,6 +73,4 @@
                 getEditLayer().mergeFrom(dataSet);
             }
-
-            Main.pleaseWaitDlg.setCustomText("");
         }
 
@@ -86,5 +79,4 @@
                 reader.cancel();
             }
-            Main.pleaseWaitDlg.cancel.setEnabled(false);
         }
     }
@@ -100,5 +92,5 @@
 
     public void download(DownloadAction action, double minlat, double minlon,
-            double maxlat, double maxlon, boolean silent, String message) {
+            double maxlat, double maxlon, ProgressMonitor progressMonitor) {
         // Swap min and max if user has specified them the wrong way round
         // (easy to do if you are crossing 0, for example)
@@ -115,16 +107,9 @@
 
         Task t = new Task(newLayer,
-                new BoundingBoxDownloader(minlat, minlon, maxlat, maxlon),
-                silent,
-                message);
+                new BoundingBoxDownloader(minlat, minlon, maxlat, maxlon), progressMonitor);
         currentBounds = new Bounds(new LatLon(minlat, minlon), new LatLon(maxlat, maxlon));
         // We need submit instead of execute so we can wait for it to finish and get the error
         // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
         task = Main.worker.submit(t, t);
-    }
-
-    public void download(DownloadAction action, double minlat, double minlon,
-            double maxlat, double maxlon) {
-        download(action, minlat, minlon, maxlat, maxlon, false, "");
     }
 
@@ -137,6 +122,5 @@
         Task t = new Task(new_layer,
                 new OsmServerLocationReader(url),
-                false,
-        "");
+                NullProgressMonitor.INSTANCE);
         task = Main.worker.submit(t, t);
     }
@@ -160,7 +144,7 @@
         try {
             Task t = task.get();
-            return t.errorMessage == null
+            return t.getProgressMonitor().getErrorMessage() == null
             ? ""
-                    : t.errorMessage;
+                    : t.getProgressMonitor().getErrorMessage();
         } catch (Exception e) {
             return "";
Index: /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskList.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskList.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskList.java	(revision 1811)
@@ -23,4 +23,6 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
@@ -33,4 +35,5 @@
 public class DownloadOsmTaskList implements Runnable {
     private List<DownloadTask> osmTasks = new LinkedList<DownloadTask>();
+    private ProgressMonitor progressMonitor;
 
     /**
@@ -39,5 +42,6 @@
      * @param The List of Rectangle2D to download
      */
-    public void download(boolean newLayer, List<Rectangle2D> rects) {
+    public void download(boolean newLayer, List<Rectangle2D> rects, ProgressMonitor progressMonitor) {
+        this.progressMonitor = progressMonitor;
         if(newLayer) {
             Layer l = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null);
@@ -46,17 +50,22 @@
         }
 
-        int i = 0;
-        for(Rectangle2D td : rects) {
-            i++;
-            DownloadTask dt = new DownloadOsmTask();
-            dt.download(null, td.getMinY(), td.getMinX(), td.getMaxY(), td.getMaxX(), true,
-                    tr("Download {0} of {1} ({2} left)", i, rects.size(), rects.size()-i));
-            osmTasks.add(dt);
-        }
-
-        // If we try to get the error message now the download task will never have been started
-        // and we'd be stuck in a classical dead lock. Instead attach this to the worker and once
-        // run() gets called all downloadTasks have finished and we can grab the error messages.
-        Main.worker.execute(this);
+        progressMonitor.beginTask(null, rects.size());
+        try {
+            int i = 0;
+            for(Rectangle2D td : rects) {
+                i++;
+                DownloadTask dt = new DownloadOsmTask();
+                ProgressMonitor childProgress = progressMonitor.createSubTaskMonitor(1, false);
+                childProgress.setSilent(true);
+                childProgress.setCustomText(tr("Download {0} of {1} ({2} left)", i, rects.size(), rects.size()-i));
+                dt.download(null, td.getMinY(), td.getMinX(), td.getMaxY(), td.getMaxX(), childProgress);
+                osmTasks.add(dt);
+            }
+        } finally {
+            // If we try to get the error message now the download task will never have been started
+            // and we'd be stuck in a classical dead lock. Instead attach this to the worker and once
+            // run() gets called all downloadTasks have finished and we can grab the error messages.
+            Main.worker.execute(this);
+        }
     }
 
@@ -72,5 +81,5 @@
         }
 
-        download(newLayer, rects);
+        download(newLayer, rects, NullProgressMonitor.INSTANCE);
     }
 
@@ -79,4 +88,5 @@
      */
     public void run() {
+        progressMonitor.finishTask();
         String errors = "";
 
@@ -109,5 +119,5 @@
      * Updates the local state of a set of primitives (given by a set of primitive
      * ids) with the state currently held on the server.
-     * 
+     *
      * @param potentiallyDeleted a set of ids to check update from the server
      */
@@ -135,5 +145,5 @@
      * the current state on the server. If yes, retrieves the current state on the server
      * and checks whether the primitives are indeed deleted on the server.
-     * 
+     *
      * @param potentiallyDeleted a set of primitives (given by their ids)
      */
@@ -177,5 +187,5 @@
      * replies true, if the primitive with id <code>id</code> was downloaded into the
      * dataset <code>ds</code>
-     * 
+     *
      * @param id the id
      * @param ds the dataset
@@ -191,9 +201,9 @@
      * replies true, if the primitive with id <code>id</code> was downloaded into the
      * dataset of one of the download tasks
-     * 
+     *
      * @param id the id
      * @return true, if the primitive with id <code>id</code> was downloaded into the
      * dataset of one of the download tasks
-     * 
+     *
      */
     public boolean wasDownloaded(long id) {
@@ -209,5 +219,5 @@
     /**
      * Replies the set of primitive ids which have been downloaded by this task list
-     * 
+     *
      * @return the set of primitive ids which have been downloaded by this task list
      */
Index: /trunk/src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java	(revision 1811)
@@ -39,10 +39,11 @@
     }
     @Override protected void realRun() {
-        Main.pleaseWaitDlg.currentAction.setText(tr("Contact {0}...", url.getHost()));
+        progressMonitor.setTicksCount(2);
         sel = mode != SearchAction.SearchMode.remove ? new LinkedList<OsmPrimitive>() : Main.ds.allNonDeletedPrimitives();
         try {
             URLConnection con = url.openConnection();
-            InputStream in = new ProgressInputStream(con, Main.pleaseWaitDlg);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading..."));
+            progressMonitor.subTask(tr("Contact {0}...", url.getHost()));
+            InputStream in = new ProgressInputStream(con, progressMonitor.createSubTaskMonitor(1, true));
+            progressMonitor.subTask(tr("Downloading..."));
             Map<Long, String> ids = idReader.parseIds(in);
             for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
@@ -55,4 +56,5 @@
                 }
             }
+            progressMonitor.worked(1);
         } catch (IOException e) {
             e.printStackTrace();
Index: /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 1811)
@@ -3,7 +3,7 @@
 import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.event.ActionEvent;
 import java.awt.GridBagLayout;
 import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 
@@ -19,5 +19,4 @@
 import javax.swing.KeyStroke;
 
-import org.openstreetmap.josm.gui.JMultilineLabel;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
Index: /trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 1811)
@@ -6,4 +6,7 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -15,10 +18,4 @@
 import javax.swing.JMenuItem;
 import javax.swing.KeyStroke;
-
-/* For the fullscreen action */
-import java.awt.Frame;
-import java.awt.GraphicsEnvironment;
-import java.awt.GraphicsDevice;
-import org.openstreetmap.josm.tools.PlatformHookUnixoid;
 
 import org.openstreetmap.josm.Main;
@@ -39,6 +36,6 @@
 import org.openstreetmap.josm.actions.GpxExportAction;
 import org.openstreetmap.josm.actions.HelpAction;
+import org.openstreetmap.josm.actions.HistoryInfoAction;
 import org.openstreetmap.josm.actions.InfoAction;
-import org.openstreetmap.josm.actions.HistoryInfoAction;
 import org.openstreetmap.josm.actions.JoinNodeWayAction;
 import org.openstreetmap.josm.actions.JosmAction;
@@ -78,4 +75,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+import org.openstreetmap.josm.tools.PlatformHookUnixoid;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -323,5 +321,5 @@
         /**
          * Refreshes the enabled state
-         * 
+         *
          */
         protected void refreshEnabled() {
Index: /trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java	(revision 1811)
@@ -2,5 +2,6 @@
 package org.openstreetmap.josm.gui;
 
-import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Frame;
 import java.awt.GridBagLayout;
 import java.awt.event.ComponentEvent;
@@ -12,5 +13,4 @@
 import javax.swing.JDialog;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JProgressBar;
@@ -25,11 +25,10 @@
     private final JProgressBar progressBar = new JProgressBar();
 
-    public final JLabel currentAction = new JLabel(I18n.tr("Contacting the OSM server..."));
+    public final JLabel currentAction = new JLabel("");
     private final JLabel customText = new JLabel("");
     public final BoundedRangeModel progress = progressBar.getModel();
     public final JButton cancel = new JButton(I18n.tr("Cancel"));
 
-    public PleaseWaitDialog(Component parent) {
-        super(JOptionPane.getFrameForComponent(parent), true);
+    private void initDialog() {
         setLayout(new GridBagLayout());
         JPanel pane = new JPanel(new GridBagLayout());
@@ -55,4 +54,14 @@
     }
 
+    public PleaseWaitDialog(Frame parent) {
+        super(parent, true);
+        initDialog();
+    }
+
+    public PleaseWaitDialog(Dialog parent) {
+        super(parent, true);
+        initDialog();
+    }
+
     public void setIndeterminate(boolean newValue) {
         UIManager.put("ProgressBar.cycleTime", UIManager.getInt("ProgressBar.repaintInterval") * 100);
Index: /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 1811)
@@ -5,17 +5,12 @@
 
 import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 
-import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 
-import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.xml.sax.SAXException;
@@ -27,34 +22,11 @@
  * @author Imi
  */
-public abstract class PleaseWaitRunnable implements Runnable {
-    public boolean silent = false;
-    public String errorMessage;
+public abstract class PleaseWaitRunnable implements Runnable, CancelListener {
 
-    private boolean closeDialogCalled = false;
     private boolean cancelled = false;
     private boolean ignoreException;
-
     private final String title;
 
-    private ActionListener cancelListener = new ActionListener(){
-        public void actionPerformed(ActionEvent e) {
-            if (!cancelled) {
-                cancelled = true;
-                cancel();
-            }
-        }
-    };
-
-    private WindowListener windowListener = new WindowAdapter(){
-        @Override public void windowClosing(WindowEvent e) {
-            if (!closeDialogCalled) {
-                if (!cancelled) {
-                    cancelled = true;
-                    cancel();
-                }
-                closeDialog();
-            }
-        }
-    };
+    protected final ProgressMonitor progressMonitor;
 
     /**
@@ -73,19 +45,12 @@
      */
     public PleaseWaitRunnable(String title, boolean ignoreException) {
-        this.title = title;
-        this.ignoreException = ignoreException;
+        this(title, new PleaseWaitProgressMonitor(), ignoreException);
     }
 
-    private void prepareDialog() {
-        // reset dialog state
-        errorMessage = null;
-        closeDialogCalled = false;
-
-        Main.pleaseWaitDlg.setTitle(title);
-        Main.pleaseWaitDlg.cancel.setEnabled(true);
-        Main.pleaseWaitDlg.setCustomText("");
-        Main.pleaseWaitDlg.cancel.addActionListener(cancelListener);
-        Main.pleaseWaitDlg.addWindowListener(windowListener);
-        Main.pleaseWaitDlg.setVisible(true);
+    public PleaseWaitRunnable(String title, ProgressMonitor progressMonitor, boolean ignoreException) {
+        this.title = title;
+        this.progressMonitor = progressMonitor == null?new PleaseWaitProgressMonitor():progressMonitor;
+        this.ignoreException = ignoreException;
+        this.progressMonitor.addCancelListener(this);
     }
 
@@ -93,23 +58,36 @@
         try {
             try {
-                realRun();
+                progressMonitor.beginTask(title);
+                try {
+                    realRun();
+                } finally {
+                    if (EventQueue.isDispatchThread()) {
+                        finish();
+                    } else {
+                        EventQueue.invokeAndWait(new Runnable() {
+                            public void run() {
+                                finish();
+                            }
+                        });
+                    }
+                }
             } catch (SAXException x) {
                 x.printStackTrace();
-                errorMessage = tr("Error while parsing")+": "+x.getMessage();
+                progressMonitor.setErrorMessage(tr("Error while parsing")+": "+x.getMessage());
             } catch (FileNotFoundException x) {
                 x.printStackTrace();
-                errorMessage = tr("File not found")+": "+x.getMessage();
+                progressMonitor.setErrorMessage(tr("File not found")+": "+x.getMessage());
             } catch (IOException x) {
                 x.printStackTrace();
-                errorMessage = x.getMessage();
+                progressMonitor.setErrorMessage(x.getMessage());
             } catch(OsmTransferException x) {
                 x.printStackTrace();
                 if (x.getCause() != null) {
-                    errorMessage = x.getCause().getMessage();
+                    progressMonitor.setErrorMessage(x.getCause().getMessage());
                 } else {
-                    errorMessage = x.getMessage();
+                    progressMonitor.setErrorMessage(x.getMessage());
                 }
             } finally {
-                closeDialog();
+                progressMonitor.finishTask();
             }
         } catch (final Throwable e) {
@@ -135,13 +113,11 @@
                 }
             }).start();
-            prepareDialog();
         } else {
-            EventQueue.invokeLater(new Runnable() {
-                public void run() {
-                    prepareDialog();
-                }
-            });
             doRealRun();
         }
+    }
+
+    public void operationCanceled() {
+        cancel();
     }
 
@@ -164,39 +140,6 @@
     protected abstract void finish();
 
-    /**
-     * Close the dialog. Usually called from worker thread.
-     */
-    public void closeDialog() {
-        if (closeDialogCalled)
-            return;
-        closeDialogCalled  = true;
-        try {
-            Runnable runnable = new Runnable(){
-                public void run() {
-                    try {
-                        finish();
-                    } finally {
-                        Main.pleaseWaitDlg.setVisible(false);
-                        Main.pleaseWaitDlg.dispose();
-                        Main.pleaseWaitDlg.removeWindowListener(windowListener);
-                        Main.pleaseWaitDlg.cancel.removeActionListener(cancelListener);
-                    }
-                    if (errorMessage != null && !silent) {
-                        JOptionPane.showMessageDialog(Main.parent, errorMessage);
-                    }
-                }
-            };
-
-            // make sure, this is called in the dispatcher thread ASAP
-            if (EventQueue.isDispatchThread()) {
-                runnable.run();
-            } else {
-                EventQueue.invokeAndWait(runnable);
-            }
-
-        } catch (InterruptedException e) {
-        } catch (InvocationTargetException e) {
-            throw new RuntimeException(e);
-        }
+    public ProgressMonitor getProgressMonitor() {
+        return progressMonitor;
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModel.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModel.java	(revision 1811)
@@ -7,6 +7,4 @@
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
-import java.io.IOException;
-import java.net.HttpURLConnection;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -15,5 +13,4 @@
 
 import javax.swing.JOptionPane;
-import javax.swing.text.html.HTML;
 
 import org.openstreetmap.josm.Main;
@@ -27,17 +24,11 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
-import org.openstreetmap.josm.gui.conflict.properties.PropertiesMerger.KeepMyVisibleStateAction;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
-import org.openstreetmap.josm.io.OsmApi;
-import org.openstreetmap.josm.io.OsmApiException;
-import org.openstreetmap.josm.io.OsmServerObjectReader;
 import org.openstreetmap.josm.io.OsmTransferException;
-import org.xml.sax.SAXException;
 
 /**
@@ -283,5 +274,5 @@
      * replies the merged visible state; null, if the merge decision is
      * {@see MergeDecisionType#UNDECIDED}.
-     * 
+     *
      * @return the merged visible state
      */
@@ -299,5 +290,5 @@
      * decides the conflict between two deleted states
      * @param decision the decision (must not be null)
-     * 
+     *
      * @throws IllegalArgumentException thrown, if decision is null
      */
@@ -314,5 +305,5 @@
      * decides the conflict between two visible states
      * @param decision the decision (must not be null)
-     * 
+     *
      * @throws IllegalArgumentException thrown, if decision is null
      */
@@ -419,5 +410,5 @@
 
     /**
-     * 
+     *
      * @param id
      */
@@ -440,5 +431,5 @@
      * User has decided to keep his local version of a primitive which had been deleted
      * on the server
-     * 
+     *
      * @param id the primitive id
      */
@@ -457,5 +448,5 @@
      * a clone of the node which we flag as new. On the next upload the
      * server will assign the node a new id.
-     * 
+     *
      * @param node the node to undelete
      */
@@ -467,5 +458,5 @@
      * displays a confirmation message. The user has to confirm that additional dependent
      * nodes should be undeleted too.
-     * 
+     *
      * @param way  the way
      * @param dependent a list of dependent nodes which have to be undelete too
@@ -532,8 +523,8 @@
     /**
      * Creates the undelete command for a way which is already deleted on the server.
-     * 
+     *
      * This method also checks whether there are additional nodes referred to by
      * this way which are deleted on the server too.
-     * 
+     *
      * @param way the way to undelete
      * @return the undelete command
@@ -550,5 +541,5 @@
         MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
         reader.append(candidates.values());
-        DataSet ds = reader.parseOsm();
+        DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
 
         ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
@@ -569,8 +560,8 @@
     /**
      * Creates an undelete command for a relation which is already deleted on the server.
-     * 
+     *
      * This method  checks whether there are additional primitives referred to by
      * this relation which are already deleted on the server.
-     * 
+     *
      * @param r the relation
      * @return the undelete command
@@ -588,5 +579,5 @@
         MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
         reader.append(candidates.values());
-        DataSet ds = reader.parseOsm();
+        DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
 
         ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 1811)
@@ -28,5 +28,4 @@
 import javax.swing.JTable;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -87,5 +86,5 @@
      * unregisters a {@see HistoryBrowserDialog}
      * @param id the id of the primitive whose history dialog is to be unregistered
-     * 
+     *
      */
     public static void unregisterHistoryBrowserDialog(long id) {
@@ -98,5 +97,5 @@
      * 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
@@ -119,5 +118,5 @@
     /**
      * builds the row with the command buttons
-     * 
+     *
      * @return the rows with the command buttons
      */
@@ -209,5 +208,5 @@
     /**
      * shows the {@see HistoryBrowserDialog} for a given {@see History}
-     * 
+     *
      * @param h the history. Must not be null.
      * @exception IllegalArgumentException thrown, if h is null
@@ -225,5 +224,5 @@
     /**
      * invoked after the asynchronous {@see HistoryLoadTask} is finished.
-     * 
+     *
      * @param task the task which is calling back.
      */
@@ -261,5 +260,5 @@
     /**
      * The table model with the history items
-     * 
+     *
      */
     class HistoryItemDataModel extends DefaultTableModel implements SelectionChangedListener{
@@ -397,45 +396,8 @@
         }
 
-        /**
-         * update the title of the {@see PleaseWaitDialog} with information about
-         * which primitive is currently loaded
-         * 
-         * @param primitive the primitive to be loaded
-         */
-        protected void notifyStartLoadingHistory(final OsmPrimitive primitive) {
-            SwingUtilities.invokeLater(
-                    new Runnable() {
-                        public void run() {
-                            Main.pleaseWaitDlg.setTitle(
-                                    tr("Loading history for {0} with id {1}",
-                                            OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular(),
-                                            Long.toString(primitive.id)
-                                    )
-                            );
-                        }
-                    }
-            );
-        }
-
-        /**
-         * enables/disables interminate progress indication in the {@see PleaseWaitDialog}
-         * 
-         * @param enabled true, if interminate progress indication is to enabled; false, otherwise
-         */
-        protected void setInterminateEnabled(final boolean enabled) {
-            SwingUtilities.invokeLater(
-                    new Runnable() {
-                        public void run() {
-                            Main.pleaseWaitDlg.setIndeterminate(enabled);
-                        }
-                    }
-            );
-        }
-
         @Override
         protected void realRun() throws SAXException, IOException, OsmTransferException {
             Collection<OsmPrimitive> selection = Main.ds.getSelected();
             Iterator<OsmPrimitive> it = selection.iterator();
-            setInterminateEnabled(true);
             try {
                 while(it.hasNext()) {
@@ -447,10 +409,12 @@
                         continue;
                     }
-                    notifyStartLoadingHistory(primitive);
+                    progressMonitor.indeterminateSubTask(tr("Loading history for {0} with id {1}",
+                            OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular(),
+                            Long.toString(primitive.id)));
                     OsmServerHistoryReader reader = null;
                     HistoryDataSet ds = null;
                     try {
                         reader = new OsmServerHistoryReader(OsmPrimitiveType.from(primitive), primitive.id);
-                        ds = reader.parseHistory();
+                        ds = reader.parseHistory(progressMonitor.createSubTaskMonitor(1, false));
                     } catch(OsmTransferException e) {
                         if (cancelled)
@@ -463,6 +427,4 @@
                 lastException = e;
                 return;
-            } finally {
-                setInterminateEnabled(false);
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 1811)
@@ -4,6 +4,6 @@
 
 import java.awt.BorderLayout;
+import java.awt.Dialog;
 import java.awt.Dimension;
-import java.awt.EventQueue;
 import java.awt.FlowLayout;
 import java.awt.GridBagConstraints;
@@ -60,4 +60,6 @@
 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmServerObjectReader;
@@ -150,5 +152,5 @@
         tabbedPane.add(tr("Tags and Members"), pnl);
         if (relation != null && relation.id > 0) {
-            tabbedPane.add(tr("Parent Relations"), new ReferringRelationsBrowser(getLayer(), referrerModel));
+            tabbedPane.add(tr("Parent Relations"), new ReferringRelationsBrowser(getLayer(), referrerModel, this));
         }
 
@@ -166,5 +168,5 @@
     /**
      * builds the panel with the OK and  the Cancel button
-     * 
+     *
      * @return the panel with the OK and  the Cancel button
      */
@@ -181,5 +183,5 @@
     /**
      * build the panel with the buttons on the left
-     * 
+     *
      * @return
      */
@@ -220,5 +222,5 @@
     /**
      * builds the panel with the tag editor
-     * 
+     *
      * @return the panel with the tag editor
      */
@@ -287,5 +289,5 @@
     /**
      * builds the panel for the relation member editor
-     * 
+     *
      * @return the panel for the relation member editor
      */
@@ -385,5 +387,5 @@
     /**
      * builds the panel with the table displaying the currently selected primitives
-     * 
+     *
      * @return
      */
@@ -401,5 +403,5 @@
      * builds the {@see JSplitPane} which divides the editor in an upper and a lower
      * half
-     * 
+     *
      * @return the split panel
      */
@@ -415,5 +417,5 @@
     /**
      * build the panel with the buttons on the left
-     * 
+     *
      * @return
      */
@@ -459,5 +461,5 @@
     /**
      * build the panel with the buttons for adding or removing the current selection
-     * 
+     *
      * @return
      */
@@ -576,5 +578,5 @@
                         JOptionPane.WARNING_MESSAGE
                 );
-                JDialog dialog = op.createDialog(Main.pleaseWaitDlg, tr("Conflict created"));
+                JDialog dialog = op.createDialog(this, tr("Conflict created"));
                 dialog.setAlwaysOnTop(true);
                 dialog.setModal(true);
@@ -604,5 +606,5 @@
         if (!memberTableModel.hasIncompleteMembers())
             return;
-        Main.worker.submit(new DownloadTask());
+        Main.worker.submit(new DownloadTask(this));
     }
 
@@ -981,5 +983,5 @@
     /**
      * Action for editing the currently selected relation
-     * 
+     *
      *
      */
@@ -1014,13 +1016,14 @@
     /**
      * The asynchronous task for downloading relation members.
-     * 
+     *
      *
      */
     class DownloadTask extends PleaseWaitRunnable {
         private boolean cancelled;
+        private int conflictsCount;
         private Exception lastException;
 
-        public DownloadTask() {
-            super(tr("Download relation members"), false /* don't ignore exception */);
+        public DownloadTask(Dialog parent) {
+            super(tr("Download relation members"), new PleaseWaitProgressMonitor(parent), false /* don't ignore exception */);
         }
         @Override
@@ -1047,6 +1050,20 @@
             if (cancelled) return;
             memberTableModel.updateMemberReferences(getLayer().data);
-            if (lastException == null) return;
-            showLastException();
+            if (lastException != null) {
+                showLastException();
+            }
+
+            if (conflictsCount > 0) {
+                JOptionPane op = new JOptionPane(
+                        tr("There were {0} conflicts during import.",
+                                conflictsCount),
+                                JOptionPane.WARNING_MESSAGE
+                );
+                JDialog dialog = op.createDialog(GenericRelationEditor.this, tr("Conflicts in data"));
+                dialog.setAlwaysOnTop(true);
+                dialog.setModal(true);
+                dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+                dialog.setVisible(true);
+            }
         }
 
@@ -1054,15 +1071,7 @@
         protected void realRun() throws SAXException, IOException, OsmTransferException {
             try {
-                SwingUtilities.invokeLater(
-                        new Runnable() {
-                            public void run() {
-                                Main.pleaseWaitDlg.setAlwaysOnTop(true);
-                                Main.pleaseWaitDlg.toFront();
-                                Main.pleaseWaitDlg.setIndeterminate(true);
-                            }
-                        }
-                );
+                progressMonitor.indeterminateSubTask("");
                 OsmServerObjectReader reader = new OsmServerObjectReader(getRelation().id, OsmPrimitiveType.RELATION, true);
-                DataSet dataSet = reader.parseOsm();
+                DataSet dataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
                 if (dataSet != null) {
                     final MergeVisitor visitor = new MergeVisitor(getLayer().data, dataSet);
@@ -1084,17 +1093,8 @@
                             }
                     );
-                    if (visitor.getConflicts().isEmpty())
-                        return;
-                    getLayer().getConflicts().add(visitor.getConflicts());
-                    JOptionPane op = new JOptionPane(
-                            tr("There were {0} conflicts during import.",
-                                    visitor.getConflicts().size()),
-                                    JOptionPane.WARNING_MESSAGE
-                    );
-                    JDialog dialog = op.createDialog(Main.pleaseWaitDlg, tr("Conflicts in data"));
-                    dialog.setAlwaysOnTop(true);
-                    dialog.setModal(true);
-                    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-                    dialog.setVisible(true);
+                    if (!visitor.getConflicts().isEmpty()) {
+                        getLayer().getConflicts().add(visitor.getConflicts());
+                        conflictsCount = visitor.getConflicts().size();
+                    }
                 }
             } catch(Exception e) {
@@ -1104,13 +1104,4 @@
                 }
                 lastException = e;
-            } finally {
-                SwingUtilities.invokeLater(
-                        new Runnable() {
-                            public void run() {
-                                Main.pleaseWaitDlg.setAlwaysOnTop(false);
-                                Main.pleaseWaitDlg.setIndeterminate(false);
-                            }
-                        }
-                );
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java	(revision 1811)
@@ -5,5 +5,5 @@
 
 import java.awt.BorderLayout;
-import java.awt.EventQueue;
+import java.awt.Dialog;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
@@ -14,5 +14,4 @@
 
 import javax.swing.AbstractAction;
-import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JDialog;
@@ -37,4 +36,5 @@
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmServerBackreferenceReader;
@@ -45,5 +45,5 @@
 /**
  * This is browser for a list of relations which refer to another relations
- * 
+ *
  *
  */
@@ -56,4 +56,5 @@
     private JCheckBox cbReadFull;
     private EditAction editAction;
+    private final GenericRelationEditor relationEditor;
 
     /**
@@ -83,5 +84,6 @@
     }
 
-    public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model) {
+    public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model, GenericRelationEditor relationEditor) {
+        this.relationEditor = relationEditor;
         this.model = model;
         this.layer = layer;
@@ -111,5 +113,5 @@
         public void actionPerformed(ActionEvent e) {
             boolean full = cbReadFull.isSelected();
-            ReloadTask task = new ReloadTask(full);
+            ReloadTask task = new ReloadTask(full, relationEditor);
             Main.worker.submit(task);
         }
@@ -130,5 +132,5 @@
     /**
      * Action for editing the currently selected relation
-     * 
+     *
      */
     class EditAction extends AbstractAction implements ListSelectionListener {
@@ -181,16 +183,6 @@
         private boolean full;
 
-        protected void setIndeterminateEnabled(final boolean enabled) {
-            EventQueue.invokeLater(
-                    new Runnable() {
-                        public void run() {
-                            Main.pleaseWaitDlg.setIndeterminate(enabled);
-                        }
-                    }
-            );
-        }
-
-        public ReloadTask(boolean full) {
-            super(tr("Download referring relations"), false /* don't ignore exception */);
+        public ReloadTask(boolean full, Dialog parent) {
+            super(tr("Download referring relations"), new PleaseWaitProgressMonitor(parent), false /* don't ignore exception */);
             referrers = null;
         }
@@ -237,9 +229,7 @@
         protected void realRun() throws SAXException, IOException, OsmTransferException {
             try {
-                Main.pleaseWaitDlg.setAlwaysOnTop(true);
-                Main.pleaseWaitDlg.toFront();
-                setIndeterminateEnabled(true);
+                progressMonitor.indeterminateSubTask(null);
                 OsmServerBackreferenceReader reader = new OsmServerBackreferenceReader(model.getRelation(), full);
-                referrers = reader.parseOsm();
+                referrers = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
                 if (referrers != null) {
                     final MergeVisitor visitor = new MergeVisitor(getLayer().data, referrers);
@@ -270,5 +260,5 @@
                                     JOptionPane.WARNING_MESSAGE
                     );
-                    JDialog dialog = op.createDialog(Main.pleaseWaitDlg, tr("Conflicts in data"));
+                    JDialog dialog = op.createDialog(ReferringRelationsBrowser.this, tr("Conflicts in data"));
                     dialog.setAlwaysOnTop(true);
                     dialog.setModal(true);
@@ -282,7 +272,4 @@
                 }
                 lastException = e;
-            } finally {
-                Main.pleaseWaitDlg.setAlwaysOnTop(false);
-                setIndeterminateEnabled(false);
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java	(revision 1811)
@@ -5,4 +5,7 @@
 
 import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridBagLayout;
+import java.awt.Toolkit;
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
@@ -10,7 +13,4 @@
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
-import java.awt.Font;
-import java.awt.GridBagLayout;
-import java.awt.Toolkit;
 import java.util.ArrayList;
 import java.util.List;
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.tools.GBC;
@@ -51,16 +52,9 @@
     public interface DownloadTask {
         /**
-         * Execute the download using the given bounding box
+         * Execute the download using the given bounding box. Set silent on progressMonitor
+         * if no error messages should be popped up.
          */
         void download(DownloadAction action, double minlat, double minlon,
-                double maxlat, double maxlon);
-
-        /**
-         * Execute the download using the given bounding box. Set silent to true if no error
-         * messages should be popped up. Message can be used to display an additional text below
-         * the default description.
-         */
-        void download(DownloadAction action, double minlat, double minlon,
-                double maxlat, double maxlon, boolean silent, String message);
+                double maxlat, double maxlon, ProgressMonitor progressMonitor);
 
         /**
Index: /trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 1811)
@@ -270,5 +270,4 @@
 
     private static final class Loader extends PleaseWaitRunnable {
-        boolean cancelled = false;
         private GeoImageLayer layer;
         private final Collection<File> files;
@@ -280,5 +279,5 @@
         }
         @Override protected void realRun() throws IOException {
-            Main.pleaseWaitDlg.currentAction.setText(tr("Read GPX..."));
+            progressMonitor.subTask(tr("Read GPX..."));
             LinkedList<TimedPoint> gps = new LinkedList<TimedPoint>();
 
@@ -303,5 +302,5 @@
 
             if (gps.isEmpty()) {
-                errorMessage = tr("No images with readable timestamps found.");
+                progressMonitor.setErrorMessage(tr("No images with readable timestamps found."));
                 return;
             }
@@ -309,11 +308,9 @@
             // read the image files
             ArrayList<ImageEntry> data = new ArrayList<ImageEntry>(files.size());
-            int i = 0;
-            Main.pleaseWaitDlg.progress.setMaximum(files.size());
+            progressMonitor.setTicksCount(files.size());
             for (File f : files) {
-                if (cancelled)
+                if (progressMonitor.isCancelled())
                     break;
-                Main.pleaseWaitDlg.currentAction.setText(tr("Reading {0}...",f.getName()));
-                Main.pleaseWaitDlg.progress.setValue(i++);
+                progressMonitor.subTask(tr("Reading {0}...",f.getName()));
 
                 ImageEntry e = new ImageEntry(f);
@@ -327,4 +324,5 @@
 
                 data.add(e);
+                progressMonitor.worked(1);
             }
             layer = new GeoImageLayer(data, gps);
@@ -335,5 +333,8 @@
                 Main.main.addLayer(layer);
         }
-        @Override protected void cancel() {cancelled = true;}
+        @Override
+        protected void cancel() {
+
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1811)
@@ -51,5 +51,4 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxRoute;
 import org.openstreetmap.josm.data.gpx.GpxTrack;
 import org.openstreetmap.josm.data.gpx.WayPoint;
@@ -63,4 +62,5 @@
 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
 import org.openstreetmap.josm.tools.AudioUtil;
 import org.openstreetmap.josm.tools.DateUtils;
@@ -842,5 +842,5 @@
                 return;
 
-            new DownloadOsmTaskList().download(false, toDownload);
+            new DownloadOsmTaskList().download(false, toDownload, new PleaseWaitProgressMonitor());
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java	(revision 1811)
@@ -0,0 +1,388 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Queue;
+
+
+public abstract class AbstractProgressMonitor implements ProgressMonitor {
+
+    private static class Request {
+        AbstractProgressMonitor originator;
+        int childTicks;
+        double currentValue;
+
+        String title;
+        String customText;
+        String extraText;
+        Boolean intermediate;
+    }
+
+    private final CancelHandler cancelHandler;
+
+    protected enum State {INIT, IN_TASK, IN_SUBTASK, FINISHED}
+
+    protected State state = State.INIT;
+
+    int ticksCount;
+    int ticks;
+    private int childTicks;
+
+    private String taskTitle;
+    private String customText;
+    private String extraText;
+    private String shownTitle;
+    private String shownCustomText;
+    private boolean intermediateTask;
+
+    private Queue<Request> requests = new LinkedList<Request>();
+    private AbstractProgressMonitor currentChild;
+    private Request requestedState = new Request();
+
+    private boolean silent;
+    private String errorMessage;
+
+    protected abstract void doBeginTask();
+    protected abstract void doFinishTask();
+    protected abstract void doSetIntermediate(boolean value);
+    protected abstract void doSetTitle(String title);
+    protected abstract void doSetCustomText(String title);
+    protected abstract void doSetErrorMessage(String message);
+
+    protected AbstractProgressMonitor(CancelHandler cancelHandler) {
+        this.cancelHandler = cancelHandler;
+    }
+
+    protected void checkState(State... expectedStates) {
+        for (State s:expectedStates) {
+            if (s == state) {
+                return;
+            }
+        }
+        throw new ProgressException("Expected states are %s but current state is %s", Arrays.asList(expectedStates).toString(), state);
+    }
+
+    /*=======
+     * Tasks
+     =======*/
+
+    public void beginTask(String title) {
+        beginTask(title, DEFAULT_TICKS);
+    }
+
+    public synchronized void beginTask(final String title, int ticks) {
+        this.taskTitle = title;
+        checkState(State.INIT);
+        state = State.IN_TASK;
+        doBeginTask();
+        setTicksCount(ticks);
+        resetState();
+    }
+
+    public synchronized void finishTask() {
+        if (state != State.FINISHED) {
+
+            if (state == State.IN_SUBTASK) {
+                // Make sure the subtask didn't start yet (once task start it must be finished)
+                boolean broken = currentChild.state != State.INIT;
+                for (Request request:requests) {
+                    broken = broken | request.originator.state != State.INIT;
+                }
+                if (broken) {
+                    throw new ProgressException("Cannot call finishTask when there are unfinished tasks");
+                } else {
+                    state = State.IN_TASK;
+                }
+            }
+
+            checkState(State.IN_TASK);
+            state = State.FINISHED;
+            doFinishTask();
+        }
+    }
+
+    public synchronized void invalidate() {
+        checkState(State.INIT);
+        state = State.FINISHED;
+        doFinishTask();
+    }
+
+    public synchronized void subTask(final String title) {
+        if (state == State.IN_SUBTASK) {
+            if (title != null) {
+                requestedState.title = title;
+            }
+            requestedState.intermediate = false;
+        } else {
+            checkState(State.IN_TASK);
+            if (title != null) {
+                this.taskTitle = title;
+                resetState();
+            }
+            this.intermediateTask = false;
+            doSetIntermediate(false);
+        }
+    }
+
+    public synchronized void indeterminateSubTask(String title) {
+        if (state == State.IN_SUBTASK) {
+            if (title != null) {
+                requestedState.title = title;
+            }
+            requestedState.intermediate = true;
+        } else {
+            checkState(State.IN_TASK);
+            if (title != null) {
+                this.taskTitle = title;
+                resetState();
+            }
+            this.intermediateTask = true;
+            doSetIntermediate(true);
+        }
+    }
+
+    public synchronized void setCustomText(String text) {
+        if (state == State.IN_SUBTASK) {
+            requestedState.customText = text;
+        } else {
+            this.customText = text;
+            resetState();
+        }
+    }
+
+    public synchronized void setExtraText(String text) {
+        if (state == State.IN_SUBTASK) {
+            requestedState.extraText = text;
+        } else {
+            this.extraText = text;
+            resetState();
+        }
+    }
+
+    private void resetState() {
+        String newTitle;
+        if (extraText != null) {
+            newTitle = taskTitle + " " + extraText;
+        } else {
+            newTitle = taskTitle;
+        }
+
+        if (newTitle == null?shownTitle != null:!newTitle.equals(shownTitle)) {
+            shownTitle = newTitle;
+            doSetTitle(shownTitle);
+        }
+
+        if (customText == null?shownCustomText != null:!customText.equals(shownCustomText)) {
+            shownCustomText = customText;
+            doSetCustomText(shownCustomText);
+        }
+        doSetIntermediate(intermediateTask);
+    }
+
+    public void cancel() {
+        cancelHandler.cancel();
+    }
+
+    public boolean isCancelled() {
+        return cancelHandler.isCanceled();
+    }
+
+    public void addCancelListener(CancelListener listener) {
+        cancelHandler.addCancelListener(listener);
+    }
+
+    public void removeCancelListener(CancelListener listener) {
+        cancelHandler.removeCancelListener(listener);
+    }
+
+    /*=================
+     * Ticks handling
+    ==================*/
+
+    abstract void updateProgress(double value);
+
+    public synchronized void setTicks(int ticks) {
+        if (ticks >= ticksCount) {
+            ticks = ticksCount - 1;
+        }
+        this.ticks = ticks;
+        internalUpdateProgress(0);
+    }
+
+    public synchronized void setTicksCount(int ticks) {
+        this.ticksCount = ticks;
+        internalUpdateProgress(0);
+    }
+
+    public void worked(int ticks) {
+        if (ticks == ALL_TICKS) {
+            setTicks(this.ticksCount - 1);
+        } else {
+            setTicks(this.ticks + ticks);
+        }
+    }
+
+    private void internalUpdateProgress(double childProgress) {
+        if (childProgress > 1) {
+            childProgress = 1;
+        }
+        checkState(State.IN_TASK, State.IN_SUBTASK);
+        updateProgress(ticksCount == 0?0:(ticks + childProgress * childTicks) / ticksCount);
+    }
+
+    public synchronized int getTicks() {
+        return ticks;
+    }
+
+    /*==========
+     * Subtasks
+     ==========*/
+
+    public synchronized ProgressMonitor createSubTaskMonitor(int ticks, boolean internal) {
+        if (ticks == ALL_TICKS) {
+            ticks = ticksCount - this.ticks;
+        }
+
+        if (state == State.IN_SUBTASK) {
+            Request request = new Request();
+            request.originator = new ChildProgress(this, cancelHandler, internal);
+            request.childTicks = ticks;
+            requests.add(request);
+            return request.originator;
+        } else {
+            checkState(State.IN_TASK);
+            state = State.IN_SUBTASK;
+            this.childTicks = ticks;
+            currentChild = new ChildProgress(this, cancelHandler, internal);
+            return currentChild;
+        }
+    }
+
+    private void applyChildRequest(Request request) {
+        if (request.customText != null) {
+            doSetCustomText(request.customText);
+        }
+
+        if (request.title != null) {
+            doSetTitle(request.title);
+        }
+
+        if (request.intermediate != null) {
+            doSetIntermediate(request.intermediate);
+        }
+
+        internalUpdateProgress(request.currentValue);
+    }
+
+    private void applyThisRequest(Request request) {
+        if (request.customText != null) {
+            this.customText = request.customText;
+        }
+
+        if (request.title != null) {
+            this.taskTitle = request.title;
+        }
+
+        if (request.intermediate != null) {
+            this.intermediateTask = request.intermediate;
+        }
+
+        if (request.extraText != null) {
+            this.extraText = request.extraText;
+        }
+
+        resetState();
+    }
+
+    protected synchronized void childFinished(AbstractProgressMonitor child) {
+        checkState(State.IN_SUBTASK);
+        if (currentChild == child) {
+            setTicks(ticks + childTicks);
+            if (requests.isEmpty()) {
+                state = State.IN_TASK;
+                applyThisRequest(requestedState);
+                requestedState = new Request();
+            } else {
+                Request newChild = requests.poll();
+                currentChild = newChild.originator;
+                childTicks = newChild.childTicks;
+                applyChildRequest(newChild);
+            }
+        } else {
+            Iterator<Request> it = requests.iterator();
+            while (it.hasNext()) {
+                if (it.next().originator == child) {
+                    it.remove();
+                    return;
+                }
+            }
+            throw new ProgressException("Subtask %s not found", child);
+        }
+    }
+
+    private Request getRequest(AbstractProgressMonitor child) {
+        for (Request request:requests) {
+            if (request.originator == child) {
+                return request;
+            }
+        }
+        throw new ProgressException("Subtask %s not found", child);
+    }
+
+    protected synchronized void childSetProgress(AbstractProgressMonitor child, double value) {
+        checkState(State.IN_SUBTASK);
+        if (currentChild == child) {
+            internalUpdateProgress(value);
+        } else {
+            getRequest(child).currentValue = value;
+        }
+    }
+
+    protected synchronized void childSetTitle(AbstractProgressMonitor child, String title) {
+        checkState(State.IN_SUBTASK);
+        if (currentChild == child) {
+            doSetTitle(title);
+        } else {
+            getRequest(child).title = title;
+        }
+    }
+
+    protected synchronized void childSetCustomText(AbstractProgressMonitor child, String customText) {
+        checkState(State.IN_SUBTASK);
+        if (currentChild == child) {
+            doSetCustomText(customText);
+        } else {
+            getRequest(child).customText = customText;
+        }
+    }
+
+    protected synchronized void childSetIntermediate(AbstractProgressMonitor child, boolean value) {
+        checkState(State.IN_SUBTASK);
+        if (currentChild == child) {
+            doSetIntermediate(value);
+        } else {
+            getRequest(child).intermediate = value;
+        }
+    }
+
+    /*======================
+     * Silent/error message
+     ======================*/
+    public synchronized void setSilent(boolean value) {
+        this.silent = value;
+    }
+
+    public synchronized void setErrorMessage(String message) {
+        this.errorMessage = message;
+        if (!silent) {
+            doSetErrorMessage(message);
+        }
+    }
+
+    public synchronized String getErrorMessage() {
+        return errorMessage;
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/CancelHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/CancelHandler.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/CancelHandler.java	(revision 1811)
@@ -0,0 +1,35 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
+
+public class CancelHandler {
+
+    private boolean isCanceled;
+    private List<CancelListener> listeners = new ArrayList<CancelListener>();
+
+    public synchronized void cancel() {
+        if (!isCanceled) {
+            isCanceled = true;
+            for (CancelListener listener:listeners) {
+                listener.operationCanceled();
+            }
+        }
+    }
+
+    public synchronized boolean isCanceled() {
+        return isCanceled;
+    }
+
+    public synchronized void addCancelListener(CancelListener listener) {
+        listeners.add(listener);
+    }
+
+    public synchronized void removeCancelListener(CancelListener listener) {
+        listeners.remove(listener);
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java	(revision 1811)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+class ChildProgress extends AbstractProgressMonitor {
+
+    private final AbstractProgressMonitor parent;
+    private final boolean internal;
+
+    public ChildProgress(AbstractProgressMonitor parent, CancelHandler cancelHandler, boolean internal) {
+        super(cancelHandler);
+        this.parent = parent;
+        this.internal = internal;
+    }
+
+    @Override
+    void updateProgress(double value) {
+        parent.childSetProgress(this, value);
+    }
+
+    @Override
+    protected void doBeginTask() {
+    }
+
+    @Override
+    protected void doSetCustomText(String title) {
+        if (!internal) {
+            parent.childSetCustomText(this, title);
+        }
+    }
+
+    @Override
+    protected void doSetTitle(String title) {
+        if (!internal) {
+            parent.childSetTitle(this, title);
+        }
+    }
+
+    @Override
+    protected void doSetIntermediate(boolean value) {
+        if (!internal) {
+            parent.childSetIntermediate(this, value);
+        }
+    }
+
+    @Override
+    protected void doSetErrorMessage(String message) {
+        parent.setErrorMessage(message);
+    }
+
+    @Override
+    protected void doFinishTask() {
+        parent.childFinished(this);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java	(revision 1811)
@@ -0,0 +1,76 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+
+public class NullProgressMonitor implements ProgressMonitor {
+
+    public static final ProgressMonitor INSTANCE = new NullProgressMonitor();
+
+    private NullProgressMonitor() {
+
+    }
+
+    public void addCancelListener(CancelListener listener) {
+    }
+
+    public void beginTask(String title) {
+    }
+
+    public void beginTask(String title, int ticks) {
+    }
+
+    public void cancel() {
+    }
+
+    public ProgressMonitor createSubTaskMonitor(int ticks, boolean internal) {
+        return INSTANCE;
+    }
+
+    public void finishTask() {
+    }
+
+    public String getErrorMessage() {
+        return null;
+    }
+
+    public int getTicks() {
+        return 0;
+    }
+
+    public void indeterminateSubTask(String title) {
+    }
+
+    public void invalidate() {
+    }
+
+    public boolean isCancelled() {
+        return false;
+    }
+
+    public void removeCancelListener(CancelListener listener) {
+    }
+
+    public void setCustomText(String text) {
+    }
+
+    public void setErrorMessage(String message) {
+    }
+
+    public void setExtraText(String text) {
+    }
+
+    public void setSilent(boolean value) {
+    }
+
+    public void setTicks(int ticks) {
+    }
+
+    public void setTicksCount(int ticks) {
+    }
+
+    public void subTask(String title) {
+    }
+
+    public void worked(int ticks) {
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java	(revision 1811)
@@ -0,0 +1,165 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+import java.awt.Dialog;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.PleaseWaitDialog;
+
+
+public class PleaseWaitProgressMonitor extends AbstractProgressMonitor {
+
+    private static final int PROGRESS_BAR_MAX = 100;
+    private final Window dialogParent;
+
+    private PleaseWaitDialog dialog;
+
+    public PleaseWaitProgressMonitor() {
+        this(JOptionPane.getFrameForComponent(Main.map));
+    }
+
+    public PleaseWaitProgressMonitor(Window dialogParent) {
+        super(new CancelHandler());
+        this.dialogParent = dialogParent;
+    }
+
+    private ActionListener cancelListener = new ActionListener(){
+        public void actionPerformed(ActionEvent e) {
+            cancel();
+        }
+    };
+
+    private WindowListener windowListener = new WindowAdapter(){
+        @Override public void windowClosing(WindowEvent e) {
+            cancel();
+            closeDialog();
+        }
+    };
+
+    private void closeDialog() {
+        try {
+            Runnable runnable = new Runnable(){
+                public void run() {
+                }
+            };
+
+            // make sure, this is called in the dispatcher thread ASAP
+            if (EventQueue.isDispatchThread()) {
+                runnable.run();
+            } else {
+                EventQueue.invokeAndWait(runnable);
+            }
+
+        } catch (InterruptedException e) {
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void doInEDT(Runnable runnable) {
+        EventQueue.invokeLater(runnable);
+    }
+
+    public void doBeginTask() {
+        doInEDT(new Runnable() {
+            public void run() {
+                if (dialogParent instanceof Frame) {
+                    dialog = new PleaseWaitDialog((Frame)dialogParent);
+                } else if (dialogParent instanceof Dialog) {
+                    dialog = new PleaseWaitDialog((Dialog)dialogParent);
+                } else {
+                    throw new ProgressException("PleaseWaitDialog parent must be either Frame or Dialog");
+                }
+
+                dialog.cancel.setEnabled(true);
+                dialog.setCustomText("");
+                dialog.cancel.addActionListener(cancelListener);
+                dialog.addWindowListener(windowListener);
+                dialog.progress.setMaximum(PROGRESS_BAR_MAX);
+                dialog.setVisible(true);
+            }
+        });
+    }
+
+    public void doFinishTask() {
+        doInEDT(new Runnable() {
+            public void run() {
+                if (dialog != null) {
+                    dialog.setVisible(false);
+                    dialog.dispose();
+                    dialog.removeWindowListener(windowListener);
+                    dialog.cancel.removeActionListener(cancelListener);
+                    if (getErrorMessage() != null) {
+                        JOptionPane.showMessageDialog(Main.parent, getErrorMessage());
+                    }
+                    dialog = null;
+                }
+            }
+        });
+    }
+
+    public void worked(int ticks) {
+        this.ticks += ticks;
+        updateProgress(0);
+    }
+
+    protected void updateProgress(final double progressValue) {
+        doInEDT(new Runnable() {
+            public void run() {
+                dialog.progress.setValue((int)(progressValue * PROGRESS_BAR_MAX));
+            }
+        });
+    }
+
+    @Override
+    protected void doSetCustomText(final String title) {
+        checkState(State.IN_TASK, State.IN_SUBTASK);
+        doInEDT(new Runnable() {
+            public void run() {
+                dialog.setCustomText(title);
+            }
+        });
+    }
+
+    @Override
+    protected void doSetTitle(final String title) {
+        checkState(State.IN_TASK, State.IN_SUBTASK);
+        doInEDT(new Runnable() {
+            public void run() {
+                dialog.currentAction.setText(title);
+            }
+        });
+    }
+
+    @Override
+    protected void doSetIntermediate(final boolean value) {
+        doInEDT(new Runnable() {
+            public void run() {
+                if (value && dialog.progress.getValue() == 0) {
+                    // Enable only if progress is at the begging. Doing intermediate progress in the middle
+                    // will hide already reached progress
+                    dialog.setIndeterminate(true);
+                } else {
+                    dialog.setIndeterminate(false);
+                }
+            }
+        });
+    }
+
+    @Override
+    protected void doSetErrorMessage(String message) {
+        // Do nothing
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/ProgressException.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/ProgressException.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/ProgressException.java	(revision 1811)
@@ -0,0 +1,10 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+public class ProgressException extends RuntimeException {
+
+    public ProgressException(String message, Object... args) {
+        super(String.format(message, args));
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java	(revision 1811)
@@ -0,0 +1,118 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+/**
+ * Typical usecase is:
+ * <pre>
+ *   monitor.beginTask()
+ *   try {
+ *     .. do some work
+ *     monitor.worked()
+ *     monitor.subTask()/monitor.intermediateTask()
+ *     .. do some work
+ *     monitor.worked()
+ *   } finally {
+ *     monitor.finishTask();
+ *   }
+ * </pre>
+ *
+ * {@link #subTask(String)} and {@link #indeterminateSubTask(String)} has nothing to do with logical
+ * structure of the work, they just show task title to the user.
+ *
+ * If task consists of multiple tasks then {@link #createSubTaskMonitor(int, boolean)} may be used. It
+ * will create new ProgressMonitor, then can be passed to the subtask. Subtask doesn't know whether
+ * it runs standalono or as a part of other task. Progressbar will be updated so that total progress is
+ * shown, not just progress of the subtask
+ *
+ * All ProgressMonitor implemenenatations should be thread safe.
+ *
+ */
+public interface ProgressMonitor {
+
+    public interface CancelListener {
+        void operationCanceled();
+    }
+
+    public final int DEFAULT_TICKS = 100;
+
+    /**
+     * Can be used with {@link #worked(int)} and {@link #createSubTaskMonitor(int, boolean)} to
+     * express that the task should use all remaining ticks
+     */
+    public final int ALL_TICKS = -1;
+
+    void beginTask(String title);
+
+    /**
+     * Starts this progress monitor. Must be called excatly once
+     * @param title
+     * @param ticks
+     */
+    void beginTask(String title, int ticks);
+    /**
+     * Finish this progress monitor, close the dialog or inform the parent progress monitor
+     * that it can continue with other tasks. Must be called at least once (if called multiply times
+     * then futher calls are ignored)
+     */
+    void finishTask();
+    /**
+     * Can be used if method receive ProgressMonitor but it's not interested progress monitoring.
+     * Basically replaces {@link #beginTask(String)} and {@link #finishTask()}
+     */
+    void invalidate();
+
+    /**
+     *
+     * @param ticks Number of total work units
+     */
+    void setTicksCount(int ticks);
+    /**
+     *
+     * @param ticks Number of work units already done
+     */
+    void setTicks(int ticks);
+    int getTicks();
+    /**
+     * Increase number of already done work units by ticks
+     * @param ticks
+     */
+    void worked(int ticks);
+
+    /**
+     * Subtask that will show progress runing back and forworth
+     * @param title Can be null, in that case task title is not changed
+     */
+    void indeterminateSubTask(String title);
+    /**
+     * Normal subtask
+     * @param title Can be null, in that case task title is not changed
+     */
+    void subTask(String title);
+    /**
+     * Shows additonal text
+     */
+    void setCustomText(String text);
+    /**
+     * Show extra text after normal task title. Hack for ProgressInputStream to show number of kB
+     * already downloaded
+     * @param text
+     */
+    void setExtraText(String text);
+
+    /**
+     * Creates subtasks monitor.
+     * @param ticks Number of work units that should be done when subtask finishes
+     * @param internal If true then subtask can't modify task title/custom text
+     * @return
+     */
+    ProgressMonitor createSubTaskMonitor(int ticks, boolean internal);
+
+    boolean isCancelled();
+    void cancel();
+    void addCancelListener(CancelListener listener);
+    void removeCancelListener(CancelListener listener);
+
+    void setSilent(boolean value);
+    void setErrorMessage(String message);
+    String getErrorMessage();
+}
Index: /trunk/src/org/openstreetmap/josm/gui/progress/StackableProgress.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/progress/StackableProgress.java	(revision 1811)
+++ /trunk/src/org/openstreetmap/josm/gui/progress/StackableProgress.java	(revision 1811)
@@ -0,0 +1,7 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+public interface StackableProgress {
+    public void setChildProgress(double value);
+    public void setSubTaskName(String value);
+}
Index: /trunk/src/org/openstreetmap/josm/io/BoundingBoxDownloader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/BoundingBoxDownloader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/BoundingBoxDownloader.java	(revision 1811)
@@ -8,6 +8,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.xml.sax.SAXException;
 
@@ -39,8 +40,8 @@
      *      ways.
      */
-    public GpxData parseRawGps() throws IOException, SAXException {
-        Main.pleaseWaitDlg.progress.setValue(0);
-        Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
+    public GpxData parseRawGps(ProgressMonitor progressMonitor) throws IOException, SAXException {
+        progressMonitor.beginTask("", 1);
         try {
+            progressMonitor.indeterminateSubTask(tr("Contacting OSM Server..."));
             String url = "trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=";
 
@@ -48,9 +49,10 @@
             GpxData result = null;
             for (int i = 0;!done;++i) {
-                Main.pleaseWaitDlg.currentAction.setText(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
-                InputStream in = getInputStream(url+i, Main.pleaseWaitDlg);
+                progressMonitor.subTask(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
+                InputStream in = getInputStream(url+i, progressMonitor.createSubTaskMonitor(1, true));
                 if (in == null) {
                     break;
                 }
+                progressMonitor.setTicks(0);
                 GpxData currentGpx = new GpxReader(in, null).data;
                 if (result == null) {
@@ -83,4 +85,6 @@
                 throw (RuntimeException)e;
             throw new RuntimeException(e);
+        } finally {
+            progressMonitor.finishTask();
         }
     }
@@ -91,15 +95,12 @@
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask(tr("Contacting OSM Server..."), 10);
         try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
-            Main.pleaseWaitDlg.setIndeterminate(true);
-            final InputStream in = getInputStream("map?bbox="+lon1+","+lat1+","+lon2+","+lat2, Main.pleaseWaitDlg);
-            Main.pleaseWaitDlg.setIndeterminate(false);
+            progressMonitor.indeterminateSubTask(null);
+            final InputStream in = getInputStream("map?bbox="+lon1+","+lat1+","+lon2+","+lat2, progressMonitor.createSubTaskMonitor(9, false));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
-            final DataSet data = OsmReader.parseDataSet(in,Main.pleaseWaitDlg);
+            final DataSet data = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false));
             in.close();
             activeConnection = null;
@@ -117,4 +118,6 @@
                 return null;
             throw new OsmTransferException(e);
+        } finally {
+            progressMonitor.finishTask();
         }
     }
Index: /trunk/src/org/openstreetmap/josm/io/DiffResultReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/DiffResultReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/DiffResultReader.java	(revision 1811)
@@ -18,5 +18,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
@@ -64,29 +64,30 @@
      * Parse the given input source and return the dataset.
      */
-    public static void parseDiffResult(String source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, PleaseWaitDialog pleaseWaitDlg)
+    public static void parseDiffResult(String source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, ProgressMonitor progressMonitor)
     throws SAXException, IOException {
 
-       DiffResultReader drr = new DiffResultReader();
-       drr.processed = processed;
-       drr.newIdMap = newIdMap;
-       InputSource inputSource = new InputSource(new StringReader(source));
-       try {
-           SAXParserFactory.newInstance().newSAXParser().parse(inputSource, drr.new Parser());
-       } catch (ParserConfigurationException e1) {
-           e1.printStackTrace(); // broken SAXException chaining
-           throw new SAXException(e1);
-       }
+        progressMonitor.beginTask(tr("Preparing data..."));
+        try {
 
-       if (pleaseWaitDlg != null) {
-           pleaseWaitDlg.progress.setValue(0);
-           pleaseWaitDlg.currentAction.setText(tr("Preparing data..."));
-       }
+            DiffResultReader drr = new DiffResultReader();
+            drr.processed = processed;
+            drr.newIdMap = newIdMap;
+            InputSource inputSource = new InputSource(new StringReader(source));
+            try {
+                SAXParserFactory.newInstance().newSAXParser().parse(inputSource, drr.new Parser());
+            } catch (ParserConfigurationException e1) {
+                e1.printStackTrace(); // broken SAXException chaining
+                throw new SAXException(e1);
+            }
 
-       for (OsmPrimitive p : osm) {
-           //System.out.println("old: "+ p);
-           p.visit(drr);
-           //System.out.println("new: "+ p);
-           //System.out.println("");
-       }
+            for (OsmPrimitive p : osm) {
+                //System.out.println("old: "+ p);
+                p.visit(drr);
+                //System.out.println("new: "+ p);
+                //System.out.println("");
+            }
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(revision 1811)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
@@ -14,5 +13,4 @@
 import java.util.logging.Logger;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -23,10 +21,11 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
-import org.xml.sax.SAXException;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
  * Retrieves a set of {@see OsmPrimitive}s from an OSM server using the so called
  * Multi Fetch API.
- * 
+ *
  * Usage:
  * <pre>
@@ -42,5 +41,5 @@
  *    }
  * </pre>
- * 
+ *
  *
  */
@@ -53,5 +52,5 @@
      * which should be safe according to the
      * <a href="http://www.boutell.com/newfaq/misc/urllength.html">WWW FAQ</a>.
-     * 
+     *
      */
     static private int MAX_IDS_PER_REQUEST = 200;
@@ -79,7 +78,7 @@
      * remembers an {@see OsmPrimitive}'s id and its type. The id will
      * later be fetched as part of a Multi Get request.
-     * 
+     *
      * Ignore the id if it id <= 0.
-     * 
+     *
      * @param id  the id
      * @param type  the type
@@ -100,7 +99,7 @@
      * an {@see OsmPrimitive} with id=<code>id</code>. The id will
      * later we fetched as part of a Multi Get request.
-     * 
+     *
      * Ignore the id if it id <= 0.
-     * 
+     *
      * @param ds  the dataset (must not be null)
      * @param id  the id
@@ -123,11 +122,11 @@
      * appends a list of  ids to the list of ids which will be fetched from the server. ds must
      * include an {@see OsmPrimitive} for each id in ids.
-     * 
+     *
      * id is ignored if id <= 0.
-     * 
+     *
      * @param ds  the dataset
      * @param ids  the list of ids
      * @return this
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(DataSet ds, long ... ids)  {
@@ -142,11 +141,11 @@
      * appends a collection of  ids to the list of ids which will be fetched from the server. ds must
      * include an {@see OsmPrimitive} for each id in ids.
-     * 
+     *
      * id is ignored if id <= 0.
-     * 
+     *
      * @param ds  the dataset
      * @param ids  the collection of ids
      * @return this
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(DataSet ds, Collection<Long> ids) {
@@ -163,5 +162,5 @@
      * @param node  the node (ignored, if null)
      * @return this
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(Node node) {
@@ -177,5 +176,5 @@
      * @param way the way (ignored, if null)
      * @return this
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(Way way) {
@@ -196,5 +195,5 @@
      * @param relation  the relation (ignored, if null)
      * @return this
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(Relation relation) {
@@ -225,9 +224,9 @@
      * @param primitives  the list of primitives (ignored, if null)
      * @return this
-     * 
+     *
      * @see #append(Node)
      * @see #append(Way)
      * @see #append(Relation)
-     * 
+     *
      */
     public MultiFetchServerObjectReader append(Collection<OsmPrimitive> primitives) {
@@ -242,5 +241,5 @@
      * extracts a subset of max {@see #MAX_IDS_PER_REQUEST} ids from <code>ids</code> and
      * replies the subset. The extracted subset is removed from <code>ids</code>.
-     * 
+     *
      * @param ids a set of ids
      * @return the subset of ids
@@ -267,5 +266,5 @@
      * builds the Multi Get request string for a set of ids and a given
      * {@see OsmPrimitiveType}.
-     * 
+     *
      * @param type the type
      * @param idPackage  the package of ids
@@ -290,5 +289,5 @@
      * builds the Multi Get request string for a single id and a given
      * {@see OsmPrimitiveType}.
-     * 
+     *
      * @param type the type
      * @param id the id
@@ -306,17 +305,17 @@
      * invokes a Multi Get for a set of ids and a given {@see OsmPrimitiveType}.
      * The retrieved primitives are merged to {@see #outputDataSet}.
-     * 
+     *
      * @param type the type
      * @param pkg the package of ids
      * @exception OsmTransferException thrown if an error occurs while communicating with the API server
-     * 
-     */
-    protected void multiGetIdPackage(OsmPrimitiveType type, Set<Long> pkg) throws OsmTransferException {
+     *
+     */
+    protected void multiGetIdPackage(OsmPrimitiveType type, Set<Long> pkg, ProgressMonitor progressMonitor) throws OsmTransferException {
         String request = buildRequestString(type, pkg);
-        final InputStream in = getInputStream(request, Main.pleaseWaitDlg);
+        final InputStream in = getInputStream(request, NullProgressMonitor.INSTANCE);
         if (in == null) return;
-        Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
+        progressMonitor.subTask(tr("Downloading OSM data..."));
         try {
-            final OsmReader osm = OsmReader.parseDataSetOsm(in, Main.pleaseWaitDlg);
+            final OsmReader osm = OsmReader.parseDataSetOsm(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
             merge(osm.getDs());
         } catch(Exception e) {
@@ -328,18 +327,18 @@
      * invokes a Multi Get for a single id and a given {@see OsmPrimitiveType}.
      * The retrieved primitive is merged to {@see #outputDataSet}.
-     * 
+     *
      * @param type the type
      * @param id the id
      * @exception OsmTransferException thrown if an error occurs while communicating with the API server
-     * 
-     */
-    protected void singleGetId(OsmPrimitiveType type, long id) throws OsmTransferException {
+     *
+     */
+    protected void singleGetId(OsmPrimitiveType type, long id, ProgressMonitor progressMonitor) throws OsmTransferException {
         String request = buildRequestString(type, id);
-        final InputStream in = getInputStream(request, Main.pleaseWaitDlg);
+        final InputStream in = getInputStream(request, NullProgressMonitor.INSTANCE);
         if (in == null)
             return;
-        Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
+        progressMonitor.subTask(tr("Downloading OSM data..."));
         try {
-            final OsmReader osm = OsmReader.parseDataSetOsm(in,Main.pleaseWaitDlg);
+            final OsmReader osm = OsmReader.parseDataSetOsm(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
             merge(osm.getDs());
         } catch(Exception e) {
@@ -351,18 +350,18 @@
      * invokes a sequence of Multi Gets for individual ids in a set of ids and a given {@see OsmPrimitiveType}.
      * The retrieved primitives are merged to {@see #outputDataSet}.
-     * 
+     *
      * This method is used if one of the ids in pkg doesn't exist (the server replies with return code 404).
      * If the set is fetched with this method it is possible to find out which of the ids doesn't exist.
      * Unfortunatelly, the server does not provide an error header or an error body for a 404 reply.
-     * 
+     *
      * @param type the type
      * @param pkg the set of ids
      * @exception OsmTransferException thrown if an error occurs while communicating with the API server
-     * 
-     */
-    protected void singleGetIdPackage(OsmPrimitiveType type, Set<Long> pkg) throws OsmTransferException {
+     *
+     */
+    protected void singleGetIdPackage(OsmPrimitiveType type, Set<Long> pkg, ProgressMonitor progressMonitor) throws OsmTransferException {
         for (long id : pkg) {
             try {
-                singleGetId(type, id);
+                singleGetId(type, id, progressMonitor);
             } catch(OsmApiException e) {
                 if (e.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
@@ -378,7 +377,7 @@
     /**
      * merges the dataset <code>from</code> to {@see #outputDataSet}.
-     * 
+     *
      * @param from the other dataset
-     * 
+     *
      */
     protected void merge(DataSet from) {
@@ -389,10 +388,10 @@
     /**
      * fetches a set of ids of a given {@see OsmPrimitiveType} from the server
-     * 
+     *
      * @param ids the set of ids
      * @param type the  type
      * @exception OsmTransferException thrown if an error occurs while communicating with the API server
      */
-    protected void fetchPrimitives(Set<Long> ids, OsmPrimitiveType type) throws OsmTransferException{
+    protected void fetchPrimitives(Set<Long> ids, OsmPrimitiveType type, ProgressMonitor progressMonitor) throws OsmTransferException{
         Set<Long> toFetch = new HashSet<Long>(ids);
         toFetch.addAll(ids);
@@ -400,9 +399,9 @@
             Set<Long> pkg = extractIdPackage(toFetch);
             try {
-                multiGetIdPackage(type, pkg);
+                multiGetIdPackage(type, pkg, progressMonitor);
             } catch(OsmApiException e) {
                 if (e.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
                     logger.warning(tr("Server replied with response code 404, retrying with an individual request for each primitive"));
-                    singleGetIdPackage(type, pkg);
+                    singleGetIdPackage(type, pkg, progressMonitor);
                 } else
                     throw e;
@@ -417,26 +416,31 @@
      * the latest version of the primitive (if any), even if the primitive is not visible (i.e. if
      * visible==false).
-     * 
+     *
      * Invoke {@see #getMissingPrimitives()} to get a list of primitives which have not been
      * found on  the server (the server response code was 404)
-     * 
+     *
      * Invoke {@see #getSkippedWay()} to get a list of ways which this reader could not build from
      * the fetched data because the ways refer to nodes which don't exist on the server.
-     * 
+     *
      * @return the parsed data
      * @exception OsmTransferException thrown if an error occurs while communicating with the API server
      * @see #getMissingPrimitives()
      * @see #getSkippedWays()
-     * 
+     *
 
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
-        missingPrimitives = new HashSet<Long>();
-
-        fetchPrimitives(nodes,OsmPrimitiveType.NODE);
-        fetchPrimitives(ways,OsmPrimitiveType.WAY);
-        fetchPrimitives(relations,OsmPrimitiveType.RELATION);
-        return outputDataSet;
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask("");
+        try {
+            missingPrimitives = new HashSet<Long>();
+
+            fetchPrimitives(nodes,OsmPrimitiveType.NODE, progressMonitor);
+            fetchPrimitives(ways,OsmPrimitiveType.WAY, progressMonitor);
+            fetchPrimitives(relations,OsmPrimitiveType.RELATION, progressMonitor);
+            return outputDataSet;
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 
@@ -445,5 +449,5 @@
      * server was submitted but which are not available from the server (the server
      * replied a return code of 404)
-     * 
+     *
      * @return the set of ids of missing primitives
      */
Index: /trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 1811)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.EventQueue;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -32,4 +31,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
@@ -279,12 +279,16 @@
      * @throws OsmTransferException signifying a non-200 return code, or connection errors
      */
-    public void createChangeset(String comment) throws OsmTransferException {
-        changeset = new Changeset();
-        notifyStatusMessage(tr("Opening changeset..."));
-        Properties sysProp = System.getProperties();
-        Object ua = sysProp.get("http.agent");
-        changeset.put("created_by", (ua == null) ? "JOSM" : ua.toString());
-        changeset.put("comment", comment);
-        createPrimitive(changeset);
+    public void createChangeset(String comment, ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask((tr("Opening changeset...")));
+        try {
+            changeset = new Changeset();
+            Properties sysProp = System.getProperties();
+            Object ua = sysProp.get("http.agent");
+            changeset.put("created_by", (ua == null) ? "JOSM" : ua.toString());
+            changeset.put("comment", comment);
+            createPrimitive(changeset);
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 
@@ -294,9 +298,13 @@
      * @throws OsmTransferException if something goes wrong.
      */
-    public void stopChangeset() throws OsmTransferException {
-        initialize();
-        notifyStatusMessage(tr("Closing changeset..."));
-        sendRequest("PUT", "changeset" + "/" + changeset.id + "/close", null);
-        changeset = null;
+    public void stopChangeset(ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask(tr("Closing changeset..."));
+        try {
+            initialize();
+            sendRequest("PUT", "changeset" + "/" + changeset.id + "/close", null);
+            changeset = null;
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 
@@ -308,35 +316,38 @@
      * @throws OsmTransferException if something is wrong
      */
-    public Collection<OsmPrimitive> uploadDiff(final Collection<OsmPrimitive> list) throws OsmTransferException {
-
-        if (changeset == null)
-            throw new OsmTransferException(tr("No changeset present for diff upload"));
-
-        initialize();
-        final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
-
-        CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
-
-        notifyStatusMessage(tr("Preparing..."));
-        for (OsmPrimitive osm : list) {
-            osm.visit(duv);
-            notifyRelativeProgress(1);
-        }
-        notifyStatusMessage(tr("Uploading..."));
-        setAutoProgressIndication(true);
-
-        String diff = duv.getDocument();
+    public Collection<OsmPrimitive> uploadDiff(final Collection<OsmPrimitive> list, ProgressMonitor progressMonitor) throws OsmTransferException {
+
+        progressMonitor.beginTask("", list.size() * 2);
         try {
-            String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);
-            DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
-        } catch(OsmTransferException e) {
-            throw e;
-        } catch(Exception e) {
-            throw new OsmTransferException(e);
+            if (changeset == null)
+                throw new OsmTransferException(tr("No changeset present for diff upload"));
+
+            initialize();
+            final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
+
+            CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
+
+            progressMonitor.subTask(tr("Preparing..."));
+            for (OsmPrimitive osm : list) {
+                osm.visit(duv);
+                progressMonitor.worked(1);
+            }
+            progressMonitor.indeterminateSubTask(tr("Uploading..."));
+
+            String diff = duv.getDocument();
+            try {
+                String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);
+                DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(),
+                        progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
+            } catch(OsmTransferException e) {
+                throw e;
+            } catch(Exception e) {
+                throw new OsmTransferException(e);
+            }
+
+            return processed;
         } finally {
-            setAutoProgressIndication(false);
-        }
-
-        return processed;
+            progressMonitor.finishTask();
+        }
     }
 
@@ -468,38 +479,6 @@
 
     /**
-     * notifies any listeners about the current state of this API. Currently just
-     * displays the message in the global progress dialog, see {@see Main#pleaseWaitDlg}
-     *
-     * @param message a status message.
-     */
-    protected void notifyStatusMessage(String message) {
-        Main.pleaseWaitDlg.currentAction.setText(message);
-    }
-
-    /**
-     * notifies any listeners about the current about a relative progress. Currently just
-     * increments the progress monitor in the in the global progress dialog, see {@see Main#pleaseWaitDlg}
-     *
-     * @param int the delta
-     */
-    protected void notifyRelativeProgress(int delta) {
-        int current= Main.pleaseWaitDlg.progress.getValue();
-        Main.pleaseWaitDlg.progress.setValue(current + delta);
-    }
-
-
-    protected void setAutoProgressIndication(final boolean enabled) {
-        EventQueue.invokeLater(
-                new Runnable() {
-                    public void run() {
-                        Main.pleaseWaitDlg.setIndeterminate(enabled);
-                    }
-                }
-        );
-    }
-
-    /**
      * returns the API capabilities; null, if the API is not initialized yet
-     * 
+     *
      * @return the API capabilities
      */
Index: /trunk/src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 1811)
@@ -11,7 +11,7 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CharacterCodingException;
 
 import javax.swing.JCheckBox;
@@ -126,5 +126,6 @@
 
     public void cancel() {
-        Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
+        //TODO
+        //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
         cancel = true;
         if (activeConnection != null) {
Index: /trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 1811)
@@ -18,5 +18,5 @@
 import org.openstreetmap.josm.data.osm.history.HistoryRelation;
 import org.openstreetmap.josm.data.osm.history.HistoryWay;
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.tools.DateUtils;
 import org.xml.sax.Attributes;
@@ -32,5 +32,5 @@
  * {@see OsmPrimitive}s. We use objects derived from {@see HistoryOsmPrimitive} instead and we
  * keep the data in a dedicated {@see HistoryDataSet}.
- * 
+ *
  */
 public class OsmHistoryReader {
@@ -210,7 +210,7 @@
     }
 
-    public HistoryDataSet parse(PleaseWaitDialog dialog) throws SAXException, IOException {
+    public HistoryDataSet parse(ProgressMonitor progressMonitor) throws SAXException, IOException {
         InputSource inputSource = new InputSource(new InputStreamReader(in, "UTF-8"));
-        dialog.currentAction.setText("Parsing OSM history data ...");
+        progressMonitor.beginTask(tr("Parsing OSM history data ..."));
         try {
             SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser());
@@ -218,4 +218,6 @@
             e1.printStackTrace(); // broken SAXException chaining
             throw new SAXException(e1);
+        } finally {
+            progressMonitor.finishTask();
         }
         return data;
Index: /trunk/src/org/openstreetmap/josm/io/OsmImporter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmImporter.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmImporter.java	(revision 1811)
@@ -11,10 +11,9 @@
 import java.io.InputStream;
 
-import javax.swing.JOptionPane;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExtensionFileFilter;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.xml.sax.SAXException;
 
@@ -46,5 +45,5 @@
 
     protected void importData(InputStream in, File associatedFile) throws SAXException, IOException {
-        OsmReader osm = OsmReader.parseDataSetOsm(in,Main.pleaseWaitDlg);
+        OsmReader osm = OsmReader.parseDataSetOsm(in, NullProgressMonitor.INSTANCE);
         DataSet dataSet = osm.getDs();
         OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile);
Index: /trunk/src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 1811)
@@ -16,5 +16,4 @@
 import java.util.logging.Logger;
 
-import javax.swing.SwingUtilities;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParserFactory;
@@ -31,5 +30,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.tools.DateUtils;
 import org.xml.sax.Attributes;
@@ -70,7 +69,7 @@
     /**
      * constructor (for private use only)
-     * 
-     * @see #parseDataSet(InputStream, DataSet, PleaseWaitDialog)
-     * @see #parseDataSetOsm(InputStream, DataSet, PleaseWaitDialog)
+     *
+     * @see #parseDataSet(InputStream, DataSet, ProgressMonitor)
+     * @see #parseDataSetOsm(InputStream, DataSet, ProgressMonitor)
      */
     private OsmReader() {
@@ -454,9 +453,9 @@
      *  element found there is returned.
      */
-    public static DataSet parseDataSet(InputStream source, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException {
-        return parseDataSetOsm(source, pleaseWaitDlg).ds;
-    }
-
-    public static OsmReader parseDataSetOsm(InputStream source, final PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException {
+    public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws SAXException, IOException {
+        return parseDataSetOsm(source, progressMonitor).ds;
+    }
+
+    public static OsmReader parseDataSetOsm(InputStream source, ProgressMonitor progressMonitor) throws SAXException, IOException {
         OsmReader osm = new OsmReader();
 
@@ -470,41 +469,30 @@
         }
 
-        SwingUtilities.invokeLater(
-                new Runnable() {
-                    public void run() {
-                        pleaseWaitDlg.currentAction.setText(tr("Prepare OSM data..."));
-                        pleaseWaitDlg.setIndeterminate(true);
-                    }
+        progressMonitor.beginTask(tr("Prepare OSM data...", 2));
+        try {
+            for (Node n : osm.nodes.values()) {
+                osm.adder.visit(n);
+            }
+
+            progressMonitor.worked(1);
+
+            try {
+                osm.createWays();
+                osm.createRelations();
+            } catch (NumberFormatException e) {
+                e.printStackTrace();
+                throw new SAXException(tr("Ill-formed node id"));
+            }
+
+            // clear all negative ids (new to this file)
+            for (OsmPrimitive o : osm.ds.allPrimitives())
+                if (o.id < 0) {
+                    o.id = 0;
                 }
-        );
-
-        for (Node n : osm.nodes.values()) {
-            osm.adder.visit(n);
-        }
-
-        try {
-            osm.createWays();
-            osm.createRelations();
-        } catch (NumberFormatException e) {
-            e.printStackTrace();
-            throw new SAXException(tr("Ill-formed node id"));
-        }
-
-        // clear all negative ids (new to this file)
-        for (OsmPrimitive o : osm.ds.allPrimitives())
-            if (o.id < 0) {
-                o.id = 0;
-            }
-
-        SwingUtilities.invokeLater(
-                new Runnable() {
-                    public void run() {
-                        pleaseWaitDlg.setIndeterminate(false);
-                        pleaseWaitDlg.progress.setValue(0);
-                    }
-                }
-        );
-
-        return osm;
+
+            return osm;
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 }
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java	(revision 1811)
@@ -8,5 +8,4 @@
 import java.util.Collection;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -15,4 +14,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
@@ -21,12 +21,12 @@
  * which refer to the node. For a {@see Way} or a {@see Relation}, only relations are
  * read.
- * 
+ *
  * OsmServerBackreferenceReader uses the API calls <code>[node|way|relation]/#id/relations</code>
  * and  <code>node/#id/ways</code> to retrieve the referring primitives. The default behaviour
  * of these calls is to reply incomplete primitives only.
- * 
+ *
  * If you set {@see #setReadFull(boolean)} to true this reader uses a {@see MultiFetchServerObjectReader}
  * to complete incomplete primitives.
- * 
+ *
  *
  */
@@ -42,7 +42,7 @@
     /**
      * constructor
-     * 
+     *
      * @param primitive  the primitive to be read. Must not be null. primitive.id > 0 expected
-     * 
+     *
      * @exception IllegalArgumentException thrown if primitive is null
      * @exception IllegalArgumentException thrown if primitive.id <= 0
@@ -60,11 +60,11 @@
     /**
      * constructor
-     * 
+     *
      * @param id  the id of the primitive. > 0 expected
      * @param type the type of the primitive. Must not be null.
-     * 
+     *
      * @exception IllegalArgumentException thrown if id <= 0
      * @exception IllegalArgumentException thrown if type is null
-     * 
+     *
      */
     public OsmServerBackreferenceReader(long id, OsmPrimitiveType type) throws IllegalArgumentException   {
@@ -80,9 +80,9 @@
     /**
      * constructor
-     * 
+     *
      * @param id  the id of the primitive. > 0 expected
      * @param type the type of the primitive. Must not be null.
      * @param readFull true, if referers should be read fully (i.e. including their immediate children)
-     * 
+     *
      */
     public OsmServerBackreferenceReader(OsmPrimitive primitive, boolean readFull) {
@@ -93,11 +93,11 @@
     /**
      * constructor
-     * 
+     *
      * @param primitive the primitive whose referers are to be read
      * @param readFull true, if referers should be read fully (i.e. including their immediate children)
-     * 
+     *
      * @exception IllegalArgumentException thrown if id <= 0
      * @exception IllegalArgumentException thrown if type is null
-     * 
+     *
      */
     public OsmServerBackreferenceReader(long id, OsmPrimitiveType type, boolean readFull) throws IllegalArgumentException  {
@@ -108,5 +108,5 @@
     /**
      * Replies true if this reader also reads immediate children of referring primitives
-     * 
+     *
      * @return true if this reader also reads immediate children of referring primitives
      */
@@ -117,5 +117,5 @@
     /**
      * Set true if this reader should reads immediate children of referring primitives too. False, otherweise.
-     * 
+     *
      * @param readFull true if this reader should reads immediate children of referring primitives too. False, otherweise.
      */
@@ -126,22 +126,22 @@
     /**
      * Reads referring ways from the API server and replies them in a {@see DataSet}
-     * 
+     *
      * @return the data set
      * @throws OsmTransferException
      */
-    protected DataSet getReferringWays() throws OsmTransferException {
+    protected DataSet getReferringWays(ProgressMonitor progressMonitor) throws OsmTransferException {
         InputStream in = null;
-        try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
+        progressMonitor.beginTask(null, 2);
+        try {
+            progressMonitor.indeterminateSubTask(tr("Contacting OSM Server..."));
             StringBuffer sb = new StringBuffer();
             sb.append(primitiveType.getAPIName())
             .append("/").append(id).append("/ways");
 
-            in = getInputStream(sb.toString(), Main.pleaseWaitDlg);
+            in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading referring ways ..."));
-            return OsmReader.parseDataSet(in,Main.pleaseWaitDlg);
+            progressMonitor.subTask(tr("Downloading referring ways ..."));
+            return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, true));
         } catch(OsmTransferException e) {
             throw e;
@@ -151,4 +151,5 @@
             throw new OsmTransferException(e);
         } finally {
+            progressMonitor.finishTask();
             if (in != null) {
                 try {
@@ -162,22 +163,22 @@
 
      * Reads referring relations from the API server and replies them in a {@see DataSet}
-     * 
+     *
      * @return the data set
      * @throws OsmTransferException
      */
-    protected DataSet getReferringRelations() throws OsmTransferException {
+    protected DataSet getReferringRelations(ProgressMonitor progressMonitor) throws OsmTransferException {
         InputStream in = null;
-        try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
+        progressMonitor.beginTask(null, 2);
+        try {
+            progressMonitor.subTask(tr("Contacting OSM Server..."));
             StringBuffer sb = new StringBuffer();
             sb.append(primitiveType.getAPIName())
             .append("/").append(id).append("/relations");
 
-            in = getInputStream(sb.toString(), Main.pleaseWaitDlg);
+            in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading referring relations ..."));
-            return OsmReader.parseDataSet(in,Main.pleaseWaitDlg);
+            progressMonitor.subTask(tr("Downloading referring relations ..."));
+            return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, true));
         } catch(OsmTransferException e) {
             throw e;
@@ -187,4 +188,5 @@
             throw new OsmTransferException(e);
         } finally {
+            progressMonitor.finishTask();
             if (in != null) {
                 try {
@@ -200,5 +202,5 @@
      * incomplete primitives are read from the server with an individual <tt>/api/0.6/[way,relation]/#id/full</tt>
      * request.
-     * 
+     *
      * <ul>
      *   <li>if this reader reads referers for an {@see Node}, referring ways are always
@@ -207,35 +209,40 @@
      *    are only read fully if {@see #setReadFull(boolean)} is set to true.</li>
      * </ul>
-     * 
+     *
      * The method replies the modified dataset.
-     * 
+     *
      * @param ds the original dataset
      * @return the modified dataset
      * @throws OsmTransferException thrown if an exception occurs.
      */
-    protected DataSet readIncompletePrimitives(DataSet ds) throws OsmTransferException {
-        Collection<Way> waysToCheck = new ArrayList<Way>(ds.ways);
-        if (isReadFull() ||primitiveType.equals(OsmPrimitiveType.NODE)) {
-            for (Way way: waysToCheck) {
-                if (way.id > 0 && way.incomplete) {
-                    OsmServerObjectReader reader = new OsmServerObjectReader(way.id, OsmPrimitiveType.from(way), true /* read full */);
-                    DataSet wayDs = reader.parseOsm();
-                    MergeVisitor visitor = new MergeVisitor(ds, wayDs);
-                    visitor.merge();
+    protected DataSet readIncompletePrimitives(DataSet ds, ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask(null, 2);
+        try {
+            Collection<Way> waysToCheck = new ArrayList<Way>(ds.ways);
+            if (isReadFull() ||primitiveType.equals(OsmPrimitiveType.NODE)) {
+                for (Way way: waysToCheck) {
+                    if (way.id > 0 && way.incomplete) {
+                        OsmServerObjectReader reader = new OsmServerObjectReader(way.id, OsmPrimitiveType.from(way), true /* read full */);
+                        DataSet wayDs = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
+                        MergeVisitor visitor = new MergeVisitor(ds, wayDs);
+                        visitor.merge();
+                    }
                 }
             }
-        }
-        if (isReadFull()) {
-            Collection<Relation> relationsToCheck  = new ArrayList<Relation>(ds.relations);
-            for (Relation relation: relationsToCheck) {
-                if (relation.id > 0 && relation.incomplete) {
-                    OsmServerObjectReader reader = new OsmServerObjectReader(relation.id, OsmPrimitiveType.from(relation), true /* read full */);
-                    DataSet wayDs = reader.parseOsm();
-                    MergeVisitor visitor = new MergeVisitor(ds, wayDs);
-                    visitor.merge();
+            if (isReadFull()) {
+                Collection<Relation> relationsToCheck  = new ArrayList<Relation>(ds.relations);
+                for (Relation relation: relationsToCheck) {
+                    if (relation.id > 0 && relation.incomplete) {
+                        OsmServerObjectReader reader = new OsmServerObjectReader(relation.id, OsmPrimitiveType.from(relation), true /* read full */);
+                        DataSet wayDs = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
+                        MergeVisitor visitor = new MergeVisitor(ds, wayDs);
+                        visitor.merge();
+                    }
                 }
             }
-        }
-        return ds;
+            return ds;
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 
@@ -243,23 +250,28 @@
      * Reads the referring primitives from the OSM server, parses them and
      * replies them as {@see DataSet}
-     * 
+     *
      * @return the dataset with the referring primitives
      * @exception OsmTransferException thrown if an error occurs while communicating with the server
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
-        DataSet ret = new DataSet();
-        if (primitiveType.equals(OsmPrimitiveType.NODE)) {
-            DataSet ds = getReferringWays();
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask(null, 3);
+        try {
+            DataSet ret = new DataSet();
+            if (primitiveType.equals(OsmPrimitiveType.NODE)) {
+                DataSet ds = getReferringWays(progressMonitor.createSubTaskMonitor(1, false));
+                MergeVisitor visitor = new MergeVisitor(ret,ds);
+                visitor.merge();
+                ret = visitor.getMyDataSet();
+            }
+            DataSet ds = getReferringRelations(progressMonitor.createSubTaskMonitor(1, false));
             MergeVisitor visitor = new MergeVisitor(ret,ds);
             visitor.merge();
             ret = visitor.getMyDataSet();
-        }
-        DataSet ds = getReferringRelations();
-        MergeVisitor visitor = new MergeVisitor(ret,ds);
-        visitor.merge();
-        ret = visitor.getMyDataSet();
-        readIncompletePrimitives(ret);
-        return ret;
+            readIncompletePrimitives(ret, progressMonitor.createSubTaskMonitor(1, false));
+            return ret;
+        } finally {
+            progressMonitor.finishTask();
+        }
     }
 }
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerHistoryReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerHistoryReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerHistoryReader.java	(revision 1811)
@@ -7,8 +7,8 @@
 import java.io.InputStream;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.xml.sax.SAXException;
 
@@ -17,5 +17,5 @@
 /**
  * Reads the history of an {@see OsmPrimitive} from the OSM API server.
- * 
+ *
  */
 public class OsmServerHistoryReader extends OsmServerReader {
@@ -26,9 +26,9 @@
     /**
      * constructor
-     * 
+     *
      * @param type the type of the primitive whose history is to be fetched from the server.
      *   Must not be null.
      * @param id the id of the primitive
-     * 
+     *
      *  @exception IllegalArgumentException thrown, if type is null
      */
@@ -44,9 +44,9 @@
     /**
      * don't use - not implemented!
-     * 
+     *
      * @exception NotImplementedException
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
         throw new NotImplementedException();
     }
@@ -54,23 +54,23 @@
     /**
      * Fetches the history from the OSM API and parses it
-     * 
+     *
      * @return the data set with the parsed history data
      * @throws OsmTransferException thrown, if an exception occurs
      */
-    public HistoryDataSet parseHistory() throws OsmTransferException {
+    public HistoryDataSet parseHistory(ProgressMonitor progressMonitor) throws OsmTransferException {
         InputStream in = null;
+        progressMonitor.beginTask("");
         try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
+            progressMonitor.indeterminateSubTask(tr("Contacting OSM Server..."));
             StringBuffer sb = new StringBuffer();
             sb.append(primitiveType.getAPIName())
             .append("/").append(id).append("/history");
 
-            in = getInputStream(sb.toString(), Main.pleaseWaitDlg);
+            in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading history..."));
+            progressMonitor.indeterminateSubTask(tr("Downloading history..."));
             final OsmHistoryReader reader = new OsmHistoryReader(in);
-            HistoryDataSet data = reader.parse(Main.pleaseWaitDlg);
+            HistoryDataSet data = reader.parse(progressMonitor.createSubTaskMonitor(1, true));
             return data;
         } catch(OsmTransferException e) {
@@ -81,4 +81,5 @@
             throw new OsmTransferException(e);
         } finally {
+            progressMonitor.finishTask();
             if (in != null) {
                 try {
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java	(revision 1811)
@@ -4,10 +4,8 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.io.IOException;
 import java.io.InputStream;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.xml.sax.SAXException;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 public class OsmServerLocationReader extends OsmServerReader {
@@ -23,15 +21,13 @@
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
         InputStream in = null;
+        progressMonitor.beginTask(tr("Contacting Server...", 10));
         try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting Server..."));
-
-            in = getInputStreamRaw(url, Main.pleaseWaitDlg);
+            in = getInputStreamRaw(url, progressMonitor.createSubTaskMonitor(9, false));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
-            return OsmReader.parseDataSet(in, Main.pleaseWaitDlg);
+            progressMonitor.subTask(tr("Downloading OSM data..."));
+            return OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false));
         } catch(OsmTransferException e) {
             throw e;
@@ -41,4 +37,5 @@
             throw new OsmTransferException(e);
         } finally {
+            progressMonitor.finishTask();
             try {
                 if (in != null) {
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java	(revision 1811)
@@ -7,7 +7,7 @@
 import java.io.InputStream;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.xml.sax.SAXException;
 
@@ -30,8 +30,8 @@
      */
     @Override
-    public DataSet parseOsm() throws OsmTransferException {
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+        progressMonitor.beginTask("", 1);
         try {
-            Main.pleaseWaitDlg.progress.setValue(0);
-            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
+            progressMonitor.subTask(tr("Downloading OSM data..."));
             StringBuffer sb = new StringBuffer();
             sb.append(type.getAPIName());
@@ -42,9 +42,8 @@
             }
 
-            final InputStream in = getInputStream(sb.toString(), Main.pleaseWaitDlg);
+            final InputStream in = getInputStream(sb.toString(), progressMonitor.createSubTaskMonitor(1, true));
             if (in == null)
                 return null;
-            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
-            final OsmReader osm = OsmReader.parseDataSetOsm(in,Main.pleaseWaitDlg);
+            final OsmReader osm = OsmReader.parseDataSetOsm(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
             final DataSet data = osm.getDs();
 
@@ -64,4 +63,6 @@
                 return null;
             throw new OsmTransferException(e);
+        } finally {
+            progressMonitor.finishTask();
         }
     }
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 1811)
@@ -14,9 +14,7 @@
 import java.util.zip.InflaterInputStream;
 
-import javax.swing.JOptionPane;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
@@ -40,11 +38,11 @@
      * @return An reader reading the input stream (servers answer) or <code>null</code>.
      */
-    protected InputStream getInputStream(String urlStr, PleaseWaitDialog pleaseWaitDlg) throws OsmTransferException  {
+    protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor) throws OsmTransferException  {
         api.initialize();
         urlStr = api.getBaseUrl() + urlStr;
-        return getInputStreamRaw(urlStr, pleaseWaitDlg);
+        return getInputStreamRaw(urlStr, progressMonitor);
     }
 
-    protected InputStream getInputStreamRaw(String urlStr, PleaseWaitDialog pleaseWaitDlg) throws OsmTransferException {
+    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor) throws OsmTransferException {
         URL url = null;
         try {
@@ -97,5 +95,5 @@
 
             String encoding = activeConnection.getContentEncoding();
-            InputStream inputStream = new ProgressInputStream(activeConnection, pleaseWaitDlg);
+            InputStream inputStream = new ProgressInputStream(activeConnection, progressMonitor);
             if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
                 inputStream = new GZIPInputStream(inputStream);
@@ -114,5 +112,5 @@
     }
 
-    public abstract DataSet parseOsm() throws OsmTransferException;
+    public abstract DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException;
 
 }
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 1811)
@@ -13,4 +13,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
@@ -81,58 +82,63 @@
      * @param primitives list of objects to send
      */
-    public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives) throws OsmTransferException {
+    public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
         processed = new LinkedList<OsmPrimitive>();
 
         api.initialize();
 
-        Main.pleaseWaitDlg.progress.setMaximum(primitives.size());
-        Main.pleaseWaitDlg.progress.setValue(0);
+        progressMonitor.beginTask("");
 
-        // check whether we can use changeset
-        //
-        boolean canUseChangeset = api.hasChangesetSupport();
-        boolean useChangeset = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0);
-        if (useChangeset && ! canUseChangeset) {
-            System.out.println(tr("WARNING: preference ''{0}'' or api version ''{1}'' of dataset requires to use changesets, but API is not able to handle them. Ignoring changesets.", "osm-server.atomic-upload", apiVersion));
-            useChangeset = false;
-        }
+        try {
 
-        if (useChangeset) {
-            // upload everything in one changeset
+            // check whether we can use changeset
             //
-            try {
-                api.createChangeset(getChangesetComment());
-                processed.addAll(api.uploadDiff(primitives));
-            } catch(OsmTransferException e) {
-                throw e;
-            } finally {
+            boolean canUseChangeset = api.hasChangesetSupport();
+            boolean useChangeset = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0);
+            if (useChangeset && ! canUseChangeset) {
+                System.out.println(tr("WARNING: preference ''{0}'' or api version ''{1}'' of dataset requires to use changesets, but API is not able to handle them. Ignoring changesets.", "osm-server.atomic-upload", apiVersion));
+                useChangeset = false;
+            }
+
+            if (useChangeset) {
+                // upload everything in one changeset
+                //
                 try {
-                    if (canUseChangeset) {
-                        api.stopChangeset();
+                    api.createChangeset(getChangesetComment(), progressMonitor.createSubTaskMonitor(0, false));
+                    processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
+                } catch(OsmTransferException e) {
+                    throw e;
+                } finally {
+                    try {
+                        if (canUseChangeset) {
+                            api.stopChangeset(progressMonitor.createSubTaskMonitor(0, false));
+                        }
+                    } catch (Exception ee) {
+                        ee.printStackTrace();
+                        // ignore nested exception
                     }
-                } catch (Exception ee) {
-                    ee.printStackTrace();
-                    // ignore nested exception
                 }
+            } else {
+                // upload changes individually (90% of code is for the status display...)
+                //
+                progressMonitor.setTicksCount(primitives.size());
+                api.createChangeset(getChangesetComment(), progressMonitor.createSubTaskMonitor(0, false));
+                NameVisitor v = new NameVisitor();
+                uploadStartTime = System.currentTimeMillis();
+                for (OsmPrimitive osm : primitives) {
+                    osm.visit(v);
+                    int progress = progressMonitor.getTicks();
+                    String time_left_str = timeLeft(progress, primitives.size());
+                    progressMonitor.subTask(
+                            tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})",
+                                    Math.round(100.0*progress/primitives.size()), progress,
+                                    primitives.size(), time_left_str, tr(v.className), v.name, osm.id));
+                    makeApiRequest(osm);
+                    processed.add(osm);
+                    progressMonitor.worked(1);
+                }
+                api.stopChangeset(progressMonitor.createSubTaskMonitor(0, false));
             }
-        } else {
-            // upload changes individually (90% of code is for the status display...)
-            //
-            api.createChangeset(getChangesetComment());
-            NameVisitor v = new NameVisitor();
-            uploadStartTime = System.currentTimeMillis();
-            for (OsmPrimitive osm : primitives) {
-                osm.visit(v);
-                int progress = Main.pleaseWaitDlg.progress.getValue();
-                String time_left_str = timeLeft(progress, primitives.size());
-                Main.pleaseWaitDlg.currentAction.setText(
-                        tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})",
-                                Math.round(100.0*progress/primitives.size()), progress,
-                                primitives.size(), time_left_str, tr(v.className), v.name, osm.id));
-                makeApiRequest(osm);
-                processed.add(osm);
-                Main.pleaseWaitDlg.progress.setValue(progress+1);
-            }
-            api.stopChangeset();
+        } finally {
+            progressMonitor.finishTask();
         }
     }
Index: /trunk/src/org/openstreetmap/josm/io/ProgressInputStream.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/ProgressInputStream.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/io/ProgressInputStream.java	(revision 1811)
@@ -8,5 +8,6 @@
 import java.net.URLConnection;
 
-import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 /**
@@ -19,9 +20,16 @@
     private int readSoFar = 0;
     private int lastDialogUpdate = 0;
+    private boolean sizeKnown;
     private final URLConnection connection;
-    private PleaseWaitDialog pleaseWaitDlg;
+    private final ProgressMonitor progressMonitor;
 
-    public ProgressInputStream(URLConnection con, PleaseWaitDialog pleaseWaitDlg) throws OsmTransferException {
+    public ProgressInputStream(URLConnection con, ProgressMonitor progressMonitor) throws OsmTransferException {
         this.connection = con;
+        if (progressMonitor == null) {
+            progressMonitor = NullProgressMonitor.INSTANCE;
+        }
+        this.progressMonitor = progressMonitor;
+        progressMonitor.beginTask(tr("Contacting OSM Server..."), 1);
+        progressMonitor.indeterminateSubTask(null);
 
         try {
@@ -33,18 +41,13 @@
         }
 
-        int contentLength = con.getContentLength();
-        this.pleaseWaitDlg = pleaseWaitDlg;
-        if (pleaseWaitDlg == null)
-            return;
-        if (contentLength > 0) {
-            pleaseWaitDlg.progress.setMaximum(contentLength);
-        } else {
-            pleaseWaitDlg.progress.setMaximum(0);
+        updateSize();
+        if (!sizeKnown) {
+            progressMonitor.indeterminateSubTask(tr("Downloading OSM data..."));
         }
-        pleaseWaitDlg.progress.setValue(0);
     }
 
     @Override public void close() throws IOException {
         in.close();
+        progressMonitor.finishTask();
     }
 
@@ -53,4 +56,6 @@
         if (read != -1) {
             advanceTicker(read);
+        } else {
+            progressMonitor.finishTask();
         }
         return read;
@@ -61,4 +66,6 @@
         if (read != -1) {
             advanceTicker(1);
+        } else {
+            progressMonitor.finishTask();
         }
         return read;
@@ -70,27 +77,23 @@
      */
     private void advanceTicker(int amount) {
-        if (pleaseWaitDlg == null)
-            return;
-
-        if (pleaseWaitDlg.progress.getMaximum() == 0 && connection.getContentLength() != -1) {
-            pleaseWaitDlg.progress.setMaximum(connection.getContentLength());
-        }
-
         readSoFar += amount;
+        updateSize();
 
         if (readSoFar / 1024 != lastDialogUpdate) {
             lastDialogUpdate++;
-            String progStr = " "+readSoFar/1024+"/";
-            progStr += (pleaseWaitDlg.progress.getMaximum()==0) ? "??? KB" : (pleaseWaitDlg.progress.getMaximum()/1024)+" KB";
-            pleaseWaitDlg.progress.setValue(readSoFar);
+            if (sizeKnown) {
+                progressMonitor.setExtraText(readSoFar/1024 + " KB");
+                progressMonitor.setTicks(readSoFar);
+            } else {
+                progressMonitor.setExtraText("??? KB");
+            }
+        }
+    }
 
-            String cur = pleaseWaitDlg.currentAction.getText();
-            int i = cur.indexOf(' ');
-            if (i != -1) {
-                cur = cur.substring(0, i) + progStr;
-            } else {
-                cur += progStr;
-            }
-            pleaseWaitDlg.currentAction.setText(cur);
+    private void updateSize() {
+        if (!sizeKnown && connection.getContentLength() > 0) {
+            sizeKnown = true;
+            progressMonitor.subTask(tr("Downloading OSM data..."));
+            progressMonitor.setTicksCount(connection.getContentLength());
         }
     }
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginDownloader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginDownloader.java	(revision 1810)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginDownloader.java	(revision 1811)
@@ -49,5 +49,4 @@
 
         @Override protected void finish() {
-            Main.pleaseWaitDlg.setVisible(false);
             if (errors.length() > 0)
                 JOptionPane.showMessageDialog(Main.parent, tr("There were problems with the following plugins:\n\n {0}",errors));
@@ -60,9 +59,8 @@
             if (!pluginDir.exists())
                 pluginDir.mkdirs();
-            Main.pleaseWaitDlg.progress.setMaximum(toUpdate.size());
-            int progressValue = 0;
+            progressMonitor.setTicksCount(toUpdate.size());
             for (PluginInformation d : toUpdate) {
-                Main.pleaseWaitDlg.progress.setValue(progressValue++);
-                Main.pleaseWaitDlg.currentAction.setText(tr("Downloading Plugin {0}...", d.name));
+                progressMonitor.subTask(tr("Downloading Plugin {0}...", d.name));
+                progressMonitor.worked(1);
                 File pluginFile = new File(pluginDir, d.name + ".jar.new");
                 if(download(d, pluginFile))
