Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 3102)
@@ -324,5 +324,5 @@
         Collection<OsmPrimitive> selection = ds.getSelected();
         Collection<Command> cmds = new LinkedList<Command>();
-        Collection<OsmPrimitive> newSelection = ds.getSelected();
+        Collection<OsmPrimitive> newSelection = new LinkedList<OsmPrimitive>(ds.getSelected());
 
         ArrayList<Way> reuseWays = new ArrayList<Way>(),
Index: trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 3102)
@@ -55,12 +55,5 @@
         if (!isEnabled())
             return;
-        SearchSetting s = lastSearch;
-        if (s == null) {
-            s = new SearchSetting();
-        }
-        SearchSetting se = showSearchDialog(s);
-        if(se != null) {
-            searchWithHistory(se);
-        }
+        search();
     }
 
@@ -74,5 +67,7 @@
 
     public static SearchSetting showSearchDialog(SearchSetting initialValues) {
-
+        if (initialValues == null) {
+            initialValues = new SearchSetting();
+        }
         // -- prepare the combo box with the search expressions
         //
@@ -178,4 +173,15 @@
 
     /**
+     * Launches the dialog for specifying search criteria and runs
+     * a search
+     */
+    public static void search() {
+        SearchSetting se = showSearchDialog(lastSearch);
+        if(se != null) {
+            searchWithHistory(se);
+        }
+    }
+
+    /**
      * Adds the search specified by the settings in <code>s</code> to the
      * search history and performs the search.
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 3102)
@@ -9,5 +9,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -313,13 +312,11 @@
 
     /**
-     * Return a list of all selected objects. Even keys are returned.
-     * @return List of all selected objects.
+     * Replies an unmodifiable collection of primitives currently selected
+     * in this dataset
+     * 
+     * @return unmodifiable collection of primitives
      */
     public Collection<OsmPrimitive> getSelected() {
-        // It would be nice to have this be a copy-on-write list
-        // or an Collections.unmodifiableList().  It would be
-        // much faster for large selections.  May users just
-        // call this, and only check the .size().
-        return new ArrayList<OsmPrimitive>(selectedPrimitives);
+        return Collections.unmodifiableSet(selectedPrimitives);
     }
 
@@ -610,33 +607,4 @@
         }
         return a;
-    }
-
-    // Provide well-defined sorting for collections of OsmPrimitives.
-    // FIXME: probably not a good place to put this code.
-    public static OsmPrimitive[] sort(Collection<? extends OsmPrimitive> list) {
-        OsmPrimitive[] selArr = new OsmPrimitive[list.size()];
-        final HashMap<Object, String> h = new HashMap<Object, String>();
-        selArr = list.toArray(selArr);
-        Arrays.sort(selArr, new Comparator<OsmPrimitive>() {
-            public int compare(OsmPrimitive a, OsmPrimitive b) {
-                if (a.getClass() == b.getClass()) {
-                    String as = h.get(a);
-                    if (as == null) {
-                        as = a.getName() != null ? a.getName() : Long.toString(a.getId());
-                        h.put(a, as);
-                    }
-                    String bs = h.get(b);
-                    if (bs == null) {
-                        bs = b.getName() != null ? b.getName() : Long.toString(b.getId());
-                        h.put(b, bs);
-                    }
-                    int res = as.compareTo(bs);
-                    if (res != 0)
-                        return res;
-                }
-                return a.compareTo(b);
-            }
-        });
-        return selArr;
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 3102)
@@ -398,3 +398,32 @@
         }
     }
