Index: trunk/src/org/openstreetmap/josm/actions/DownloadPrimitiveAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DownloadPrimitiveAction.java	(revision 5764)
+++ trunk/src/org/openstreetmap/josm/actions/DownloadPrimitiveAction.java	(revision 5765)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
 import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trc;
 import static org.openstreetmap.josm.tools.I18n.trn;
 
@@ -10,17 +9,10 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.awt.event.KeyEvent;
 import java.lang.reflect.InvocationTargetException;
-import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
-import javax.swing.BorderFactory;
-import javax.swing.GroupLayout;
 
-import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
@@ -28,9 +20,5 @@
 import javax.swing.JScrollPane;
 import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.KeyStroke;
 import javax.swing.SwingUtilities;
-import javax.swing.border.EtchedBorder;
-import javax.swing.plaf.basic.BasicComboBoxEditor;
 
 import org.openstreetmap.josm.Main;
@@ -38,13 +26,10 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.download.DownloadObjectDialog;
 import org.openstreetmap.josm.gui.io.DownloadPrimitivesTask;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
-import org.openstreetmap.josm.gui.widgets.OsmIdTextField;
-import org.openstreetmap.josm.gui.widgets.OsmPrimitiveTypesComboBox;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -64,146 +49,10 @@
     }
 
