Index: /trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/Main.java	(revision 10604)
+++ /trunk/src/org/openstreetmap/josm/Main.java	(revision 10605)
@@ -85,4 +85,5 @@
 import org.openstreetmap.josm.gui.MapFrameListener;
 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler;
+import org.openstreetmap.josm.gui.datatransfer.data.OsmLayerTransferData;
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.io.SaveLayersDialog;
Index: /trunk/src/org/openstreetmap/josm/actions/CopyAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CopyAction.java	(revision 10604)
+++ /trunk/src/org/openstreetmap/josm/actions/CopyAction.java	(revision 10605)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable;
 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -48,5 +49,5 @@
         }
 
-        copy(selection);
+        copy(getLayerManager().getEditLayer(), selection);
     }
 
@@ -54,9 +55,10 @@
      * Copies the given primitive ids to the clipboard. The output by this function
      * looks similar to: node 1089302677,node 1089303458,way 93793372
+     * @param source The OSM data layer source
      * @param primitives The OSM primitives to copy
      */
-    public static void copy(Collection<OsmPrimitive> primitives) {
+    public static void copy(OsmDataLayer source, Collection<OsmPrimitive> primitives) {
         // copy ids to the clipboard
-        ClipboardUtils.copy(new PrimitiveTransferable(PrimitiveTransferData.getDataWithReferences(primitives)));
+        ClipboardUtils.copy(new PrimitiveTransferable(PrimitiveTransferData.getDataWithReferences(primitives), source));
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/datatransfer/LayerTransferable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/datatransfer/LayerTransferable.java	(revision 10605)
+++ /trunk/src/org/openstreetmap/josm/gui/datatransfer/LayerTransferable.java	(revision 10605)
@@ -0,0 +1,97 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+
+/**
+ * This class allows to transfer multiple layers in the current JOSM instance.
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class LayerTransferable implements Transferable {
+
+    /**
+     * A wrapper for a collection of {@link Layer}.
+     */
+    public static class Data {
+        private final LayerManager manager;
+        private final List<Layer> layers;
+
+        /**
+         * Create a new data object
+         * @param manager The layer manager the layers are from.
+         * @param layers The layers.
+         */
+        public Data(LayerManager manager, List<Layer> layers) {
+            super();
+            this.manager = manager;
+            this.layers = new ArrayList<>(layers);
+        }
+
+        /**
+         * Gets the layer manager the layers belong to.
+         * @return The layer manager. It may be <code>null</code>
+         */
+        public LayerManager getManager() {
+            return manager;
+        }
+
+        /**
+         * Gets the list of layers that were copied.
+         * @return The layers.
+         */
+        public List<Layer> getLayers() {
+            return Collections.unmodifiableList(layers);
+        }
+
+        @Override
+        public String toString() {
+            return "Data [layers=" + layers + ']';
+        }
+    }
+
+    /**
+     * Data flavor for {@link Layer}s which are wrapped in {@link Data}.
+     */
+    public static final DataFlavor LAYER_DATA = new DataFlavor(
+            DataFlavor.javaJVMLocalObjectMimeType + ";class=" + Data.class.getName(), "Layers");
+
+    private final Data data;
+
+    /**
+     * Create a new data object
+     * @param manager The layer manager the layers are from.
+     * @param layers The layers.
+     */
+    public LayerTransferable(LayerManager manager, List<Layer> layers) {
+        this.data = new Data(manager, layers);
+    }
+
+    @Override
+    public DataFlavor[] getTransferDataFlavors() {
+        return new DataFlavor[] {LAYER_DATA};
+    }
+
+    @Override
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        return LAYER_DATA.equals(flavor);
+    }
+
+    @Override
+    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+        if (!isDataFlavorSupported(flavor)) {
+            throw new UnsupportedFlavorException(flavor);
+        } else {
+            return data;
+        }
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferable.java	(revision 10604)
+++ /trunk/src/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferable.java	(revision 10605)
@@ -11,6 +11,8 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.gui.datatransfer.data.OsmLayerTransferData;
 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
 import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
@@ -27,4 +29,5 @@
             TagTransferData.FLAVOR, DataFlavor.stringFlavor);
     private final PrimitiveTransferData primitives;
+    private OsmDataLayer sourceLayer;
 
     /**
@@ -33,5 +36,15 @@
      */
     public PrimitiveTransferable(PrimitiveTransferData primitives) {
+        this(primitives, null);
+    }
+
+    /**
+     * Constructs a new {@code PrimitiveTransferable}.
+     * @param primitives collection of OSM primitives
+     * @param sourceLayer The layer the primitives are copied from
+     */
+    public PrimitiveTransferable(PrimitiveTransferData primitives, OsmDataLayer sourceLayer) {
         this.primitives = primitives;
+        this.sourceLayer = sourceLayer;
     }
 