+
+    /**
+     * Replies true if at least one child primitive is incomplete
+     * 
+     * @return true if at least one child primitive is incomplete
+     */
+    public boolean hasIncompleteMembers() {
+        for (RelationMember rm: members) {
+            if (rm.getMember().isIncomplete()) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Replies a collection with the incomplete children this relation
+     * refers to
+     * 
+     * @return the incomplete children. Empty collection if no children are incomplete.
+     */
+    public Collection<OsmPrimitive> getIncompleteMembers() {
+        Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
+        for (RelationMember rm: members) {
+            if (!rm.getMember().isIncomplete()) {
+                continue;
+            }
+            ret.add(rm.getMember());
+        }
+        return ret;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintVisitor.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintVisitor.java	(revision 3102)
@@ -17,4 +17,5 @@
 import java.util.Comparator;
 import java.util.LinkedList;
+import java.util.List;
 
 import org.openstreetmap.josm.Main;
@@ -674,4 +675,5 @@
             Collection<Way> noAreaWays = new LinkedList<Way>();
 
+            List<Relation> relations = data.searchRelations(bbox);
             /*** RELATIONS ***/
             for (final Relation osm: data.searchRelations(bbox)) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 3102)
@@ -15,4 +15,5 @@
 import java.util.Comparator;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -52,4 +53,5 @@
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
@@ -234,4 +236,5 @@
 
         @Override public void mouseClicked(MouseEvent e) {
+            if (Main.main.getEditLayer() == null) return;
             if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
                 if (e.isControlDown()) {
@@ -254,4 +257,5 @@
         }
         @Override public void mousePressed(MouseEvent e) {
+            if (Main.main.getEditLayer() == null) return;
             if (e.isPopupTrigger()) {
                 openPopup(e);
@@ -259,4 +263,5 @@
         }
         @Override public void mouseReleased(MouseEvent e) {
+            if (Main.main.getEditLayer() == null) return;
             if (e.isPopupTrigger()) {
                 openPopup(e);
@@ -507,4 +512,45 @@
                     Main.map.mapView.getEditLayer())
             );
+        }
+    }
+
+    /**
+     * Action for downloading incomplete members of selected relations
+     * 
+     */
+    class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener{
+        public DownloadSelectedIncompleteMembersAction() {
+            putValue(SHORT_DESCRIPTION, tr("Download incomplete members of selected relations"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected"));
+            putValue(NAME, tr("Download incomplete members"));
+            updateEnabledState();
+        }
+
+        public Set<OsmPrimitive> buildSetOfIncompleteMembers(List<Relation> rels) {
+            Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
+            for(Relation r: rels) {
+                ret.addAll(r.getIncompleteMembers());
+            }
+            return ret;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (!isEnabled())
+                return;
+            List<Relation> rels = model.getSelectedRelationsWithIncompleteMembers();
+            if (rels.isEmpty()) return;
+            Main.worker.submit(new DownloadRelationMemberTask(
+                    rels,
+                    buildSetOfIncompleteMembers(rels),
+                    Main.map.mapView.getEditLayer()
+            ));
+        }
+
+        protected void updateEnabledState() {
+            setEnabled(!model.getSelectedRelationsWithIncompleteMembers().isEmpty());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
         }
     }
@@ -623,4 +669,21 @@
         }
 
+        /**
+         * Replies the list of selected relations with incomplete members
+         * 
+         * @return the list of selected relations with incomplete members
+         */
+        public List<Relation> getSelectedRelationsWithIncompleteMembers() {
+            List<Relation> ret = getSelectedNonNewRelations();
+            Iterator<Relation> it = ret.iterator();
+            while(it.hasNext()) {
+                Relation r = it.next();
+                if (!r.hasIncompleteMembers()) {
+                    it.remove();
+                }
+            }
+            return ret;
+        }
+
         public Object getElementAt(int index) {
             return relations.get(index);
@@ -715,4 +778,12 @@
             add(downloadMembersAction);
 
+            // -- download incomplete members action
+            //
+            DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembers = new DownloadSelectedIncompleteMembersAction();
+            displaylist.addListSelectionListener(downloadSelectedIncompleteMembers);
+            add(downloadSelectedIncompleteMembers);
+
+            addSeparator();
+
             // -- select members action
             //
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 3102)
@@ -2,5 +2,4 @@
 package org.openstreetmap.josm.gui.dialogs;
 
-import static org.openstreetmap.josm.tools.I18n.marktr;
 import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trn;
@@ -8,18 +7,25 @@
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
+import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
 import java.util.LinkedList;
-import java.util.NoSuchElementException;
+import java.util.List;
+import java.util.Set;
 
 import javax.swing.AbstractAction;
+import javax.swing.AbstractListModel;
 import javax.swing.BorderFactory;
-import javax.swing.DefaultListModel;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JButton;
 import javax.swing.JList;
 import javax.swing.JMenuItem;
@@ -29,153 +35,159 @@
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingConstants;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
 import javax.swing.plaf.basic.BasicArrowButton;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AutoScaleAction;
-import org.openstreetmap.josm.actions.search.SearchAction;
 import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
 import org.openstreetmap.josm.data.SelectionChangedListener;
-import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.NameFormatter;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataSetListener;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
+import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
+import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
 import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
+import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
+import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
 import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
+import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
 /**
- * A small tool dialog for displaying the current selection. The selection manager
- * respects clicks into the selection list. Ctrl-click will remove entries from
- * the list while single click will make the clicked entry the only selection.
- *
- * @author imi
+ * A small tool dialog for displaying the current selection.
+ * 
  */
-public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener {
-
-    private static final int SELECTION_HISTORY_SIZE = 10;
-
-    /**
-     * The selection's list data.
-     */
-    private final DefaultListModel list = new DefaultListModel();
-
-    private LinkedList<Collection<? extends OsmPrimitive>> selectionHistory;
-
-    /**
-     * The display list.
-     */
-    private JList displaylist = new JList(list);
-    private SideButton selectButton;
-    private SideButton searchButton;
-    private JPopupMenu popupMenu;
-    private JMenuItem zoomToElement;
+public class SelectionListDialog extends ToggleDialog  {
+
+    private JList lstPrimitives;
+    private SelectionListModel model;
 
     private SelectAction actSelect;
-
-    /**
-     * If the selection changed event is triggered with newSelection equals
-     * this element, the newSelection will not be added to the selection history
-     */
-    private Collection<? extends OsmPrimitive> historyIgnoreSelection = null;
-
-    public SelectionListDialog() {
-        super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."),
-                Shortcut.registerShortcut("subwindow:selection", tr("Toggle: {0}", tr("Current Selection")), KeyEvent.VK_T, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150, true);
-
-        selectionHistory = new LinkedList<Collection<? extends OsmPrimitive>>();
-        popupMenu = new JPopupMenu();
-        displaylist.setCellRenderer(new OsmPrimitivRenderer());
-        displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-        displaylist.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mouseClicked(MouseEvent e) {
-                if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
-                    updateMap();
-                }
-            }
-
-            @Override
-            public void mousePressed(MouseEvent e) {
-                showPopupMenu(e);
-            }
-
-            @Override
-            public void mouseReleased(MouseEvent e) {
-                showPopupMenu(e);
-            }
-
-        });
-
-        add(new JScrollPane(displaylist), BorderLayout.CENTER);
-
-        JPanel buttonPanel = getButtonPanel(2);
-        selectButton = new SideButton(actSelect = new SelectAction());
-        buttonPanel.add(selectButton);
+    private SearchAction actSearch;
+    private ZoomToJOSMSelectionAction actZoomToJOSMSelection;
+    private ZoomToListSelection actZoomToListSelection;
+    private DownloadSelectedIncompleteMembersAction actDownloadSelectedIncompleteMembers;
+
+    /**
+     * Builds the panel with the list of selected OSM primitives
+     * 
+     * @return the panel with the list of selected OSM primitives
+     */
+    protected JPanel buildListPanel() {
+        JPanel pnl = new JPanel(new BorderLayout());
+        DefaultListSelectionModel selectionModel  = new DefaultListSelectionModel();
+        model = new SelectionListModel(selectionModel);
+        lstPrimitives = new JList(model);
+        lstPrimitives.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        lstPrimitives.setSelectionModel(selectionModel);
+        lstPrimitives.setCellRenderer(new OsmPrimitivRenderer());
+        pnl.add(new JScrollPane(lstPrimitives), BorderLayout.CENTER);
+
+        return pnl;
+    }
+
+    /**
+     * Builds the row of action buttons at the bottom of this dialog
+     * 
+     * @return the panel
+     */
+    protected JPanel buildActionPanel() {
+        JPanel pnl = new  JPanel(new GridLayout(1,2));
+
+        // the select action
+        final JButton selectButton = new SideButton(actSelect = new SelectAction());
+        lstPrimitives.getSelectionModel().addListSelectionListener(actSelect);
+        pnl.add(selectButton);
         BasicArrowButton selectionHistoryMenuButton = createArrowButton(selectButton);
         selectionHistoryMenuButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
-                showSelectionHistoryMenu();
+                SelectionHistoryPopup.launch(selectButton, model.getSelectionHistory());
             }
         });
-        add(buttonPanel, BorderLayout.SOUTH);
-
-        zoomToElement = new JMenuItem(tr("Zoom to selected element(s)"));
-        zoomToElement.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                zoomToSelectedElement();
-            }
-        });
-
-        searchButton = new SideButton(marktr("Search"), "search", "SelectionList", tr("Search for objects."),
-                Main.main.menu.search);
-        buttonPanel.add(searchButton);
+
+        // the search button
+        final JButton searchButton = new SideButton(actSearch = new SearchAction());
+        pnl.add(searchButton);
 
         BasicArrowButton searchHistoryMenuButton = createArrowButton(searchButton);
         searchHistoryMenuButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