-    /**
-     * Restore the current history from the preferences
-     *
-     * @param cbHistory
-     */
-    protected void restorePrimitivesHistory(HistoryComboBox cbHistory) {
-        List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(getClass().getName() + ".primitivesHistory", new LinkedList<String>()));
-        // we have to reverse the history, because ComboBoxHistory will reverse it again
-        // in addElement()
-        //
-        Collections.reverse(cmtHistory);
-        cbHistory.setPossibleItems(cmtHistory);
-    }
-
-    /**
-     * Remind the current history in the preferences
-     * @param cbHistory
-     */
-    protected void remindPrimitivesHistory(HistoryComboBox cbHistory) {
-        cbHistory.addCurrentItemToHistory();
-        Main.pref.putCollection(getClass().getName() + ".primitivesHistory", cbHistory.getHistory());
-    }
-
     public void actionPerformed(ActionEvent e) {
 
-        JPanel all = new JPanel();
-        GroupLayout layout = new GroupLayout(all);
-        all.setLayout(layout);
-        layout.setAutoCreateGaps(true);
-        layout.setAutoCreateContainerGaps(true);
+        DownloadObjectDialog dialog = new DownloadObjectDialog();
+        if (dialog.showDialog().getValue() != 1) return;
 
-        JLabel lbl1 = new JLabel(tr("Object type:"));
-        final OsmPrimitiveTypesComboBox cbType = new OsmPrimitiveTypesComboBox();
-        cbType.addItem(trc("osm object types", "mixed"));
-        cbType.setToolTipText(tr("Choose the OSM object type"));
-        JLabel lbl2 = new JLabel(tr("Object ID:"));
-        final OsmIdTextField tfId = new OsmIdTextField();
-        HistoryComboBox cbId = new HistoryComboBox();
-        cbId.setEditor(new BasicComboBoxEditor() {
-            @Override
-            protected JTextField createEditorComponent() {
-                return tfId;
-            }
-        });
-        cbId.setToolTipText(tr("Enter the ID of the object that should be downloaded"));
-        restorePrimitivesHistory(cbId);
-        // forward the enter key stroke to the download button
-        tfId.getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false));
-        JCheckBox layer = new JCheckBox(tr("Separate Layer"));
-        layer.setToolTipText(tr("Select if the data should be downloaded into a new layer"));
-        layer.setSelected(Main.pref.getBoolean("download.newlayer"));
-        final JCheckBox referrers = new JCheckBox(tr("Download referrers (parent relations)"));
-        referrers.setToolTipText(tr("Select if the referrers of the object should be downloaded as well, i.e.,"
-                + "parent relations and for nodes, additionally, parent ways"));
-        referrers.setSelected(Main.pref.getBoolean("downloadprimitive.referrers", true));
-        JCheckBox full = new JCheckBox(tr("Download relation members"));
-        full.setToolTipText(tr("Select if the members of a relation should be downloaded as well"));
-        full.setSelected(Main.pref.getBoolean("downloadprimitive.full", true));
-        HtmlPanel help = new HtmlPanel(tr("Object IDs can be separated by comma or space.<br/>"
-                + " Examples: <b><ul><li>1 2 5</li><li>1,2,5</li></ul><br/></b>"
-                + " In mixed mode, specify objects like this: <b>w123, n110, w12, r15</b><br/>"));
-        help.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
-
-        layout.setVerticalGroup(layout.createSequentialGroup()
-            .addGroup(layout.createParallelGroup()
-                .addComponent(lbl1)
-                .addComponent(cbType, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
-            .addGroup(layout.createParallelGroup()
-                .addComponent(lbl2)
-                .addComponent(cbId, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
-            .addComponent(referrers)
-            .addComponent(full)
-            .addComponent(layer)
-            .addComponent(help)
-        );
-
-        cbType.addItemListener(new ItemListener() {
-
-            @Override
-            public void itemStateChanged(ItemEvent e) {
-                tfId.setType(cbType.getType());
-                tfId.performValidation();
-                referrers.setText(cbType.getType() == OsmPrimitiveType.NODE
-                        ? tr("Download referrers (parent relations and ways)")
-                        : tr("Download referrers (parent relations)"));
-            }
-        });
-
-        layout.setHorizontalGroup(layout.createParallelGroup()
-            .addGroup(layout.createSequentialGroup()
-                .addGroup(layout.createParallelGroup()
-                    .addComponent(lbl1)
-                    .addComponent(lbl2)
-                )
-                .addGroup(layout.createParallelGroup()
-                    .addComponent(cbType)
-                    .addComponent(cbId))
-                )
-            .addComponent(referrers)
-            .addComponent(full)
-            .addComponent(layer)
-            .addComponent(help)
-        );
-
-        ExtendedDialog dialog = new ExtendedDialog(Main.parent,
-                tr("Download object"),
-                new String[] {tr("Download object"), tr("Cancel")}
-        );
-        dialog.setContent(all, false);
-        dialog.setButtonIcons(new String[] {"download.png", "cancel.png"});
-        dialog.setToolTipTexts(new String[] {
-                tr("Start downloading"),
-                tr("Close dialog and cancel downloading")
-        });
-        dialog.setDefaultButton(1);
-        dialog.configureContextsensitiveHelp("/Action/DownloadObject", true /* show help button */);
-        cbType.setSelectedIndex(Main.pref.getInteger("downloadprimitive.lasttype", 0));
-        tfId.setType(cbType.getType());
-        if (Main.pref.getBoolean("downloadprimitive.autopaste", true)) { 
-            tryToPasteFromClipboard(tfId, cbType);
-        }
-        
-        dialog.showDialog();
-        if (dialog.getValue() != 1) return;
-        Main.pref.putInteger("downloadprimitive.lasttype", cbType.getSelectedIndex());
-        Main.pref.put("downloadprimitive.referrers", referrers.isSelected());
-        Main.pref.put("downloadprimitive.full", full.isSelected());
-        Main.pref.put("download.newlayer", layer.isSelected());
-
-        tfId.setType(cbType.getType());
-        if(!tfId.readOsmIds()) {
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr("Invalid ID list specified\n"
-                    + "Cannot download object."),
-                    tr("Information"),
-                    JOptionPane.INFORMATION_MESSAGE
-            );
-            return;
-        }
-        remindPrimitivesHistory(cbId);
-        processItems(layer.isSelected(), tfId.getIds(), referrers.isSelected(), full.isSelected());
+        processItems(dialog.isNewLayerRequested(), dialog.getOsmIds(), dialog.isReferrersRequested(), dialog.isFullRelationRequested());
     }
 
@@ -232,22 +81,21 @@
             @Override
             public void run() {
-                Set<PrimitiveId> errs = task.getMissingPrimitives();
+                final Set<PrimitiveId> errs = task.getMissingPrimitives();
                 if (errs != null && !errs.isEmpty()) {
-                    final ExtendedDialog dlg = reportProblemDialog(errs,
-                            trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()),
-                            trn("One object could not be downloaded.<br>",
-                                "{0} objects could not be downloaded.<br>",
-                                errs.size(),
-                                errs.size())
-                            + tr("The server replied with response code 404.<br>"
-                                + "This usually means, the server does not know an object with the requested id."),
-                            tr("missing objects:"),
-                            JOptionPane.ERROR_MESSAGE
-                    );
                     try {
                         SwingUtilities.invokeAndWait(new Runnable() {
                             @Override
                             public void run() {
-                                dlg.showDialog();
+                                reportProblemDialog(errs,
+                                        trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()),
+                                        trn("One object could not be downloaded.<br>",
+                                            "{0} objects could not be downloaded.<br>",
+                                            errs.size(),
+                                            errs.size())
+                                        + tr("The server replied with response code 404.<br>"
+                                            + "This usually means, the server does not know an object with the requested id."),
+                                        tr("missing objects:"),
+                                        JOptionPane.ERROR_MESSAGE
+                                ).showDialog();
                             }
                         });
@@ -257,5 +105,5 @@
                 }
 
-                Set<PrimitiveId> del = new TreeSet<PrimitiveId>();
+                final Set<PrimitiveId> del = new TreeSet<PrimitiveId>();
                 DataSet ds = getCurrentDataSet();
                 for (PrimitiveId id : ids) {
@@ -266,18 +114,17 @@
                 }
                 if (!del.isEmpty()) {
-                    final ExtendedDialog dlg = reportProblemDialog(del,
-                            trn("Object deleted", "Objects deleted", del.size()),
-                            trn(
-                                "One downloaded object is deleted.",
-                                "{0} downloaded objects are deleted.",
-                                del.size(),
-                                del.size()),
-                            null,
-                            JOptionPane.WARNING_MESSAGE
-                    );
                     SwingUtilities.invokeLater(new Runnable() {
                         @Override
                         public void run() {
-                            dlg.showDialog();
+                            reportProblemDialog(del,
+                                    trn("Object deleted", "Objects deleted", del.size()),
+                                    trn(
+                                        "One downloaded object is deleted.",
+                                        "{0} downloaded objects are deleted.",
+                                        del.size(),
+                                        del.size()),
+                                    null,
+                                    JOptionPane.WARNING_MESSAGE
+                            ).showDialog();
                         }
                     });
@@ -315,22 +162,3 @@
             .setContent(p, false);
     }
-
-    private void tryToPasteFromClipboard(OsmIdTextField tfId, OsmPrimitiveTypesComboBox cbType) {
-        String buf = Utils.getClipboardContent();
-        if (buf != null) {
-            if (buf.contains("node")) cbType.setSelectedIndex(0);
-            if (buf.contains("way")) cbType.setSelectedIndex(1);
-            if (buf.contains("relation")) cbType.setSelectedIndex(2);
-            String[] res = buf.split("/");
-            String txt;
-            if (res.length>0) {
-                txt = res[res.length-1];
-                if (txt.isEmpty() && txt.length()>1) txt=res[res.length-2];
-            } else {
-                txt=buf;
-            }
-            tfId.setText(txt);
-            tfId.clearTextIfInvalid();
-        }
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java	(revision 5764)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java	(revision 5765)
@@ -13,11 +13,10 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JTextField;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
-import javax.swing.text.JTextComponent;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.SideButton;
-import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
+import org.openstreetmap.josm.gui.widgets.ChangesetIdTextField;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -30,7 +29,6 @@
 public class SingleChangesetDownloadPanel extends JPanel {
 
-    private JTextField tfChangesetId;
+    private ChangesetIdTextField tfChangesetId;
     private DownloadAction actDownload;
-    private ChangesetIdValidator valChangesetId;
 
     protected void build() {
@@ -44,7 +42,6 @@
 
         add(new JLabel(tr("Changeset ID: ")));
-        add(tfChangesetId = new JTextField(10));
+        add(tfChangesetId = new ChangesetIdTextField());
         tfChangesetId.setToolTipText(tr("Enter a changeset id"));
-        valChangesetId  =ChangesetIdValidator.decorate(tfChangesetId);
         SelectAllOnFocusGainedDecorator.decorate(tfChangesetId);
 
@@ -54,6 +51,13 @@
         tfChangesetId.getDocument().addDocumentListener(actDownload);
         add(btn);
+        
+        if (Main.pref.getBoolean("downloadchangeset.autopaste", true)) { 
+            tfChangesetId.tryToPasteFromClipboard();
+        }
     }
 
+    /**
+     * Constructs a new {@link SingleChangesetDownloadPanel}
+     */
     public SingleChangesetDownloadPanel() {
         build();
@@ -67,5 +71,5 @@
      */
     public int getChangesetId() {
-        return valChangesetId.getChangesetId();
+        return tfChangesetId.getChangesetId();
     }
 
@@ -94,10 +98,5 @@
 
         protected void updateEnabledState() {
-            String v = tfChangesetId.getText();
-            if (v == null || v.trim().length() == 0) {
-                setEnabled(false);
-                return;
-            }
-            setEnabled(valChangesetId.isValid());
+            setEnabled(tfChangesetId.readIds());
         }
 
@@ -114,46 +113,3 @@
         }
     }
-
-    /**
-     * Validator for a changeset ID entered in a {@link JTextComponent}.
-     *
-     */
-    static private class ChangesetIdValidator extends AbstractTextComponentValidator {
-        static public ChangesetIdValidator decorate(JTextComponent tc) {
-            return new ChangesetIdValidator(tc);
-        }
-
-        public ChangesetIdValidator(JTextComponent tc) {
-            super(tc);
-        }
-
-        @Override
-        public boolean isValid() {
-            String value  = getComponent().getText();
-            if (value == null || value.trim().length() == 0)
-                return true;
-            return getChangesetId() > 0;
-        }
-
-        @Override
-        public void validate() {
-            if (!isValid()) {
-                feedbackInvalid(tr("The current value is not a valid changeset ID. Please enter an integer value > 0"));
-            } else {
-                feedbackValid(tr("Please enter an integer value > 0"));
-            }
-        }
-
-        public int getChangesetId() {
-            String value  = getComponent().getText();
-            if (value == null || value.trim().length() == 0) return 0;
-            try {
-                int changesetId = Integer.parseInt(value.trim());
-                if (changesetId > 0) return changesetId;
-                return 0;
-            } catch(NumberFormatException e) {
-                return 0;
-            }
-        }
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java	(revision 5765)
+++ trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java	(revision 5765)
@@ -0,0 +1,268 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.download;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trc;
+
+import java.awt.Component;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.GroupLayout;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.border.EtchedBorder;
+import javax.swing.plaf.basic.BasicComboBoxEditor;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
+import org.openstreetmap.josm.gui.widgets.HtmlPanel;
+import org.openstreetmap.josm.gui.widgets.OsmIdTextField;
+import org.openstreetmap.josm.gui.widgets.OsmPrimitiveTypesComboBox;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Dialog prompt to user to let him choose OSM primitives to download by specifying their type and IDs
+ * @since 5765
+ */
+public class DownloadObjectDialog extends ExtendedDialog implements WindowListener {
+
+    protected final JPanel panel = new JPanel();
+    protected final OsmPrimitiveTypesComboBox cbType = new OsmPrimitiveTypesComboBox();
+    protected final OsmIdTextField tfId = new OsmIdTextField();
+    protected final HistoryComboBox cbId = new HistoryComboBox();
+    
+    protected final JCheckBox referrers = new JCheckBox(tr("Download referrers (parent relations)"));
+    protected final JCheckBox fullRel   = new JCheckBox(tr("Download relation members"));
+    protected final JCheckBox newLayer  = new JCheckBox(tr("Separate Layer"));
+    
+    /**
+     * Constructs a new DownloadObjectDialog with Main.parent as parent component.
+     */
+    public DownloadObjectDialog() {
+        this(Main.parent);
+    }
+
+    /**
+     * Constructs a new DownloadObjectDialog.
+     * @param parent The parent component
+     */
+    public DownloadObjectDialog(Component parent) {
+        super(parent, tr("Download object"), new String[] {tr("Download object"), tr("Cancel")});
+        init();
+    }
+    
+    protected void init() {
+        GroupLayout layout = new GroupLayout(panel);
+        panel.setLayout(layout);
+        layout.setAutoCreateGaps(true);
+        layout.setAutoCreateContainerGaps(true);
+
+        JLabel lbl1 = new JLabel(tr("Object type:"));
+        
+        cbType.addItem(trc("osm object types", "mixed"));
+        cbType.setToolTipText(tr("Choose the OSM object type"));
+        JLabel lbl2 = new JLabel(tr("Object ID:"));
+        
+        cbId.setEditor(new BasicComboBoxEditor() {
+            @Override
+            protected JTextField createEditorComponent() {
+                return tfId;
+            }
+        });
+        cbId.setToolTipText(tr("Enter the ID of the object that should be downloaded"));
+        restorePrimitivesHistory(cbId);
+        
+        // forward the enter key stroke to the download button
+        tfId.getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false));
+        
+        newLayer.setToolTipText(tr("Select if the data should be downloaded into a new layer"));
+        newLayer.setSelected(Main.pref.getBoolean("download.newlayer"));
+        
+        referrers.setToolTipText(tr("Select if the referrers of the object should be downloaded as well, i.e.,"
+                + "parent relations and for nodes, additionally, parent ways"));
+        referrers.setSelected(Main.pref.getBoolean("downloadprimitive.referrers", true));
+        
+        fullRel.setToolTipText(tr("Select if the members of a relation should be downloaded as well"));
+        fullRel.setSelected(Main.pref.getBoolean("downloadprimitive.full", true));
+        
+        HtmlPanel help = new HtmlPanel(tr("Object IDs can be separated by comma or space.<br/>"
+                + " Examples: <b><ul><li>1 2 5</li><li>1,2,5</li></ul><br/></b>"
+                + " In mixed mode, specify objects like this: <b>w123, n110, w12, r15</b><br/>"));
+        help.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+
+        layout.setVerticalGroup(layout.createSequentialGroup()
+            .addGroup(layout.createParallelGroup()
+                .addComponent(lbl1)
+                .addComponent(cbType, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
+            .addGroup(layout.createParallelGroup()
+                .addComponent(lbl2)
+                .addComponent(cbId, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
+            .addComponent(referrers)
+            .addComponent(fullRel)
+            .addComponent(newLayer)
+            .addComponent(help)
+        );
+
+        cbType.addItemListener(new ItemListener() {
+            @Override
+            public void itemStateChanged(ItemEvent e) {
+                tfId.setType(cbType.getType());
+                tfId.performValidation();
+                referrers.setText(cbType.getType() == OsmPrimitiveType.NODE
+                        ? tr("Download referrers (parent relations and ways)")
+                        : tr("Download referrers (parent relations)"));
+            }
+        });
+
+        layout.setHorizontalGroup(layout.createParallelGroup()
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup()
+                    .addComponent(lbl1)
+                    .addComponent(lbl2)
+                )
+                .addGroup(layout.createParallelGroup()
+                    .addComponent(cbType)
+                    .addComponent(cbId))
+                )
+            .addComponent(referrers)
+            .addComponent(fullRel)
+            .addComponent(newLayer)
+            .addComponent(help)
+        );
+    }
+
+    @Override
+    public void setupDialog() {
+        
+        setContent(panel, false);
+        setButtonIcons(new String[] {"download.png", "cancel.png"});
+        setToolTipTexts(new String[] {
+                tr("Start downloading"),
+                tr("Close dialog and cancel downloading")
+        });
+        setDefaultButton(1);
+        configureContextsensitiveHelp("/Action/DownloadObject", true /* show help button */);
+        cbType.setSelectedIndex(Main.pref.getInteger("downloadprimitive.lasttype", 0));
+        tfId.setType(cbType.getType());
+        if (Main.pref.getBoolean("downloadprimitive.autopaste", true)) { 
+            tryToPasteFromClipboard(tfId, cbType);
+        }
+        
+        addWindowListener(this);
+        super.setupDialog();
+    }
+    
+    /**
+     * Restore the current history from the preferences
+     *
+     * @param cbHistory
+     */
+    protected void restorePrimitivesHistory(HistoryComboBox cbHistory) {
+        List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(getClass().getName() + ".primitivesHistory", new LinkedList<String>()));
+        // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
+        Collections.reverse(cmtHistory);
+        cbHistory.setPossibleItems(cmtHistory);
+    }
+    
+    /**
+     * Remind the current history in the preferences
+     * @param cbHistory
+     */
+    protected void remindPrimitivesHistory(HistoryComboBox cbHistory) {
+        cbHistory.addCurrentItemToHistory();
+        Main.pref.putCollection(getClass().getName() + ".primitivesHistory", cbHistory.getHistory());
+    }
+
+    protected void tryToPasteFromClipboard(OsmIdTextField tfId, OsmPrimitiveTypesComboBox cbType) {
+        String buf = Utils.getClipboardContent();
+        if (buf != null) {
+            if (buf.contains("node")) cbType.setSelectedIndex(0);
+            if (buf.contains("way")) cbType.setSelectedIndex(1);
+            if (buf.contains("relation")) cbType.setSelectedIndex(2);
+            String[] res = buf.split("/");
+            String txt;
+            if (res.length>0) {
+                txt = res[res.length-1];
+                if (txt.isEmpty() && txt.length()>1) txt=res[res.length-2];
+            } else {
+                txt=buf;
+            }
+            tfId.tryToPasteFrom(txt);
+        }
+    }
+    
+    /**
+     * Determines if a new layer has been requested.
+     * @return true if a new layer has been requested, false otherwise
+     */
+    public final boolean isNewLayerRequested() {
+        return newLayer.isSelected();
+    }
+    
+    /**
+     * Determines if relation members have been requested.
+     * @return true if relation members have been requested, false otherwise
+     */
+    public final boolean isFullRelationRequested() {
+        return fullRel.isSelected();
+    }
+    
+    /**
+     * Determines if referrers have been requested.
+     * @return true if referrers have been requested, false otherwise
+     */
+    public final boolean isReferrersRequested() {
+        return referrers.isSelected();
+    }
+    
+    /**
+     * Gets the requested OSM object IDs.
+     * @return The list of requested OSM object IDs
+     */
+    public final List<PrimitiveId> getOsmIds() {
+        return tfId.getIds();
+    }
+
+    @Override public void windowClosed(WindowEvent e) {
+        if (e != null && e.getComponent() == this && getValue() == 1) {
+            Main.pref.putInteger("downloadprimitive.lasttype", cbType.getSelectedIndex());
+            Main.pref.put("downloadprimitive.referrers", referrers.isSelected());
+            Main.pref.put("downloadprimitive.full", fullRel.isSelected());
+            Main.pref.put("download.newlayer", newLayer.isSelected());
+            
+            if (!tfId.readIds()) {
+                JOptionPane.showMessageDialog(getParent(),
+                        tr("Invalid ID list specified\n"
+                        + "Cannot download object."),
+                        tr("Information"),
+                        JOptionPane.INFORMATION_MESSAGE
+                );
+                return;
+            }
+            
+            remindPrimitivesHistory(cbId);
+        }
+    }
+
+    @Override public void windowOpened(WindowEvent e) {}
+    @Override public void windowClosing(WindowEvent e) {}
+    @Override public void windowIconified(WindowEvent e) {}
+    @Override public void windowDeiconified(WindowEvent e) {}
+    @Override public void windowActivated(WindowEvent e) {}
+    @Override public void windowDeactivated(WindowEvent e) {}
+}
Index: trunk/src/org/openstreetmap/josm/gui/widgets/AbstractIdTextField.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/AbstractIdTextField.java	(revision 5765)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/AbstractIdTextField.java	(revision 5765)
@@ -0,0 +1,89 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.widgets;
+
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * An abstract class for ID text fields.
+ *
+ * @param <T> The ID validator class
+ * @since 5765
+ */
+public abstract class AbstractIdTextField<T extends AbstractTextComponentValidator> extends JTextField {
+
+    protected final T validator;
+
+    /**
+     * Constructs a new {@link AbstractIdTextField}
+     * @param klass The validator class
+     */
+    public AbstractIdTextField(Class<T> klass) {
+        this(klass, 0);
+    }
+
+    /**
+     * Constructs a new {@link AbstractIdTextField}
+     * @param klass The validator class
+     * @param columns The number of columns to use to calculate the preferred width
+     * @see JTextField#JTextField(int)
+     */
+    public AbstractIdTextField(Class<T> klass, int columns) {
+        super(columns);
+        T validator = null;
+        try {
+            if (klass != null) {
+                validator = klass.getConstructor(JTextComponent.class).newInstance(this);
+            }
+        } catch (Exception e) {
+            System.err.println(e.getClass().getName()+": "+e.getMessage());
+        } finally {
+            this.validator = validator;
+        }
+    }
+
+    /**
+     * Performs the field validation
+     */
+    public final void performValidation() {
+        validator.validate();
+    }
+
+    /**
+     * Clears field if content is invalid
+     */
+    public final void clearTextIfInvalid() {
+        if (!validator.isValid()) 
+            setText("");
+        validator.validate();
+    }
+    
+    /**
+     * Reads the id(s).
+     * @return true if at least a valid id has been successfully read, false otherwise
+     */
+    public abstract boolean readIds();
+
+    /**
+     * Tries to set text from clipboard (no effect with invalid or empty clipboard)
+     */
+    public void tryToPasteFromClipboard() {
+        tryToPasteFrom(Utils.getClipboardContent());
+    }
+
+    /**
+     * Tries to set text from given contents (no effect with invalid or empty contents)
+     * @param contents The text to interprete as ID(s)
+     * @return true if text has been pasted and valid ids have been read
+     */
+    public boolean tryToPasteFrom(String contents) {
+        if (contents != null && !contents.trim().isEmpty()) {
+            setText(contents.trim());
+            clearTextIfInvalid();
+            return readIds();
+        }
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/widgets/ChangesetIdTextField.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/ChangesetIdTextField.java	(revision 5765)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/ChangesetIdTextField.java	(revision 5765)
@@ -0,0 +1,91 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.widgets;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.text.JTextComponent;
+
+import com.sun.org.apache.bcel.internal.generic.NEW;
+
+/**
+ * A text field designed to enter a single OSM changeset ID.
+ * @since 5765
+ */
+public class ChangesetIdTextField extends AbstractIdTextField<ChangesetIdTextField.ChangesetIdValidator> {
+
+    /**
+     * Constructs a {@link NEW} {@link ChangesetIdTextField}
+     */
+    public ChangesetIdTextField() {
+        super(ChangesetIdValidator.class, 10);
+    }
+
+    /**
+     * Gets the entered changeset id.
+     * @return The entered changeset id
+     */
+    public final int getChangesetId() {
+        return validator.id;
+    }
+    
+    /**
+     * Reads the changeset id.
+     * @return true if a valid changeset id has been successfully read, false otherwise
+     * @see ChangesetIdValidator#readChangesetId
+     */
+    @Override
+    public boolean readIds() {
+        return validator.readChangesetId();
+    }
+    
+    /**
+     * Validator for a changeset ID entered in a {@link JTextComponent}.
+     */
+    public static class ChangesetIdValidator extends AbstractTextComponentValidator {
+        
+        private int id = 0;
+
+        /**
+         * Constructs a new {@link ChangesetIdValidator}
+         * @param tc The text component to validate
+         */
+        public ChangesetIdValidator(JTextComponent tc) {
+            super(tc);
+        }
+
+        @Override
+        public boolean isValid() {
+            return readChangesetId();
+        }
+
+        @Override
+        public void validate() {
+            if (!isValid()) {
+                feedbackInvalid(tr("The current value is not a valid changeset ID. Please enter an integer value > 0"));
+            } else {
+                feedbackValid(tr("Please enter an integer value > 0"));
+            }
+        }
+        
+        /**
+         * Reads the changeset id.
+         * @return true if a valid changeset id has been successfully read, false otherwise
+         */
+        public boolean readChangesetId() {
+            String value = getComponent().getText();
+            if (value != null && !value.trim().isEmpty()) {
+                id = 0;
+                try {
+                    int changesetId = Integer.parseInt(value.trim());
+                    if (changesetId > 0) {
+                        id = changesetId;
+                        return true;
+                    }
+                } catch(NumberFormatException e) {
+                    // Ignored
+                }
+            }
+            return false;
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/widgets/OsmIdTextField.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/OsmIdTextField.java	(revision 5764)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/OsmIdTextField.java	(revision 5765)
@@ -8,5 +8,4 @@
 import java.util.StringTokenizer;
 
-import javax.swing.JTextField;
 import javax.swing.text.JTextComponent;
 
@@ -16,14 +15,23 @@
 
 /**
+ * A text field designed to enter one or several OSM primitive IDs.
  * @author Matthias Julius
  */
-public class OsmIdTextField extends JTextField {
+public class OsmIdTextField extends AbstractIdTextField<OsmIdTextField.OsmIdValidator> {
 
-    private OsmIdValidator validator;
-
+    /**
+     * Constructs a new {@link OsmIdTextField}
+     */
     public OsmIdTextField() {
-        validator = OsmIdValidator.decorate(this);
+        super(OsmIdValidator.class);
     }
 
+    /**
+     * Sets the type of primitive object
+     * @param type The type of primitive object (
+     *      {@link OsmPrimitiveType#NODE NODE}, 
+     *      {@link OsmPrimitiveType#WAY WAY}, 
+     *      {@link OsmPrimitiveType#RELATION RELATION})
+     */
     public void setType(OsmPrimitiveType type) {
         validator.type = type;
@@ -34,35 +42,30 @@
      * @return list of id's
      */
-    public List<PrimitiveId> getIds() {
+    public final List<PrimitiveId> getIds() {
         return validator.ids;
     }
 
-    public boolean readOsmIds() {
+    /**
+     * Reads the OSM primitive id(s)
+     * @return true if valid OSM objects IDs have been read, false otherwise
+     * @see OsmIdValidator#readOsmIds
+     */
+    @Override
+    public boolean readIds() {
         return validator.readOsmIds();
     }
 
-    public void performValidation() {
-        validator.validate();
-    }
+    /**
+     * Validator for an OSM primitive ID entered in a {@link JTextComponent}.
+     */
+    public static class OsmIdValidator extends AbstractTextComponentValidator {
 
-    public void clearTextIfInvalid() {
-        if (!validator.isValid()) 
-            setText("");
-        validator.validate();
-    }
-
-    /**
-     * Validator for a changeset ID entered in a {@link JTextComponent}.
-     *
-     */
-    static private class OsmIdValidator extends AbstractTextComponentValidator {
-
-        static public OsmIdValidator decorate(JTextComponent tc) {
-            return new OsmIdValidator(tc);
-        }
-
-        private List<PrimitiveId> ids = new ArrayList<PrimitiveId>();
+        private final List<PrimitiveId> ids = new ArrayList<PrimitiveId>();
         private OsmPrimitiveType type;
 
+        /**
+         * Constructs a new {@link OsmIdValidator}
+         * @param tc The text component to validate
+         */
         public OsmIdValidator(JTextComponent tc) {
             super(tc, false);
@@ -83,8 +86,12 @@
         }
 
+        /**
+         * Reads the OSM primitive id(s)
+         * @return true if valid OSM objects IDs have been read, false otherwise
+         */
         public boolean readOsmIds() {
             String value = getComponent().getText();
             char c;
-            if (value == null || value.trim().length() == 0) {
+            if (value == null || value.trim().isEmpty()) {
                 return false;
             }
@@ -108,7 +115,7 @@
                             } else if (type == OsmPrimitiveType.NODE) {
                                 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));
-                            } else if (type == OsmPrimitiveType.WAY) {
+                            } else if (type == OsmPrimitiveType.WAY || type == OsmPrimitiveType.CLOSEDWAY) {
                                 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.WAY));
-                            } else if (type == OsmPrimitiveType.RELATION) {
+                            } else if (type == OsmPrimitiveType.RELATION || type == OsmPrimitiveType.MULTIPOLYGON) {
                                 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.RELATION));
                             } else {