@@ -39,4 +52,7 @@
     public DataFlavor[] getTransferDataFlavors() {
         ArrayList<DataFlavor> flavors = new ArrayList<>(PRIMITIVE_FLAVORS);
+        if (sourceLayer != null) {
+            flavors.addAll(OsmLayerTransferData.FLAVORS);
+        }
         return flavors.toArray(new DataFlavor[flavors.size()]);
     }
@@ -61,4 +77,6 @@
         } else if (TagTransferData.FLAVOR.equals(flavor)) {
             return new TagTransferData(primitives.getDirectlyAdded());
+        } else if (sourceLayer != null && OsmLayerTransferData.FLAVORS.contains(flavor)) {
+            return new OsmLayerTransferData(null, sourceLayer);
         } else {
             throw new UnsupportedFlavorException(flavor);
Index: /trunk/src/org/openstreetmap/josm/gui/datatransfer/SingleLayerTransferable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/datatransfer/SingleLayerTransferable.java	(revision 10605)
+++ /trunk/src/org/openstreetmap/josm/gui/datatransfer/SingleLayerTransferable.java	(revision 10605)
@@ -0,0 +1,56 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.datatransfer.data.LayerTransferData;
+import org.openstreetmap.josm.gui.datatransfer.data.OsmLayerTransferData;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+/**
+ * This class handles the transfer of a layer inside this JOSM instance.
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class SingleLayerTransferable implements Transferable {
+    private final LayerTransferData data;
+
+    /**
+     * Create a new {@link SingleLayerTransferable}
+     * @param manager The manager the layer belongs to
+     * @param layer The layer that is transfered.
+     */
+    public SingleLayerTransferable(LayerManager manager, Layer layer) {
+        if (layer instanceof OsmDataLayer) {
+            this.data = new OsmLayerTransferData(manager, (OsmDataLayer) layer);
+        } else {
+            this.data = new LayerTransferData(manager, layer);
+        }
+    }
+
+    @Override
+    public DataFlavor[] getTransferDataFlavors() {
+        List<DataFlavor> flavors = data.getSupportedFlavors();
+        return flavors.toArray(new DataFlavor[flavors.size()]);
+    }
+
+    @Override
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        return data.getSupportedFlavors().contains(flavor);
+    }
+
+    @Override
+    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+        if (isDataFlavorSupported(flavor)) {
+            return data;
+        } else {
+            throw new UnsupportedFlavorException(flavor);
+        }
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/LayerTransferData.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/LayerTransferData.java	(revision 10605)
+++ /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/LayerTransferData.java	(revision 10605)
@@ -0,0 +1,62 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer.data;
+
+import java.awt.datatransfer.DataFlavor;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.datatransfer.LayerTransferable;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+
+/**
+ * This transferable implements a layer transfer.
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class LayerTransferData extends LayerTransferable.Data {
+    /**
+     * This is a data flavor for all layer types
+     */
+    public static final DataFlavor FLAVOR = new DataFlavor(
+            DataFlavor.javaJVMLocalObjectMimeType + ";class=" + LayerTransferData.class.getName(), "Layer");
+
+    /**
+     * The flavors that are supported by this data type.
+     */
+    private static final List<DataFlavor> FLAVORS = Arrays.asList(LayerTransferData.FLAVOR, LayerTransferable.LAYER_DATA);
+
+    private final Layer layer;
+
+    /**
+     * Create a new transfer data for the given layer
+     * @param layerManager The layer manager that the layer is moved in. May be <code>null</code>
+     * @param layer The layer
+     */
+    public LayerTransferData(LayerManager layerManager, Layer layer) {
+        super(layerManager, Collections.singletonList(layer));
+        this.layer = layer;
+    }
+
+    /**
+     * Gets the layer to be transfered.
+     * @return The layer
+     */
+    public Layer getLayer() {
+        return layer;
+    }
+
+    /**
+     * Gets a list of flavors supported by this data.
+     * @return The flavors.
+     */
+    public List<DataFlavor> getSupportedFlavors() {
+        return Collections.unmodifiableList(FLAVORS);
+    }
+
+    @Override
+    public String toString() {
+        return "LayerTransferData [layer=" + layer + ']';
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/OsmLayerTransferData.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/OsmLayerTransferData.java	(revision 10605)
+++ /trunk/src/org/openstreetmap/josm/gui/datatransfer/data/OsmLayerTransferData.java	(revision 10605)
@@ -0,0 +1,64 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer.data;
+
+import java.awt.datatransfer.DataFlavor;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.datatransfer.LayerTransferable;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+/**
+ * A special form of {@link LayerTransferData} that ensures you that the layer is an OSM data layer
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class OsmLayerTransferData extends LayerTransferData {
+
+    /**
+     * This is a data flavor specific for OSM data layers.
+     * <p>
+     * @see LayerTransferData#FLAVOR
+     * @see #FLAVORS
+     */
+    public static final DataFlavor OSM_FLAVOR = new DataFlavor(
+            DataFlavor.javaJVMLocalObjectMimeType + ";class=" + LayerTransferData.class.getName(), "Layer");
+
+    /**
+     * The flavors that are supported by this data type.
+     */
+    public static final List<DataFlavor> FLAVORS = Collections
+            .unmodifiableList(Arrays.asList(OSM_FLAVOR, LayerTransferData.FLAVOR, LayerTransferable.LAYER_DATA));
+
+    private final OsmDataLayer osmLayer;
+
+    /**
+     * Create a new {@link OsmLayerTransferData} object
+     * @param layerManager The layer manager
+     * @param layer The layer that is moved.
+     */
+    public OsmLayerTransferData(LayerManager layerManager, OsmDataLayer layer) {
+        super(layerManager, layer);
+        osmLayer = layer;
+    }
+
+    /**
+     * Gets the OSM data layer.
+     * @return The layer
+     */
+    public OsmDataLayer getOsmLayer() {
+        return osmLayer;
+    }
+
+    @Override
+    public List<DataFlavor> getSupportedFlavors() {
+        return FLAVORS;
+    }
+
+    @Override
+    public String toString() {
+        return "OsmLayerTransferData [osmLayer=" + osmLayer + ']';
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 10604)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 10605)
@@ -25,4 +25,5 @@
 import javax.swing.DefaultCellEditor;
 import javax.swing.DefaultListSelectionModel;