-                showSearchHistoryMenu();
+                SearchPopupMenu.launch(searchButton);
             }
         });
 
-        popupMenu.add(zoomToElement);
-        JMenuItem zoomToSelection = new JMenuItem(tr("Zoom to selection"));
-        zoomToSelection.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                zoomToSelection();
-            }
-        });
-        popupMenu.add(zoomToSelection);
-
-        if (Main.main.getCurrentDataSet() != null) {
-            selectionChanged(Main.main.getCurrentDataSet().getSelected());
-        }
-
+        return pnl;
+    }
+
+    /**
+     * Builds the content panel for this dialog
+     * 
+     * @return the content panel
+     */
+    protected JPanel buildContentPanel() {
+        JPanel pnl = new JPanel(new BorderLayout());
+        pnl.add(buildListPanel(), BorderLayout.CENTER);
+        pnl.add(buildActionPanel(), BorderLayout.SOUTH);
+        return pnl;
+    }
+
+    public SelectionListDialog() {
+        super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."),
+                Shortcut.registerShortcut("subwindow:selection", tr("Toggle: {0}", tr("Current Selection")), KeyEvent.VK_T, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT),
+                150, // default height
+                true // default is "show dialog"
+        );
+
+        add(buildContentPanel(), BorderLayout.CENTER);
+        model.addListDataListener(new TitleUpdater());
+        actZoomToJOSMSelection = new ZoomToJOSMSelectionAction();
+        model.addListDataListener(actZoomToJOSMSelection);
+
+        actZoomToListSelection = new ZoomToListSelection();
+        lstPrimitives.getSelectionModel().addListSelectionListener(actZoomToListSelection);
+
+        actDownloadSelectedIncompleteMembers = new DownloadSelectedIncompleteMembersAction();
+        lstPrimitives.getSelectionModel().addListSelectionListener(actDownloadSelectedIncompleteMembers);
+
+        lstPrimitives.addMouseListener(new SelectionPopupMenuLauncher());
     }
 
     @Override
     public void showNotify() {
-        SelectionEventManager.getInstance().addSelectionListener(this, FireMode.IN_EDT_CONSOLIDATED);
-        MapView.addEditLayerChangeListener(this);
-        MapView.addEditLayerChangeListener(actSelect);
-        updateSelection();
+        MapView.addEditLayerChangeListener(model);
+        SelectionEventManager.getInstance().addSelectionListener(model, FireMode.IN_EDT_CONSOLIDATED);
+        DatasetEventManager.getInstance().addDatasetListener(model, FireMode.IN_EDT);
+        MapView.addEditLayerChangeListener(actSearch);
     }
 
     @Override
     public void hideNotify() {
-        SelectionEventManager.getInstance().removeSelectionListener(this);
-        MapView.removeEditLayerChangeListener(this);
-        MapView.removeEditLayerChangeListener(actSelect);
-        updateTitle(0, 0, 0);
-    }
-
-    private BasicArrowButton createArrowButton(SideButton parentButton) {
+        MapView.removeEditLayerChangeListener(actSearch);
+        MapView.removeEditLayerChangeListener(model);
+        SelectionEventManager.getInstance().removeSelectionListener(model);
+        DatasetEventManager.getInstance().removeDatasetListener(model);
+    }
+
+    private BasicArrowButton createArrowButton(JButton parentButton) {
         BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
         arrowButton.setBorder(BorderFactory.createEmptyBorder());
@@ -185,130 +197,471 @@
     }
 