+import javax.swing.DropMode;
 import javax.swing.ImageIcon;
 import javax.swing.JCheckBox;
@@ -52,4 +53,5 @@
 import org.openstreetmap.josm.gui.dialogs.layer.DeleteLayerAction;
 import org.openstreetmap.josm.gui.dialogs.layer.DuplicateAction;
+import org.openstreetmap.josm.gui.dialogs.layer.LayerListTransferHandler;
 import org.openstreetmap.josm.gui.dialogs.layer.LayerVisibilityAction;
 import org.openstreetmap.josm.gui.dialogs.layer.MergeAction;
@@ -1104,5 +1106,5 @@
         @Override
         public void layerOrderChanged(LayerOrderChangeEvent e) {
-            // ignored for now, since only we change layer order.
+            fireTableDataChanged();
         }
 
@@ -1130,4 +1132,7 @@
             super(dataModel);
             dataModel.setLayerList(this);
+            setDragEnabled(true);
+            setDropMode(DropMode.INSERT_ROWS);
+            setTransferHandler(new LayerListTransferHandler());
         }
 
@@ -1141,4 +1146,9 @@
             viewport.scrollRectToVisible(rect);
         }
+
+        @Override
+        public LayerListModel getModel() {
+            return (LayerListModel) super.getModel();
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/DuplicateAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/DuplicateAction.java	(revision 10604)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/DuplicateAction.java	(revision 10605)
@@ -5,6 +5,4 @@
 
 import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.util.List;
 
 import javax.swing.AbstractAction;
@@ -21,5 +19,5 @@
 
 /**
- * The action to merge the currently selected layer into another layer.
+ * The action to dupplicate the given selected layer into another layer.
  */
 public final class DuplicateAction extends AbstractAction implements IEnabledStateUpdating {
@@ -53,22 +51,8 @@
     }
 
-    private void duplicate(Layer layer) {
-        if (!Main.isDisplayingMapView())
-            return;
-
-        List<String> layerNames = new ArrayList<>();
-        for (Layer l: Main.getLayerManager().getLayers()) {
-            layerNames.add(l.getName());
-        }
+    private static void duplicate(Layer layer) {
         if (layer instanceof OsmDataLayer) {
+            String newName = LayerListTransferHandler.suggestNewLayerName(layer.getName(), Main.getLayerManager().getLayers());
             OsmDataLayer oldLayer = (OsmDataLayer) layer;
-            // Translators: "Copy of {layer name}"
-            String newName = tr("Copy of {0}", oldLayer.getName());
-            int i = 2;
-            while (layerNames.contains(newName)) {
-                // Translators: "Copy {number} of {layer name}"
-                newName = tr("Copy {1} of {0}", oldLayer.getName(), i);
-                i++;
-            }
             Main.getLayerManager().addLayer(new OsmDataLayer(new DataSet(oldLayer.data), newName, null));
         }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerListTransferHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerListTransferHandler.java	(revision 10605)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerListTransferHandler.java	(revision 10605)
@@ -0,0 +1,175 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.TransferHandler;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.datatransfer.LayerTransferable;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+/**
+ * This class allows the user to transfer layers using drag+drop.
+ * <p>
+ * It supports copy (duplication) of layers, simple moves and linking layers to a new layer manager.
+ *
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class LayerListTransferHandler extends TransferHandler {
+    @Override
+    public int getSourceActions(JComponent c) {
+        // we know that the source is a layer list, so don't check c.
+        LayerListModel tableModel = (LayerListModel) ((JTable) c).getModel();
+        if (tableModel.getSelectedLayers().isEmpty()) {
+            return 0;
+        }
+        int actions = MOVE;
+        if (onlyDataLayersSelected(tableModel)) {
+            actions |= COPY;
+        }
+        return actions /* soon: | LINK*/;
+    }
+
+    private static boolean onlyDataLayersSelected(LayerListModel tableModel) {
+        for (Layer l : tableModel.getSelectedLayers()) {
+            if (!(l instanceof OsmDataLayer)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    protected Transferable createTransferable(JComponent c) {
+        LayerListModel tableModel = (LayerListModel) ((JTable) c).getModel();
+        return new LayerTransferable(tableModel.getLayerManager(), tableModel.getSelectedLayers());
+    }
+
+    @Override
+    public boolean canImport(TransferSupport support) {
+        if (support.isDrop()) {
+            support.setShowDropLocation(true);
+        }
+
+        if (!support.isDataFlavorSupported(LayerTransferable.LAYER_DATA)) {
+            return false;
+        }
+
+        if (support.getDropAction() == LINK) {
+            // cannot link yet.
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean importData(TransferSupport support) {
+        try {
+            LayerListModel tableModel = (LayerListModel) ((JTable) support.getComponent()).getModel();
+
+            LayerTransferable.Data layers = ((LayerTransferable.Data) support.getTransferable()
+                    .getTransferData(LayerTransferable.LAYER_DATA));
+
+            int dropLocation;
+            if (support.isDrop()) {
+                JTable.DropLocation dl = (JTable.DropLocation) support.getDropLocation();
+                dropLocation = dl.getRow();
+            } else {
+                dropLocation = layers.getLayers().get(0).getDefaultLayerPosition().getPosition(layers.getManager());
+            }
+
+            boolean isSameLayerManager = tableModel.getLayerManager() == layers.getManager();
+
+            if (support.getDropAction() == MOVE && isSameLayerManager) {
+                for (Layer layer : layers.getLayers()) {
+                    boolean wasBeforeInsert = layers.getManager().getLayers().indexOf(layer) <= dropLocation;
+                    if (wasBeforeInsert) {
+                        // need to move insertion point one down to preserve order
+                        dropLocation--;
+                    }
+                    layers.getManager().moveLayer(layer, dropLocation);
+                    dropLocation++;
+                }
+            } else {
+                List<Layer> layersToUse = layers.getLayers();
+                if (support.getDropAction() == COPY) {
+                    layersToUse = createCopy(layersToUse, layers.getManager().getLayers());
+                }
+                for (Layer layer : layersToUse) {
+                    layers.getManager().addLayer(layer);
+                    layers.getManager().moveLayer(layer, dropLocation);
+                    dropLocation++;
+                }
+            }
+
+            return true;
+        } catch (UnsupportedFlavorException e) {
+            Main.warn("Flavor not supported", e);
+            return false;
+        } catch (IOException e) {
+            Main.warn("Error while pasting layer", e);
+            return false;
+        }
+    }
+
+    private static List<Layer> createCopy(List<Layer> layersToUse, List<Layer> namesToAvoid) {
+        Collection<String> layerNames = getNames(namesToAvoid);
+        ArrayList<Layer> layers = new ArrayList<>();
+        for (Layer layer : layersToUse) {
+            if (layer instanceof OsmDataLayer) {
+                String newName = suggestNewLayerName(layer.getName(), layerNames);
+                OsmDataLayer newLayer = new OsmDataLayer(new DataSet(((OsmDataLayer) layer).data), newName, null);
+                layers.add(newLayer);
+                layerNames.add(newName);
+            }
+        }
+        return layers;
+    }
+
+    /**
+     * Suggests a new name in the form "copy of name"
+     * @param name The base name
+     * @param namesToAvoid The list of layers to use to avoid dupplicate names.
+     * @return The new name
+     */
+    public static String suggestNewLayerName(String name, List<Layer> namesToAvoid) {
+        Collection<String> layerNames = getNames(namesToAvoid);
+
+        return suggestNewLayerName(name, layerNames);
+    }
+
+    private static List<String> getNames(List<Layer> namesToAvoid) {
+        List<String> layerNames = new ArrayList<>();
+        for (Layer l: namesToAvoid) {
+            layerNames.add(l.getName());
+        }
+        return layerNames;
+    }
+
+    private static String suggestNewLayerName(String name, Collection<String> layerNames) {
+        // Translators: "Copy of {layer name}"
+        String newName = tr("Copy of {0}", name);
+        int i = 2;
+        while (layerNames.contains(newName)) {
+            // Translators: "Copy {number} of {layer name}"
+            newName = tr("Copy {1} of {0}", name, i);
+            i++;
+        }
+        return newName;
+    }
+}
Index: /trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/LayerTransferableTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/LayerTransferableTest.java	(revision 10605)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/LayerTransferableTest.java	(revision 10605)
@@ -0,0 +1,98 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openstreetmap.josm.gui.datatransfer.LayerTransferable.Data;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManagerTest;
+import org.openstreetmap.josm.gui.layer.LayerManagerTest.TestLayer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager;
+
+/**
+ * Tests for {@link LayerTransferable}
+ * @author Michael Zangl
+ * @since 10605
+ */
+public class LayerTransferableTest {
+    private TestLayer layer1;
+    private TestLayer layer2;
+    private MainLayerManager manager;
+
+    /**
+     * Set up test data
+     */
+    @Before
+    public void createTestData() {
+        layer1 = new LayerManagerTest.TestLayer();
+        layer2 = new LayerManagerTest.TestLayer();
+        manager = new MainLayerManager();
+        manager.addLayer(layer1);
+        manager.addLayer(layer2);
+    }
+
+    /**
+     * Test {@link LayerTransferable.Data}
+     */
+    @Test
+    public void testLayerData() {
+        Data data = new Data(manager, Arrays.<Layer>asList(layer1, layer2));
+
+        // need to be identity
+        assertSame(manager, data.getManager());
+        assertSame(layer1, data.getLayers().get(0));
+        assertSame(layer2, data.getLayers().get(1));
+    }
+
+    /**
+     * Test {@link LayerTransferable#isDataFlavorSupported(java.awt.datatransfer.DataFlavor)}
+     * and {@link LayerTransferable#getTransferDataFlavors()}
+     */
+    @Test
+    public void testSupportedDataFlavor() {
+        LayerTransferable transferable = new LayerTransferable(manager, Arrays.<Layer>asList(layer1, layer2));
+
+        assertFalse(transferable.isDataFlavorSupported(DataFlavor.imageFlavor));
+        assertTrue(transferable.isDataFlavorSupported(LayerTransferable.LAYER_DATA));
+
+        DataFlavor[] flavors = transferable.getTransferDataFlavors();
+        assertEquals(1, flavors.length);
+        assertEquals(LayerTransferable.LAYER_DATA, flavors[0]);
+    }
+
+    /**
+     * Test {@link LayerTransferable#getTransferData(DataFlavor)}
+     * @throws Exception if any error occurs
+     */
+    @Test
+    public void testTransferData() throws Exception {
+        LayerTransferable transferable = new LayerTransferable(manager, Arrays.<Layer>asList(layer1, layer2));
+
+        Object object = transferable.getTransferData(LayerTransferable.LAYER_DATA);
+        assertTrue(object instanceof Data);
+        Data data = (Data) object;
+        assertSame(manager, data.getManager());
+        assertSame(layer1, data.getLayers().get(0));
+        assertSame(layer2, data.getLayers().get(1));
+    }
+
+    /**
+     * Test {@link LayerTransferable#getTransferData(DataFlavor)} for unsupported {@link DataFlavor}
+     * @throws Exception if any error occurs
+     */
+    @Test(expected = UnsupportedFlavorException.class)
+    public void testTransferDataUnsupported() throws Exception {
+        LayerTransferable transferable = new LayerTransferable(manager, Arrays.<Layer>asList(layer1, layer2));
+
+        transferable.getTransferData(DataFlavor.imageFlavor);
+    }
+}