-    @Override
-    public void setVisible(boolean b) {
-        super.setVisible(b);
-        if (b && Main.main.getCurrentDataSet() != null) {
-            selectionChanged(Main.main.getCurrentDataSet().getSelected());
-        }
-    }
-
-    protected void showPopupMenu(MouseEvent e) {
-        if (e.isPopupTrigger()) {
-            zoomToElement.setVisible(displaylist.getSelectedIndex() >= 0);
-            popupMenu.show(e.getComponent(), e.getX(), e.getY());
-        }
-    }
-
-    public void zoomToSelection() {
-        new AutoScaleAction("selection").actionPerformed(null);
-    }
-
-    /**
-     * Zooms to the element(s) selected in {@link #displaylist}
-     */
-    public void zoomToSelectedElement() {
-        BoundingXYVisitor box = new BoundingXYVisitor();
-        int[] selected = displaylist.getSelectedIndices();
-        if (selected.length == 0)
-            return;
-        for (int i = 0; i < selected.length; i++) {
-            Object o = list.get(selected[i]);
-            if (o instanceof OsmPrimitive) {
-                ((OsmPrimitive) o).visit(box);
-            }
-        }
-        if (box.getBounds() == null)
-            return;
-        box.enlargeBoundingBox();
-        Main.map.mapView.recalculateCenterScale(box);
-    }
-
-    private void showSelectionHistoryMenu() {
-        if (selectionHistory.size() == 0)
-            return;
-        JPopupMenu historyMenu = new JPopupMenu();
-        for (Collection<? extends OsmPrimitive> sel : selectionHistory) {
-            SelectionMenuItem item = new SelectionMenuItem(sel);
-            historyMenu.add(item);
-        }
-        Rectangle r = selectButton.getBounds();
-        historyMenu.show(selectButton, r.x, r.y + r.height);
-    }
-
-    private void showSearchHistoryMenu() {
-        if (SearchAction.searchHistory.size() == 0)
-            return;
-        JPopupMenu historyMenu = new JPopupMenu();
-        for (SearchAction.SearchSetting s : SearchAction.searchHistory) {
-            SearchMenuItem item = new SearchMenuItem(s);
-            historyMenu.add(item);
-        }
-        Rectangle r = searchButton.getBounds();
-        historyMenu.show(searchButton, r.x, r.y + r.height);
-    }
-
-    /**
-     * Called when the selection in the dataset changed.
-     * @param newSelection The new selection array.
-     */
-    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
-        if (list == null || !isVisible())
-            return; // selection changed may be received in base class constructor before init
-        OsmPrimitive selArr[] = DataSet.sort(newSelection);
-        list.setSize(selArr.length);
-        int i = 0;
-        for (OsmPrimitive osm : selArr) {
-            list.setElementAt(osm, i++);
-        }
-
-        int ways = 0;
-        int nodes = 0;
-        int relations = 0;
-        for (OsmPrimitive o : newSelection) {
-            if (o instanceof Way) {
-                ways++;
-            } else if (o instanceof Node) {
-                nodes++;
-            } else if (o instanceof Relation) {
-                relations++;
-            }
-        }
-
-        updateTitle(nodes, ways, relations);
-
-        if (selectionHistory != null && newSelection.size() > 0 && !newSelection.equals(historyIgnoreSelection)) {
-            historyIgnoreSelection = null;
-            try {
-                // Check if the newSelection has already been added to the history
-                Collection<? extends OsmPrimitive> first = selectionHistory.getFirst();
-                if (first.equals(newSelection))
-                    return;
-            } catch (NoSuchElementException e) {
-            }
-            selectionHistory.addFirst(newSelection);
-            while (selectionHistory.size() > SELECTION_HISTORY_SIZE) {
-                selectionHistory.removeLast();
-            }
-        }
-    }
-
-    private void updateTitle(int nodes, int ways, int relations) {
-        if( (nodes+ways+relations) != 0) {
-            setTitle(tr("Sel.: Rel.:{0} / Ways:{1} / Nodes:{2}", relations, ways, nodes));
-        } else {
-            setTitle(tr("Selection"));
-        }
-    }
-
-    /**
-     * Sets the selection of the map to the current selected items.
-     */
-    public void updateMap() {
-        Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>();
-        for (int i = 0; i < list.getSize(); ++i)
-            if (displaylist.isSelectedIndex(i)) {
-                sel.add((OsmPrimitive) list.get(i));
-            }
-        Main.main.getCurrentDataSet().setSelected(sel);
+    /**
+     * The popup menu launcher
+     */
+    class SelectionPopupMenuLauncher extends PopupMenuLauncher {
+        private SelectionPopup popup = new SelectionPopup();
+
+        @Override
+        public void launch(MouseEvent evt) {
+            if (model.getSelected().isEmpty()) {
+                int idx = lstPrimitives.locationToIndex(evt.getPoint());
+                if (idx < 0) return;
+                model.setSelected(Collections.singleton((OsmPrimitive)model.getElementAt(idx)));
+            }
+            popup.show(lstPrimitives, evt.getX(), evt.getY());
+        }
+    }
+
+    /**
+     * The popup menu for the selection list
+     */
+    class SelectionPopup extends JPopupMenu {
+        public SelectionPopup() {
+            add(actZoomToJOSMSelection);
+            add(actZoomToListSelection);
+            addSeparator();
+            add(actDownloadSelectedIncompleteMembers);
+        }
+    }
+
+    /**
+     * Updates the dialog title with a summary of the current JOSM selection
+     */
+    class TitleUpdater implements ListDataListener {
+        protected void updateTitle() {
+            setTitle(model.getJOSMSelectionSummary());
+        }
+
+        public void contentsChanged(ListDataEvent e) {
+            updateTitle();
+        }
+
+        public void intervalAdded(ListDataEvent e) {
+            updateTitle();
+        }
+
+        public void intervalRemoved(ListDataEvent e) {
+            updateTitle();
+        }
+    }
+
+    /**
+     * Launches the search dialog
+     */
+    class SearchAction extends AbstractAction implements EditLayerChangeListener {
+        public SearchAction() {
+            putValue(NAME, tr("Search"));
+            putValue(SHORT_DESCRIPTION,   tr("Search for objects"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs","select"));
+            updateEnabledState();
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (!isEnabled()) return;
+            org.openstreetmap.josm.actions.search.SearchAction.search();
+        }
+
+        public void updateEnabledState() {
+            setEnabled(Main.main != null && Main.main.getEditLayer() != null);
+        }
+
+        @Override
+        public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+            updateEnabledState();
+        }
+    }
+
+    /**
+     * Sets the current JOSM selection to the OSM primitives selected in the list
+     * of this dialog
+     */
+    class SelectAction extends AbstractAction implements ListSelectionListener {
+        public SelectAction() {
+            putValue(NAME, tr("Select"));
+            putValue(SHORT_DESCRIPTION,  tr("Set the selected elements on the map to the selected items in the list above."));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs","select"));
+            updateEnabledState();
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            Collection<OsmPrimitive> sel = model.getSelected();
+            if (sel.isEmpty())return;
+            if (Main.map == null || Main.map.mapView == null || Main.map.mapView.getEditLayer() == null) return;
+            Main.map.mapView.getEditLayer().data.setSelected(sel);
+        }
+
+        public void updateEnabledState() {
+            setEnabled(!model.getSelected().isEmpty());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
+        }
+    }
+
+    /**
+     * The action for zooming to the primitives in the current JOSM selection
+     * 
+     */
+    class ZoomToJOSMSelectionAction extends AbstractAction implements ListDataListener {
+
+        public ZoomToJOSMSelectionAction() {
+            putValue(NAME,tr("Zoom to selection"));
+            putValue(SHORT_DESCRIPTION, tr("Zoom to selection"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
+            updateEnabledState();
+        }
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            new AutoScaleAction("selection").autoScale();
+        }
+
+        public void updateEnabledState() {
+            setEnabled(model.getSize() > 0);
+        }
+
+        public void contentsChanged(ListDataEvent e) {
+            updateEnabledState();
+        }
+
+        public void intervalAdded(ListDataEvent e) {
+            updateEnabledState();
+        }
+
+        public void intervalRemoved(ListDataEvent e) {
+            updateEnabledState();
+        }
+    }
+
+    /**
+     * The action for zooming to the primitives which are currently selected in
+     * the list displaying the JOSM selection
+     * 
+     */
+    class ZoomToListSelection extends AbstractAction implements ListSelectionListener{
+        public ZoomToListSelection() {
+            putValue(NAME, tr("Zoom to selected element(s)"));
+            putValue(SHORT_DESCRIPTION, tr("Zoom to selected element(s)"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
+            updateEnabledState();
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            BoundingXYVisitor box = new BoundingXYVisitor();
+            Collection<OsmPrimitive> sel = model.getSelected();
+            if (sel.isEmpty()) return;
+            box.computeBoundingBox(sel);
+            if (box.getBounds() == null)
+                return;
+            box.enlargeBoundingBox();
+            Main.map.mapView.recalculateCenterScale(box);
+        }
+
+        public void updateEnabledState() {
+            setEnabled(!model.getSelected().isEmpty());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
+        }
+    }
+
+    /**
+     * The list model for the list of OSM primitives in the current JOSM selection.
+     * 
+     * The model also maintains a history of the last {@see SelectionListModel#SELECTION_HISTORY_SIZE}
+     * JOSM selection.
+     * 
+     */
+    static private class SelectionListModel extends AbstractListModel implements EditLayerChangeListener, SelectionChangedListener, DataSetListener{
+
+        private static final int SELECTION_HISTORY_SIZE = 10;
+
+        private final LinkedList<Collection<? extends OsmPrimitive>> history = new LinkedList<Collection<? extends OsmPrimitive>>();
+        private final List<OsmPrimitive> selection = new ArrayList<OsmPrimitive>();
+        private DefaultListSelectionModel selectionModel;
+
+        /**
+         * Constructor
+         * @param selectionModel the selection model used in the list
+         */
+        public SelectionListModel(DefaultListSelectionModel selectionModel) {
+            this.selectionModel = selectionModel;
+        }
+
+        /**
+         * Replies a summary of the current JOSM selection
+         * 
+         * @return a summary of the current JOSM selection
+         */
+        public String getJOSMSelectionSummary() {
+            if (selection.isEmpty()) return tr("Selection");
+            int numNodes = 0;
+            int numWays = 0;
+            int numRelations = 0;
+            for (OsmPrimitive p: selection) {
+                switch(p.getType()) {
+                case NODE: numNodes++; break;
+                case WAY: numWays++; break;
+                case RELATION: numRelations++; break;
+                }
+            }
+            return tr("Sel.: Rel.:{0} / Ways:{1} / Nodes:{2}", numRelations, numWays, numNodes);
+        }
+
+        /**
+         * Remembers a JOSM selection the history of JOSM selections
+         * 
+         * @param selection the JOSM selection. Ignored if null or empty.
+         */
+        public void remember(Collection<? extends OsmPrimitive> selection) {
+            if (selection == null)return;
+            if (selection.isEmpty())return;
+            if (history.isEmpty()) {
+                history.add(selection);
+                return;
+            }
+            if (history.getFirst().equals(selection)) return;
+            history.addFirst(selection);
+            while (history.size() > SELECTION_HISTORY_SIZE) {
+                history.removeLast();
+            }
+        }
+
+        /**
+         * Replies the history of JOSM selections
+         * 
+         * @return
+         */
+        public List<Collection<? extends OsmPrimitive>> getSelectionHistory() {
+            return history;
+        }
+
+        @Override
+        public Object getElementAt(int index) {
+            return selection.get(index);
+        }
+
+        @Override
+        public int getSize() {
+            return selection.size();
+        }
+
+        /**
+         * Replies the collection of OSM primitives currently selected in the view
+         * of this model
+         * 
+         * @return
+         */
+        public Collection<OsmPrimitive> getSelected() {
+            Set<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
+            for(int i=0; i< getSize();i++) {
+                if (selectionModel.isSelectedIndex(i)) {
+                    sel.add(selection.get(i));
+                }
+            }
+            return sel;
+        }
+
+        /**
+         * Sets the OSM primitives to be selected in the view of this model
+         * 
+         * @param sel the collection of primitives to select
+         */
+        public void setSelected(Collection<OsmPrimitive> sel) {
+            selectionModel.clearSelection();
+            if (sel == null) return;
+            for (OsmPrimitive p: sel){
+                int i = selection.indexOf(p);
+                if (i >= 0){
+                    selectionModel.addSelectionInterval(i, i);
+                }
+            }
+        }
+
+        @Override
+        protected void fireContentsChanged(Object source, int index0, int index1) {
+            Collection<OsmPrimitive> sel = getSelected();
+            super.fireContentsChanged(source, index0, index1);
+            setSelected(sel);
+        }
+
+        /**
+         * Sets the collection of currently selected OSM objects
+         * 
+         * @param selection the collection of currently selected OSM objects
+         */
+        public void setJOSMSelection(Collection<? extends OsmPrimitive> selection) {
+            this.selection.clear();
+            if (selection == null) {
+                fireContentsChanged(this, 0, getSize());
+                return;
+            }
+            this.selection.addAll(selection);
+            sort();
+            fireContentsChanged(this, 0, getSize());
+            remember(selection);
+        }
+
+        /**
+         * Sorts the primitives in the list
+         */
+        public void sort() {
+            Collections.sort(
+                    this.selection,
+                    new Comparator<OsmPrimitive>() {
+                        NameFormatter nf = DefaultNameFormatter.getInstance();
+                        @Override
+                        public int compare(OsmPrimitive o1, OsmPrimitive o2) {
+
+                            if (o1.getType() != o2.getType())
+                                return o1.getType().compareTo(o2.getType());
+                            return o1.getDisplayName(nf).compareTo(o2.getDisplayName(nf));
+                        }
+                    }
+            );
+        }
+
+        /**
+         * Triggers a refresh of the view for all primitives in {@code toUpdate}
+         * which are currently displayed in the view
+         * 
+         * @param toUpdate the collection of primitives to update
+         */
+        public void update(Collection<? extends OsmPrimitive> toUpdate) {
+            if (toUpdate == null) return;
+            if (toUpdate.isEmpty()) return;
+            Collection<OsmPrimitive> sel = getSelected();
+            for (OsmPrimitive p: toUpdate){
+                int i = selection.indexOf(p);
+                if (i >= 0) {
+                    super.fireContentsChanged(this, i,i);
+                }
+            }
+            setSelected(sel);
+        }
+
+        /**
+         * Replies the list of selected relations with incomplete members
+         * 
+         * @return the list of selected relations with incomplete members
+         */
+        public List<Relation> getSelectedRelationsWithIncompleteMembers() {
+            List<Relation> ret = new LinkedList<Relation>();
+            for(int i=0; i<getSize(); i++) {
+                if (!selectionModel.isSelectedIndex(i)) {
+                    continue;
+                }
+                OsmPrimitive p = selection.get(i);
+                if (! (p instanceof Relation)) {
+                    continue;
+                }
+                if (p.isNew()) {
+                    continue;
+                }
+                Relation r = (Relation)p;
+                if (r.hasIncompleteMembers()) {
+                    ret.add(r);
+                }
+            }
+            return ret;
+        }
+
+        /* ------------------------------------------------------------------------ */
+        /* interface EditLayerChangeListener                                        */
+        /* ------------------------------------------------------------------------ */
+        public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+            if (newLayer == null) {
+                setJOSMSelection(null);
+            } else {
+                setJOSMSelection(newLayer.data.getSelected());
+            }
+        }
+
+        /* ------------------------------------------------------------------------ */
+        /* interface SelectionChangeListener                                        */
+        /* ------------------------------------------------------------------------ */
+        public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
+            setJOSMSelection(newSelection);
+        }
+
+        /* ------------------------------------------------------------------------ */
+        /* interface DataSetListener                                                */
+        /* ------------------------------------------------------------------------ */
+        public void dataChanged(DataChangedEvent event) {
+            // refresh the whole list
+            fireContentsChanged(this, 0, getSize());
+        }
+
+        public void nodeMoved(NodeMovedEvent event) {
+            // may influence the display name of primitives, update the data
+            update(event.getPrimitives());
+        }
+
+        public void otherDatasetChange(AbstractDatasetChangedEvent event) {
+            // may influence the display name of primitives, update the data
+            update(event.getPrimitives());
+        }
+
+        public void relationMembersChanged(RelationMembersChangedEvent event) {
+            // may influence the display name of primitives, update the data
+            update(event.getPrimitives());
+        }
+
+        public void tagsChanged(TagsChangedEvent event) {
+            // may influence the display name of primitives, update the data
+            update(event.getPrimitives());
+        }
+
+        public void wayNodesChanged(WayNodesChangedEvent event) {
+            // may influence the display name of primitives, update the data
+            update(event.getPrimitives());
+        }
+
+        @Override
+        public void primtivesAdded(PrimitivesAddedEvent event) {/* ignored - handled by SelectionChangeListener */}
+        @Override
+        public void primtivesRemoved(PrimitivesRemovedEvent event) {/* ignored - handled by SelectionChangeListener*/}
+    }
+
+    /**
+     * A specialized {@link JMenuItem} for presenting one entry of the search history
+     *
+     * @author Jan Peter Stotz
+     */
+    protected static class SearchMenuItem extends JMenuItem implements ActionListener {
+        protected SearchSetting s;
+
+        public SearchMenuItem(SearchSetting s) {
+            super(s.toString());
+            this.s = s;
+            addActionListener(this);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            org.openstreetmap.josm.actions.search.SearchAction.searchWithoutHistory(s);
+        }
+    }
+
+    /**
+     * The popup menu for the search history entries
+     * 
+     */
+    protected static class SearchPopupMenu extends JPopupMenu {
+        static public void launch(Component parent) {
+            if (org.openstreetmap.josm.actions.search.SearchAction.searchHistory.isEmpty())
+                return;
+            JPopupMenu menu = new SearchPopupMenu();
+            Rectangle r = parent.getBounds();
+            menu.show(parent, r.x, r.y + r.height);
+        }
+
+        public SearchPopupMenu() {
+            for (SearchSetting ss: org.openstreetmap.josm.actions.search.SearchAction.searchHistory) {
+                add(new SearchMenuItem(ss));
+            }
+        }
     }
 
@@ -318,5 +671,5 @@
      * @author Jan Peter Stotz
      */
-    protected class SelectionMenuItem extends JMenuItem implements ActionListener {
+    protected static class SelectionMenuItem extends JMenuItem implements ActionListener {
         protected Collection<? extends OsmPrimitive> sel;
 
@@ -336,16 +689,16 @@
                 }
             }
-            String text = "";
+            StringBuffer text = new StringBuffer();
             if(ways != 0) {
-                text += (text.length() > 0 ? ", " : "")
-                + trn("{0} way", "{0} ways", ways, ways);
+                text.append(text.length() > 0 ? ", " : "")
+                .append(trn("{0} way", "{0} ways", ways, ways));
             }
             if(nodes != 0) {
-                text += (text.length() > 0 ? ", " : "")
-                + trn("{0} node", "{0} nodes", nodes, nodes);
+                text.append(text.length() > 0 ? ", " : "")
+                .append(trn("{0} node", "{0} nodes", nodes, nodes));
             }
             if(relations != 0) {
-                text += (text.length() > 0 ? ", " : "")
-                + trn("{0} relation", "{0} relations", relations, relations);
+                text.append(text.length() > 0 ? ", " : "")
+                .append(trn("{0} relation", "{0} relations", relations, relations));
             }
             setText(tr("Selection: {0}", text));
@@ -354,61 +707,64 @@
 
         public void actionPerformed(ActionEvent e) {
-            historyIgnoreSelection = sel;
             Main.main.getCurrentDataSet().setSelected(sel);
         }
-
-    }
-
-    /**
-     * A specialized {@link JMenuItem} for presenting one entry of the search history
+    }
+
+    /**
+     * The popup menue for the JOSM selection history entries
      *
-     * @author Jan Peter Stotz
-     */
-    protected static class SearchMenuItem extends JMenuItem implements ActionListener {
-        protected SearchSetting s;
-
-        public SearchMenuItem(SearchSetting s) {
-            super(s.toString());
-            this.s = s;
-            addActionListener(this);
+     */
+    protected static class SelectionHistoryPopup extends JPopupMenu {
+        static public void launch(Component parent, Collection<Collection<? extends OsmPrimitive>> history) {
+            if (history == null || history.isEmpty()) return;
+            JPopupMenu menu = new SelectionHistoryPopup(history);
+            Rectangle r = parent.getBounds();
+            menu.show(parent, r.x, r.y + r.height);
+        }
+
+        public SelectionHistoryPopup(Collection<Collection<? extends OsmPrimitive>> history) {
+            for (Collection<? extends OsmPrimitive> sel : history) {
+                add(new SelectionMenuItem(sel));
+            }
+        }
+    }
+
+    /**
+     * Action for downloading incomplete members of selected relations
+     * 
+     */
+    class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener{
+        public DownloadSelectedIncompleteMembersAction() {
+            putValue(SHORT_DESCRIPTION, tr("Download incomplete members of selected relations"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected"));
+            putValue(NAME, tr("Download incomplete members"));
+            updateEnabledState();
+        }
+
+        public Set<OsmPrimitive> buildSetOfIncompleteMembers(List<Relation> rels) {
+            Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
+            for(Relation r: rels) {
+                ret.addAll(r.getIncompleteMembers());
+            }
+            return ret;
         }
 
         public void actionPerformed(ActionEvent e) {
-            SearchAction.searchWithoutHistory(s);
-        }
-
-    }
-
-    private void updateSelection() {
-        if (Main.main.getCurrentDataSet() == null) {
-            selectionChanged(Collections.<OsmPrimitive>emptyList());
-        } else {
-            selectionChanged(Main.main.getCurrentDataSet().getSelected());
-        }
-    }
-
-    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
-        updateSelection();
-    }
-
-    class SelectAction extends AbstractAction implements EditLayerChangeListener {
-        public SelectAction() {
-            putValue(NAME, tr("Select"));
-            putValue(SHORT_DESCRIPTION,  tr("Set the selected elements on the map to the selected items in the list above."));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs","select"));
-            updateEnabledState();
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            updateMap();
-        }
-
-        public void updateEnabledState() {
-            setEnabled(Main.main != null && Main.main.getEditLayer() != null);
-        }
-
-        @Override
-        public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+            if (!isEnabled())
+                return;
+            List<Relation> rels = model.getSelectedRelationsWithIncompleteMembers();
+            if (rels.isEmpty()) return;
+            Main.worker.submit(new DownloadRelationMemberTask(
+                    rels,
+                    buildSetOfIncompleteMembers(rels),
+                    Main.map.mapView.getEditLayer()
+            ));
+        }
+
+        protected void updateEnabledState() {
+            setEnabled(!model.getSelectedRelationsWithIncompleteMembers().isEmpty());
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
             updateEnabledState();
         }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java	(revision 3102)
@@ -8,4 +8,6 @@
 import java.io.IOException;
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.swing.SwingUtilities;
@@ -32,19 +34,34 @@
     private boolean cancelled;
     private Exception lastException;
-    private Relation parent;
+    private final Set<Relation> parents = new HashSet<Relation>();
     private Collection<OsmPrimitive> children;
     private OsmDataLayer curLayer;
     private MultiFetchServerObjectReader objectReader;
 
-    public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer, MemberTableModel memberTableModel, Dialog dialog) {
+    public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer, Dialog dialog) {
         super(tr("Download relation members"), new PleaseWaitProgressMonitor(dialog), false /* don't ignore exception */);
-        this.parent = parent;
+        this.parents.add(parent);
         this.children = children;
         this.curLayer = curLayer;
     }
 
-    public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer, MemberTableModel memberTableModel) {
+    public DownloadRelationMemberTask(Relation parent, Collection<OsmPrimitive> children, OsmDataLayer curLayer) {
         super(tr("Download relation members"), false /* don't ignore exception */);
-        this.parent = parent;
+        this.parents.add(parent);
+        this.children = children;
+        this.curLayer = curLayer;
+    }
+
+    /**
+     * Creates a download task for downloading the child primitives {@code children} for all parent
+     * relations in {@code parents}.
+     * 
+     * @param parents the collection of parent relations
+     * @param children the collection of child primitives to download
+     * @param curLayer the current OSM layer
+     */
+    public DownloadRelationMemberTask(Collection<Relation> parents, Collection<OsmPrimitive> children, OsmDataLayer curLayer) {
+        super(tr("Download relation members"), false /* don't ignore exception */);
+        this.parents.addAll(parents);
         this.children = children;
         this.curLayer = curLayer;
@@ -71,4 +88,22 @@
     }
 
+    protected String buildDownloadFeedbackMessage() {
+        if (parents.size() == 1) {
+            Relation parent = parents.iterator().next();
+            return trn("Downloading {0} incomplete child of relation ''{1}''",
+                    "Downloading {0} incomplete children of relation ''{1}''",
+                    children.size(),
+                    children.size(),
+                    parent.getDisplayName(DefaultNameFormatter.getInstance())
+            );
+        } else
+            return trn("Downloading {0} incomplete child of {1} parent relations",
+                    "Downloading {0} incomplete children of  {1} parent relations",
+                    children.size(),
+                    children.size(),
+                    parents.size()
+            );
+    }
+
     @Override
     protected void realRun() throws SAXException, IOException, OsmTransferException {
@@ -80,10 +115,5 @@
             objectReader.append(children);
             progressMonitor.indeterminateSubTask(
-                    trn("Downloading {0} incomplete child of relation ''{1}''",
-                            "Downloading {0} incomplete children of relation ''{1}''",
-                            children.size(),
-                            children.size(),
-                            parent.getDisplayName(DefaultNameFormatter.getInstance())
-                    )
+                    buildDownloadFeedbackMessage()
             );
             final DataSet dataSet = objectReader.parseOsm(progressMonitor
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 3101)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 3102)
@@ -1241,5 +1241,4 @@
                     memberTableModel.getIncompleteMemberPrimitives(),
                     getLayer(),
-                    memberTableModel,
                     GenericRelationEditor.this)
             );
@@ -1275,5 +1274,4 @@
                     memberTableModel.getSelectedIncompleteMemberPrimitives(),
                     getLayer(),
-                    memberTableModel,
                     GenericRelationEditor.this)
             );
