Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 12718)
@@ -137,5 +137,5 @@
      * The commands undo/redo handler.
      */
-    public final UndoRedoHandler undoRedo = MainApplication.undoRedo;
+    public final UndoRedoHandler undoRedo = new UndoRedoHandler();
 
     /**
@@ -630,11 +630,24 @@
 
     /**
-     * Gets the data set of the active edit layer.
-     * @return That data set, <code>null</code> if there is no edit layer.
+     * Gets the active edit data set.
+     * @return That data set, <code>null</code>.
      * @since 12691
      */
-    public DataSet getEditDataSet() {
-        return null;
-    }
+    public abstract DataSet getEditDataSet();
+
+    /**
+     * Sets the active data set.
+     * @param ds New edit data set, or <code>null</code>
+     * @since 12718
+     */
+    public abstract void setEditDataSet(DataSet ds);
+
+    /**
+     * Determines if the list of data sets managed by JOSM contains {@code ds}.
+     * @param ds the data set to look for
+     * @return {@code true} if the list of data sets managed by JOSM contains {@code ds}
+     * @since 12718
+     */
+    public abstract boolean containsDataSet(DataSet ds);
 
     /**
Index: trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 12718)
@@ -693,5 +693,5 @@
         // Delete the discarded inner ways
         if (!discardedWays.isEmpty()) {
-            Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), discardedWays, true);
+            Command deleteCmd = DeleteCommand.delete(discardedWays, true);
             if (deleteCmd != null) {
                 cmds.add(deleteCmd);
@@ -1018,5 +1018,5 @@
 
         if (chunks.size() > 1) {
-            SplitWayResult split = SplitWayAction.splitWay(getLayerManager().getEditLayer(), way, chunks,
+            SplitWayResult split = SplitWayAction.splitWay(way, chunks,
                     Collections.<OsmPrimitive>emptyList(), SplitWayAction.Strategy.keepFirstChunk());
 
@@ -1467,5 +1467,5 @@
             newRel.addMember(new RelationMember("inner", w));
         }
-        cmds.add(layer != null ? new AddCommand(layer, newRel) :
+        cmds.add(layer != null ? new AddCommand(layer.data, newRel) :
             new AddCommand(inner.iterator().next().getDataSet(), newRel));
         addedRelations.add(newRel);
@@ -1538,5 +1538,4 @@
         }
 
-        OsmDataLayer layer = getLayerManager().getEditLayer();
         Relation newRel;
         switch (multiouters.size()) {
@@ -1567,5 +1566,5 @@
             }
             newRel.addMember(new RelationMember("outer", outer));
-            cmds.add(layer != null ? new AddCommand(layer, newRel) : new AddCommand(outer.getDataSet(), newRel));
+            cmds.add(new AddCommand(outer.getDataSet(), newRel));
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/PurgeAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/PurgeAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/PurgeAction.java	(revision 12718)
@@ -118,5 +118,5 @@
         layer = getLayerManager().getEditLayer();
         toPurgeAdditionally = new ArrayList<>();
-        PurgeCommand cmd = PurgeCommand.build(layer, sel, toPurgeAdditionally);
+        PurgeCommand cmd = PurgeCommand.build(sel, toPurgeAdditionally);
         modified = cmd.getParticipatingPrimitives().stream().anyMatch(OsmPrimitive::isModified);
         return cmd;
Index: trunk/src/org/openstreetmap/josm/actions/RedoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/RedoAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/RedoAction.java	(revision 12718)
@@ -9,7 +9,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -19,5 +19,5 @@
  * @author imi
  */
-public class RedoAction extends JosmAction implements OsmDataLayer.CommandQueueListener {
+public class RedoAction extends JosmAction implements CommandQueueListener {
 
     /**
Index: trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java	(revision 12718)
@@ -214,5 +214,5 @@
             }
             if (wayToKeep != null) {
-                final SplitWayResult result = doSplitWay(getLayerManager().getEditLayer(), selectedWay, wayToKeep, newWays, sel);
+                final SplitWayResult result = doSplitWay(selectedWay, wayToKeep, newWays, sel);
                 MainApplication.undoRedo.add(result.getCommand());
                 if (!result.getNewSelection().isEmpty()) {
@@ -294,6 +294,5 @@
             toggleSaveState(); // necessary since #showDialog() does not handle it due to the non-modal dialog
             if (getValue() == 1) {
-                SplitWayResult result = doSplitWay(MainApplication.getLayerManager().getEditLayer(),
-                        selectedWay, list.getSelectedValue(), newWays, selection);
+                SplitWayResult result = doSplitWay(selectedWay, list.getSelectedValue(), newWays, selection);
                 MainApplication.undoRedo.add(result.getCommand());
                 if (!result.getNewSelection().isEmpty()) {
@@ -498,8 +497,29 @@
      * @param selection The list of currently selected primitives
      * @return the result from the split operation
-     */
+     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection)} instead
+     */
+    @Deprecated
     public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks,
             Collection<? extends OsmPrimitive> selection) {
-        return splitWay(layer, way, wayChunks, selection, Strategy.keepLongestChunk());
+        return splitWay(way, wayChunks, selection);
+    }
+
+    /**
+     * Splits the way {@code way} into chunks of {@code wayChunks} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * @param way the way to split. Must not be null.
+     * @param wayChunks the list of way chunks into the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @return the result from the split operation
+     * @since 12718
+     */
+    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
+            Collection<? extends OsmPrimitive> selection) {
+        return splitWay(way, wayChunks, selection, Strategy.keepLongestChunk());
     }
 
@@ -521,6 +541,30 @@
      * @return the result from the split operation
      * @since 8954
-     */
+     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection, Strategy)} instead
+     */
+    @Deprecated
     public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks,
+            Collection<? extends OsmPrimitive> selection, Strategy splitStrategy) {
+        return splitWay(way, wayChunks, selection, splitStrategy);
+    }
+
+    /**
+     * Splits the way {@code way} into chunks of {@code wayChunks} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     * The {@link org.openstreetmap.josm.actions.SplitWayAction.Strategy} is used to determine which
+     * way chunk should reuse the old id and its history.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * @param way the way to split. Must not be null.
+     * @param wayChunks the list of way chunks into the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @param splitStrategy The strategy used to determine which way chunk should reuse the old id and its history
+     * @return the result from the split operation
+     * @since 12718
+     */
+    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
             Collection<? extends OsmPrimitive> selection, Strategy splitStrategy) {
         // build a list of commands, and also a new selection list
@@ -534,9 +578,8 @@
         final Way wayToKeep = splitStrategy.determineWayToKeep(newWays);
 
-        return wayToKeep != null ? doSplitWay(layer, way, wayToKeep, newWays, newSelection) : null;
-    }
-
-    static SplitWayResult doSplitWay(OsmDataLayer layer, Way way, Way wayToKeep, List<Way> newWays,
-                                   List<OsmPrimitive> newSelection) {
+        return wayToKeep != null ? doSplitWay(way, wayToKeep, newWays, newSelection) : null;
+    }
+
+    static SplitWayResult doSplitWay(Way way, Way wayToKeep, List<Way> newWays, List<OsmPrimitive> newSelection) {
 
         Collection<Command> commandList = new ArrayList<>(newWays.size());
@@ -550,5 +593,5 @@
         final Way changedWay = new Way(way);
         changedWay.setNodes(wayToKeep.getNodes());
-        commandList.add(layer != null ? new ChangeCommand(layer, way, changedWay) : new ChangeCommand(way.getDataSet(), way, changedWay));
+        commandList.add(new ChangeCommand(way.getDataSet(), way, changedWay));
         if (!isMapModeDraw && !newSelection.contains(way)) {
             newSelection.add(way);
@@ -561,5 +604,5 @@
         }
         for (Way wayToAdd : newWays) {
-            commandList.add(layer != null ? new AddCommand(layer, wayToAdd) : new AddCommand(way.getDataSet(), wayToAdd));
+            commandList.add(new AddCommand(way.getDataSet(), wayToAdd));
         }
 
@@ -688,5 +731,5 @@
 
             if (c != null) {
-                commandList.add(layer != null ? new ChangeCommand(layer, r, c) : new ChangeCommand(r.getDataSet(), r, c));
+                commandList.add(new ChangeCommand(r.getDataSet(), r, c));
             }
         }
@@ -741,8 +784,30 @@
      * @param selection The list of currently selected primitives
      * @return the result from the split operation
-     */
+     * @deprecated to be removed end of 2017. Use {@link #split(Way, List, Collection) instead}
+     */
+    @Deprecated
     public static SplitWayResult split(OsmDataLayer layer, Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection) {
+        return split(way, atNodes, selection);
+    }
+
+    /**
+     * Splits the way {@code way} at the nodes in {@code atNodes} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * Replies null if the way couldn't be split at the given nodes.
+     *
+     * @param way the way to split. Must not be null.
+     * @param atNodes the list of nodes where the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @return the result from the split operation
+     * @since 12718
+     */
+    public static SplitWayResult split(Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection) {
         List<List<Node>> chunks = buildSplitChunks(way, atNodes);
-        return chunks != null ? splitWay(layer, way, chunks, selection) : null;
+        return chunks != null ? splitWay(way, chunks, selection) : null;
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/UndoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UndoAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/UndoAction.java	(revision 12718)
@@ -9,7 +9,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -19,5 +19,5 @@
  * @author imi
  */
-public class UndoAction extends JosmAction implements OsmDataLayer.CommandQueueListener {
+public class UndoAction extends JosmAction implements CommandQueueListener {
 
     /**
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 12718)
@@ -151,7 +151,7 @@
         Command c;
         if (ctrl) {
-            c = DeleteCommand.deleteWithReferences(editLayer, lm.getEditDataSet().getSelected());
+            c = DeleteCommand.deleteWithReferences(lm.getEditDataSet().getSelected());
         } else {
-            c = DeleteCommand.delete(editLayer, lm.getEditDataSet().getSelected(), !alt /* also delete nodes in way */);
+            c = DeleteCommand.delete(lm.getEditDataSet().getSelected(), !alt /* also delete nodes in way */);
         }
         // if c is null, an error occurred or the user aborted. Don't do anything in that case.
@@ -352,5 +352,5 @@
         CheckParameterUtil.ensureParameterNotNull(toDelete, "toDelete");
 
-        final Command cmd = DeleteCommand.delete(layer, toDelete);
+        final Command cmd = DeleteCommand.delete(toDelete);
         if (cmd != null) {
             // cmd can be null if the user cancels dialogs DialogCommand displays
@@ -404,18 +404,17 @@
     private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean silent) {
         DeleteParameters parameters = getDeleteParameters(e, modifiers);
-        OsmDataLayer editLayer = getLayerManager().getEditLayer();
         switch (parameters.mode) {
         case node:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestNode), false, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestNode), false, silent);
         case node_with_references:
-            return DeleteCommand.deleteWithReferences(editLayer, Collections.singleton(parameters.nearestNode), silent);
+            return DeleteCommand.deleteWithReferences(Collections.singleton(parameters.nearestNode), silent);
         case segment:
-            return DeleteCommand.deleteWaySegment(editLayer, parameters.nearestSegment);
+            return DeleteCommand.deleteWaySegment(parameters.nearestSegment);
         case way:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestSegment.way), false, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestSegment.way), false, silent);
         case way_with_nodes:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestSegment.way), true, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestSegment.way), true, silent);
         case way_with_references:
-            return DeleteCommand.deleteWithReferences(editLayer, Collections.singleton(parameters.nearestSegment.way), true);
+            return DeleteCommand.deleteWithReferences(Collections.singleton(parameters.nearestSegment.way), true);
         default:
             return null;
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 12718)
@@ -488,5 +488,5 @@
                     newWay.setNodes(nodes);
                     if (nodes.size() < 2) {
-                        final Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), Collections.singleton(targetWay), true);
+                        final Command deleteCmd = DeleteCommand.delete(Collections.singleton(targetWay), true);
                         if (deleteCmd != null) {
                             MainApplication.undoRedo.add(deleteCmd);
@@ -500,5 +500,5 @@
                             tr("Error"), JOptionPane.ERROR_MESSAGE);
                 } else {
-                    final Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), Collections.singleton(candidateNode), true);
+                    final Command deleteCmd = DeleteCommand.delete(Collections.singleton(candidateNode), true);
                     if (deleteCmd != null) {
                         MainApplication.undoRedo.add(deleteCmd);
Index: trunk/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java	(revision 12718)
@@ -19,4 +19,5 @@
 
 import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -25,5 +26,4 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
Index: trunk/src/org/openstreetmap/josm/command/AddCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/AddCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/AddCommand.java	(revision 12718)
@@ -45,5 +45,7 @@
      * @param layer The data layer. Must not be {@code null}
      * @param osm The primitive to add
+     * @deprecated to be removed end of 2017. Use {@link #AddCommand(DataSet, OsmPrimitive)} instead
      */
+    @Deprecated
     public AddCommand(OsmDataLayer layer, OsmPrimitive osm) {
         super(layer);
Index: trunk/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(revision 12718)
@@ -59,7 +59,21 @@
      * @param toSelect The OSM primitives to select at the end. Can be {@code null}
      * @param layer The target data layer. Must not be {@code null}
-     */
+     * @deprecated to be removed end of 2017. Use {@link #AddPrimitivesCommand(List, List, DataSet)} instead
+     */
+    @Deprecated
     public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, OsmDataLayer layer) {
         super(layer);
+        init(data, toSelect);
+    }
+
+    /**
+     * Constructs a new {@code AddPrimitivesCommand} to add data to the given data set.
+     * @param data The OSM primitives data to add. Must not be {@code null}
+     * @param toSelect The OSM primitives to select at the end. Can be {@code null}
+     * @param ds The target data set. Must not be {@code null}
+     * @since 12718
+     */
+    public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, DataSet ds) {
+        super(ds);
         init(data, toSelect);
     }
Index: trunk/src/org/openstreetmap/josm/command/ChangeCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ChangeCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/ChangeCommand.java	(revision 12718)
@@ -45,5 +45,7 @@
      * @param osm The existing primitive to modify
      * @param newOsm The new primitive
+     * @deprecated to be removed end of 2017. Use {@link #ChangeCommand(DataSet, OsmPrimitive, OsmPrimitive)} instead
      */
+    @Deprecated
     public ChangeCommand(OsmDataLayer layer, OsmPrimitive osm, OsmPrimitive newOsm) {
         super(layer);
Index: trunk/src/org/openstreetmap/josm/command/Command.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/Command.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/Command.java	(revision 12718)
@@ -35,5 +35,5 @@
  * one atomic action on a specific dataset, such as move or delete.
  *
- * The command remembers the {@link OsmDataLayer} it is operating on.
+ * The command remembers the {@link DataSet} it is operating on.
  *
  * @author imi
@@ -135,5 +135,9 @@
     private Map<OsmPrimitive, PrimitiveData> cloneMap = new HashMap<>();
 
-    /** the layer which this command is applied to */
+    /**
+     * the layer which this command is applied to
+     * @deprecated to be removed end of 2017. Use {@link #data} instead
+     */
+    @Deprecated
     private final OsmDataLayer layer;
 
@@ -146,5 +150,5 @@
     public Command() {
         this.layer = MainApplication.getLayerManager().getEditLayer();
-        this.data = layer != null ? layer.data : null;
+        this.data = layer != null ? layer.data : Main.main.getEditDataSet();
     }
 
@@ -154,5 +158,7 @@
      * @param layer the data layer. Must not be null.
      * @throws IllegalArgumentException if layer is null
-     */
+     * @deprecated to be removed end of 2017. Use {@link #Command(DataSet)} instead
+     */
+    @Deprecated
     public Command(OsmDataLayer layer) {
         CheckParameterUtil.ensureParameterNotNull(layer, "layer");
@@ -216,5 +222,7 @@
      * @param oldLayer the old layer that was removed
      * @return true if this command is invalid after that layer is removed.
-     */
+     * @deprecated to be removed end of 2017.
+     */
+    @Deprecated
     public boolean invalidBecauselayerRemoved(Layer oldLayer) {
         return layer == oldLayer;
@@ -234,5 +242,7 @@
      * Replies the layer this command is (or was) applied to.
      * @return the layer this command is (or was) applied to
-     */
+     * @deprecated to be removed end of 2017. Use {@link #getAffectedDataSet} instead
+     */
+    @Deprecated
     protected OsmDataLayer getLayer() {
         return layer;
@@ -371,5 +381,7 @@
      * Invalidate all layers that were affected by this command.
      * @see Layer#invalidate()
-     */
+     * @deprecated to be removed end of 2017.
+     */
+    @Deprecated
     public void invalidateAffectedLayers() {
         OsmDataLayer layer = getLayer();
Index: trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 12718)
@@ -108,6 +108,5 @@
 
     /**
-     * Constructor for a single data item. Use the collection constructor to delete multiple
-     * objects.
+     * Constructor for a single data item. Use the collection constructor to delete multiple objects.
      *
      * @param layer the layer context for deleting this primitive. Must not be null.
@@ -115,5 +114,7 @@
      * @throws IllegalArgumentException if data is null
      * @throws IllegalArgumentException if layer is null
-     */
+     * @deprecated to be removed end of 2017. Use {@link #DeleteCommand(DataSet, OsmPrimitive)} instead
+     */
+    @Deprecated
     public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) {
         this(layer, Collections.singleton(data));
@@ -121,6 +122,18 @@
 
     /**
-     * Constructor for a collection of data to be deleted in the context of
-     * a specific layer
+     * Constructor for a single data item. Use the collection constructor to delete multiple objects.
+     *
+     * @param dataset the data set context for deleting this primitive. Must not be null.
+     * @param data the primitive to delete. Must not be null.
+     * @throws IllegalArgumentException if data is null
+     * @throws IllegalArgumentException if layer is null
+     * @since 12718
+     */
+    public DeleteCommand(DataSet dataset, OsmPrimitive data) {
+        this(dataset, Collections.singleton(data));
+    }
+
+    /**
+     * Constructor for a collection of data to be deleted in the context of a specific layer
      *
      * @param layer the layer context for deleting these primitives. Must not be null.
@@ -128,5 +141,7 @@
      * @throws IllegalArgumentException if layer is null
      * @throws IllegalArgumentException if data is null or empty
-     */
+     * @deprecated to be removed end of 2017. Use {@link #DeleteCommand(DataSet, Collection)} instead
+     */
+    @Deprecated
     public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) {
         super(layer);
@@ -137,6 +152,5 @@
 
     /**
-     * Constructor for a collection of data to be deleted in the context of
-     * a specific data set
+     * Constructor for a collection of data to be deleted in the context of a specific data set
      *
      * @param dataset the dataset context for deleting these primitives. Must not be null.
@@ -286,7 +300,25 @@
      * @return command A command to perform the deletions, or null of there is nothing to delete.
      * @throws IllegalArgumentException if layer is null
-     */
+     * @deprecated to be removed end of 2017. Use {@link #deleteWithReferences(Collection, boolean)} instead
+     */
+    @Deprecated
     public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean silent) {
-        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
+        return deleteWithReferences(selection, silent);
+    }
+
+    /**
+     * Delete the primitives and everything they reference.
+     *
+     * If a node is deleted, the node and all ways and relations the node is part of are deleted as well.
+     * If a way is deleted, all relations the way is member of are also deleted.
+     * If a way is deleted, only the way and no nodes are deleted.
+     *
+     * @param selection The list of all object to be deleted.
+     * @param silent  Set to true if the user should not be bugged with additional dialogs
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     * @throws IllegalArgumentException if layer is null
+     * @since 12718
+     */
+    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection, boolean silent) {
         if (selection == null || selection.isEmpty()) return null;
         Set<OsmPrimitive> parents = OsmPrimitive.getReferrer(selection);
@@ -297,5 +329,5 @@
         if (!silent && !checkAndConfirmOutlyingDelete(parents, null))
             return null;
-        return new DeleteCommand(layer, parents);
+        return new DeleteCommand(parents.iterator().next().getDataSet(), parents);
     }
 
@@ -307,11 +339,29 @@
      * If a way is deleted, only the way and no nodes are deleted.
      *
-     * @param layer the {@link OsmDataLayer} in whose context primitives are deleted. Must not be null.
+     * @param layer unused
      * @param selection The list of all object to be deleted.
      * @return command A command to perform the deletions, or null of there is nothing to delete.
      * @throws IllegalArgumentException if layer is null
-     */
+     * @deprecated to be removed end of 2017. Use {@link #deleteWithReferences(Collection)} instead
+     */
+    @Deprecated
     public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
-        return deleteWithReferences(layer, selection, false);
+        return deleteWithReferences(selection);
+    }
+
+    /**
+     * Delete the primitives and everything they reference.
+     *
+     * If a node is deleted, the node and all ways and relations the node is part of are deleted as well.
+     * If a way is deleted, all relations the way is member of are also deleted.
+     * If a way is deleted, only the way and no nodes are deleted.
+     *
+     * @param selection The list of all object to be deleted.
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     * @throws IllegalArgumentException if layer is null
+     * @since 12718
+     */
+    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
+        return deleteWithReferences(selection, false);
     }
 
@@ -325,10 +375,29 @@
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param layer unused
      * @param selection the objects to delete.
      * @return command a command to perform the deletions, or null if there is nothing to delete.
-     */
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection)} instead
+     */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
-        return delete(layer, selection, true, false);
+        return delete(selection);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param selection the objects to delete.
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since 12718
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection) {
+        return delete(selection, true, false);
     }
 
@@ -376,12 +445,14 @@
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param layer unused
      * @param selection the objects to delete.
      * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
      * @return command a command to perform the deletions, or null if there is nothing to delete.
-     */
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection, boolean)} instead
+     */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
             boolean alsoDeleteNodesInWay) {
-        return delete(layer, selection, alsoDeleteNodesInWay, false /* not silent */);
+        return delete(selection, alsoDeleteNodesInWay);
     }
 
@@ -395,12 +466,51 @@
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param selection the objects to delete.
+     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since 12718
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
+        return delete(selection, alsoDeleteNodesInWay, false /* not silent */);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param layer unused
      * @param selection the objects to delete.
      * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
      * @param silent set to true if the user should not be bugged with additional questions
      * @return command a command to perform the deletions, or null if there is nothing to delete.
-     */
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection, boolean, boolean)} instead
+     */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
             boolean alsoDeleteNodesInWay, boolean silent) {
+        return delete(selection, alsoDeleteNodesInWay, silent);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param selection the objects to delete.
+     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
+     * @param silent set to true if the user should not be bugged with additional questions
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since 12718
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay, boolean silent) {
         if (selection == null || selection.isEmpty())
             return null;
@@ -460,6 +570,5 @@
         //
         if (!primitivesToDelete.isEmpty()) {
-            cmds.add(layer != null ? new DeleteCommand(layer, primitivesToDelete) :
-                new DeleteCommand(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
+            cmds.add(new DeleteCommand(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
         }
 
@@ -469,11 +578,23 @@
     /**
      * Create a command that deletes a single way segment. The way may be split by this.
-     * @param layer The layer the segment is in.
+     * @param layer unused
      * @param ws The way segment that should be deleted
      * @return A matching command to safely delete that segment.
-     */
+     * @deprecated to be removed end of 2017. Use {@link #deleteWaySegment(WaySegment)} instead
+     */
+    @Deprecated
     public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) {
+        return deleteWaySegment(ws);
+    }
+
+    /**
+     * Create a command that deletes a single way segment. The way may be split by this.
+     * @param ws The way segment that should be deleted
+     * @return A matching command to safely delete that segment.
+     * @since 12718
+     */
+    public static Command deleteWaySegment(WaySegment ws) {
         if (ws.way.getNodesCount() < 3)
-            return delete(layer, Collections.singleton(ws.way), false);
+            return delete(Collections.singleton(ws.way), false);
 
         if (ws.way.isClosed()) {
@@ -506,5 +627,5 @@
             return new ChangeCommand(ws.way, wnew);
         } else {
-            SplitWayResult split = SplitWayAction.splitWay(layer, ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
+            SplitWayResult split = SplitWayAction.splitWay(ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
             return split != null ? split.getCommand() : null;
         }
Index: trunk/src/org/openstreetmap/josm/command/PurgeCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/PurgeCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/PurgeCommand.java	(revision 12718)
@@ -54,5 +54,7 @@
      * @param toPurge primitives to purge
      * @param makeIncomplete primitives to make incomplete
+     * @deprecated to be removed end of 2017. Use {@link #PurgeCommand(DataSet, Collection, Collection)} instead
      */
+    @Deprecated
     public PurgeCommand(OsmDataLayer layer, Collection<OsmPrimitive> toPurge, Collection<OsmPrimitive> makeIncomplete) {
         super(layer);
@@ -319,6 +321,19 @@
      * @return command to purge selected OSM primitives
      * @since 12688
+     * @deprecated to be removed end of 2017. Use {@link #build(Collection, List)} instead
      */
+    @Deprecated
     public static PurgeCommand build(OsmDataLayer layer, Collection<OsmPrimitive> sel, List<OsmPrimitive> toPurgeAdditionally) {
+        return build(sel, toPurgeAdditionally);
+    }
+
+    /**
+     * Creates a new {@code PurgeCommand} to purge selected OSM primitives.
+     * @param sel selected OSM primitives
+     * @param toPurgeAdditionally optional list that will be filled with primitives to be purged that have not been in the selection
+     * @return command to purge selected OSM primitives
+     * @since 12718
+     */
+    public static PurgeCommand build(Collection<OsmPrimitive> sel, List<OsmPrimitive> toPurgeAdditionally) {
         Set<OsmPrimitive> toPurge = new HashSet<>(sel);
         // finally, contains all objects that are purged
@@ -423,6 +438,5 @@
         }
 
-        return layer != null ? new PurgeCommand(layer, toPurgeChecked, makeIncomplete)
-                : new PurgeCommand(toPurgeChecked.iterator().next().getDataSet(), toPurgeChecked, makeIncomplete);
+        return new PurgeCommand(toPurgeChecked.iterator().next().getDataSet(), toPurgeChecked, makeIncomplete);
     }
 
Index: trunk/src/org/openstreetmap/josm/command/SequenceCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/SequenceCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/SequenceCommand.java	(revision 12718)
@@ -12,4 +12,5 @@
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Utils;
@@ -136,5 +137,11 @@
     }
 
+    /**
+     * Invalidate all layers that were affected by this command.
+     * @see Layer#invalidate()
+     * @deprecated to be removed end of 2017.
+     */
     @Override
+    @Deprecated
     public void invalidateAffectedLayers() {
         super.invalidateAffectedLayers();
Index: trunk/src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java	(revision 12718)
@@ -16,5 +16,4 @@
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -33,5 +32,7 @@
      * @param layer the data layer. Must not be null.
      * @param conflict the conflict to add
+     * @deprecated to be removed end of 2017. Use {@link #ConflictAddCommand(DataSet, Conflict)} instead
      */
+    @Deprecated
     public ConflictAddCommand(OsmDataLayer layer, Conflict<? extends OsmPrimitive> conflict) {
         super(layer);
@@ -56,5 +57,5 @@
                         + "''{1}''.<br>"
                         + "This conflict cannot be added.</html>",
-                        Utils.escapeReservedCharactersHTML(getLayer().getName()),
+                        Utils.escapeReservedCharactersHTML(getAffectedDataSet().getName()),
                         Utils.escapeReservedCharactersHTML(conflict.getMy().getDisplayName(DefaultNameFormatter.getInstance()))
                 ),
@@ -77,12 +78,13 @@
     @Override
     public void undoCommand() {
-        if (MainApplication.isDisplayingMapView() && !MainApplication.getLayerManager().containsLayer(getLayer())) {
+        DataSet ds = getAffectedDataSet();
+        if (!Main.main.containsDataSet(ds)) {
             Logging.warn(tr("Layer ''{0}'' does not exist any more. Cannot remove conflict for object ''{1}''.",
-                    getLayer().getName(),
+                    ds.getName(),
                     conflict.getMy().getDisplayName(DefaultNameFormatter.getInstance())
             ));
             return;
         }
-        getAffectedDataSet().getConflicts().remove(conflict);
+        ds.getConflicts().remove(conflict);
     }
 
Index: trunk/src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java	(revision 12718)
@@ -6,9 +6,9 @@
 import java.util.Objects;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Logging;
@@ -24,5 +24,5 @@
 public abstract class ConflictResolveCommand extends Command {
     /** the list of resolved conflicts */
-    private final ConflictCollection resolvedConflicts;
+    private final ConflictCollection resolvedConflicts = new ConflictCollection();
 
     /**
@@ -30,6 +30,5 @@
      */
     public ConflictResolveCommand() {
-        super();
-        resolvedConflicts = new ConflictCollection();
+        // Do nothing
     }
 
@@ -37,8 +36,17 @@
      * Constructs a new {@code ConflictResolveCommand} in the context of a given data layer.
      * @param layer the data layer. Must not be null.
+     * @deprecated to be removed end of 2017. Use {@link #ConflictResolveCommand(DataSet)} instead
      */
+    @Deprecated
     public ConflictResolveCommand(OsmDataLayer layer) {
         super(layer);
-        resolvedConflicts = new ConflictCollection();
+    }
+
+    /**
+     * Constructs a new {@code ConflictResolveCommand} in the context of a given data set.
+     * @param ds the data set. Must not be null.
+     */
+    public ConflictResolveCommand(DataSet ds) {
+        super(ds);
     }
 
@@ -56,5 +64,5 @@
     /**
      * reconstitutes all remembered conflicts. Add the remembered conflicts to the
-     * set of conflicts of the {@link OsmDataLayer} this command was applied to.
+     * set of conflicts of the {@link DataSet} this command was applied to.
      *
      */
@@ -72,15 +80,14 @@
         super.undoCommand();
 
-        if (MainApplication.isDisplayingMapView()) {
-            if (!MainApplication.getLayerManager().containsLayer(getLayer())) {
-                Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
-                        this.toString(),
-                        getLayer().toString()
-                ));
-                return;
-            }
+        DataSet ds = getAffectedDataSet();
+        if (!Main.main.containsDataSet(ds)) {
+            Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
+                    this.toString(),
+                    ds.getName()
+            ));
+            return;
+        }
 
-            MainApplication.getLayerManager().setActiveLayer(getLayer());
-        }
+        Main.main.setEditDataSet(ds);
         reconstituteConflicts();
     }
Index: trunk/src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java	(revision 12718)
@@ -10,4 +10,5 @@
 import javax.swing.Icon;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -15,6 +16,4 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -72,15 +71,14 @@
     @Override
     public void undoCommand() {
-        OsmDataLayer layer = getLayer();
-        if (!MainApplication.getLayerManager().containsLayer(layer)) {
+        DataSet editDs = getAffectedDataSet();
+        if (!Main.main.containsDataSet(editDs)) {
             Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
                     this.toString(),
-                    layer.toString()
+                    editDs.getName()
             ));
             return;
         }
 
-        MainApplication.getLayerManager().setActiveLayer(layer);
-        DataSet editDs = MainApplication.getLayerManager().getEditDataSet();
+        Main.main.setEditDataSet(editDs);
 
         // restore the former state
Index: trunk/src/org/openstreetmap/josm/data/UndoRedoHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/UndoRedoHandler.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/data/UndoRedoHandler.java	(revision 12718)
@@ -11,20 +11,12 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
- * This is the global undo/redo handler for all {@link OsmDataLayer}s.
+ * This is the global undo/redo handler for all {@link DataSet}s.
  * <p>
- * If you want to change a data layer, you can use {@link #add(Command)} to execute a command on it and make that command undoable.
+ * If you want to change a data set, you can use {@link #add(Command)} to execute a command on it and make that command undoable.
  */
-public class UndoRedoHandler implements LayerChangeListener {
+public class UndoRedoHandler {
 
     /**
@@ -45,5 +37,19 @@
      */
     public UndoRedoHandler() {
-        MainApplication.getLayerManager().addLayerChangeListener(this);
+        // Do nothing
+    }
+
+    /**
+     * A listener that gets notified of command queue (undo/redo) size changes.
+     * @since 12718 (moved from {@code OsmDataLayer}
+     */
+    @FunctionalInterface
+    public interface CommandQueueListener {
+        /**
+         * Notifies the listener about the new queue size
+         * @param queueSize Undo stack size
+         * @param redoSize Redo stack size
+         */
+        void commandChanged(int queueSize, int redoSize);
     }
 
@@ -92,5 +98,4 @@
         }
         addNoRedraw(c);
-        c.invalidateAffectedLayers();
         afterAdd();
 
@@ -125,5 +130,4 @@
                 final Command c = commands.removeLast();
                 c.undoCommand();
-                c.invalidateAffectedLayers();
                 redoCommands.addFirst(c);
                 if (commands.isEmpty()) {
@@ -161,5 +165,4 @@
             final Command c = redoCommands.removeFirst();
             c.executeCommand();
-            c.invalidateAffectedLayers();
             commands.add(c);
             if (redoCommands.isEmpty()) {
@@ -197,13 +200,14 @@
 
     /**
-     * Resets all commands that affect the given layer.
-     * @param layer The layer that was affected.
-     */
-    public void clean(Layer layer) {
-        if (layer == null)
+     * Resets all commands that affect the given dataset.
+     * @param dataSet The data set that was affected.
+     * @since 12718
+     */
+    public void clean(DataSet dataSet) {
+        if (dataSet == null)
             return;
         boolean changed = false;
         for (Iterator<Command> it = commands.iterator(); it.hasNext();) {
-            if (it.next().invalidBecauselayerRemoved(layer)) {
+            if (it.next().getAffectedDataSet() == dataSet) {
                 it.remove();
                 changed = true;
@@ -211,5 +215,5 @@
         }
         for (Iterator<Command> it = redoCommands.iterator(); it.hasNext();) {
-            if (it.next().invalidBecauselayerRemoved(layer)) {
+            if (it.next().getAffectedDataSet() == dataSet) {
                 it.remove();
                 changed = true;
@@ -219,19 +223,4 @@
             fireCommandsChanged();
         }
-    }
-
-    @Override
-    public void layerRemoving(LayerRemoveEvent e) {
-        clean(e.getRemovedLayer());
-    }
-
-    @Override
-    public void layerAdded(LayerAddEvent e) {
-        // Do nothing
-    }
-
-    @Override
-    public void layerOrderChanged(LayerOrderChangeEvent e) {
-        // Do nothing
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 12718)
@@ -169,4 +169,5 @@
     private final List<AbstractDatasetChangedEvent> cachedEvents = new ArrayList<>();
 
+    private String name;
     private UploadPolicy uploadPolicy;
 
@@ -1360,4 +1361,22 @@
     }
 
+    /**
+     * Returns the name of this data set (optional).
+     * @return the name of this data set. Can be {@code null}
+     * @since 12718
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of this data set.
+     * @param name the new name of this data set. Can be {@code null} to reset it
+     * @since 12718
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
     /* --------------------------------------------------------------------------------- */
     /* interface ProjectionChangeListner                                                 */
Index: trunk/src/org/openstreetmap/josm/data/validation/Test.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/Test.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/data/validation/Test.java	(revision 12718)
@@ -23,5 +23,4 @@
 import org.openstreetmap.josm.data.osm.search.SearchCompiler.NotOutsideDataSourceArea;
 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
@@ -331,5 +330,5 @@
         }
         if (!primitivesToDelete.isEmpty()) {
-            return DeleteCommand.delete(MainApplication.getLayerManager().getEditLayer(), primitivesToDelete);
+            return DeleteCommand.delete(primitivesToDelete);
         } else {
             return null;
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12718)
@@ -72,4 +72,5 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.UndoRedoHandler;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
@@ -84,6 +85,11 @@
 import org.openstreetmap.josm.gui.io.SaveLayersDialog;
 import org.openstreetmap.josm.gui.layer.AutosaveTask;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
 import org.openstreetmap.josm.gui.layer.MainLayerManager;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.TMSLayer;
 import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
@@ -187,7 +193,7 @@
     /**
      * The commands undo/redo handler.
-     * @since 12641 (as a replacement to {@code Main.main.undoRedo})
-     */
-    public static final UndoRedoHandler undoRedo = new UndoRedoHandler(); // Must be declared after layerManager
+     * @since 12641
+     */
+    public static UndoRedoHandler undoRedo;
 
     /**
@@ -213,4 +219,24 @@
     public MainApplication(MainFrame mainFrame) {
         this.mainFrame = mainFrame;
+        undoRedo = super.undoRedo;
+        getLayerManager().addLayerChangeListener(new LayerChangeListener() {
+            @Override
+            public void layerRemoving(LayerRemoveEvent e) {
+                Layer layer = e.getRemovedLayer();
+                if (layer instanceof OsmDataLayer) {
+                    undoRedo.clean(((OsmDataLayer) layer).data);
+                }
+            }
+
+            @Override
+            public void layerOrderChanged(LayerOrderChangeEvent e) {
+                // Do nothing
+            }
+
+            @Override
+            public void layerAdded(LayerAddEvent e) {
+                // Do nothing
+            }
+        });
     }
 
@@ -405,4 +431,18 @@
     public DataSet getEditDataSet() {
         return getLayerManager().getEditDataSet();
+    }
+
+    @Override
+    public void setEditDataSet(DataSet ds) {
+        Optional<OsmDataLayer> layer = getLayerManager().getLayersOfType(OsmDataLayer.class).stream()
+                .filter(l -> l.data.equals(ds)).findFirst();
+        if (layer.isPresent()) {
+            getLayerManager().setActiveLayer(layer.get());
+        }
+    }
+
+    @Override
+    public boolean containsDataSet(DataSet ds) {
+        return getLayerManager().getLayersOfType(OsmDataLayer.class).stream().anyMatch(l -> l.data.equals(ds));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java	(revision 12718)
@@ -83,5 +83,5 @@
             }
         }
-        return new AddPrimitivesCommand(bufferCopy, toSelect, layer);
+        return new AddPrimitivesCommand(bufferCopy, toSelect, layer.data);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 12718)
@@ -39,4 +39,5 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.PseudoCommand;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -44,5 +45,4 @@
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.GBC;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 12718)
@@ -11,4 +11,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
@@ -19,5 +20,4 @@
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(revision 12718)
@@ -73,5 +73,5 @@
         if (newRelation.getMembersCount() == 0 && !newRelation.hasKeys())
             return;
-        MainApplication.undoRedo.add(new AddCommand(layer, newRelation));
+        MainApplication.undoRedo.add(new AddCommand(layer.data, newRelation));
 
         // make sure everybody is notified about the changes
@@ -95,5 +95,5 @@
         memberTableModel.applyToRelation(editedRelation);
         Conflict<Relation> conflict = new Conflict<>(editor.getRelation(), editedRelation);
-        MainApplication.undoRedo.add(new ConflictAddCommand(layer, conflict));
+        MainApplication.undoRedo.add(new ConflictAddCommand(layer.data, conflict));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 12718)
@@ -339,5 +339,5 @@
      * @param name the name. If null, the name is set to the empty string.
      */
-    public final void setName(String name) {
+    public void setName(String name) {
         if (this.name != null) {
             removeColorPropertyListener();
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 12718)
@@ -295,17 +295,4 @@
 
     /**
-     * A listener that gets notified of command queue (undo/redo) size changes.
-     */
-    @FunctionalInterface
-    public interface CommandQueueListener {
-        /**
-         * Notifies the listener about the new queue size
-         * @param queueSize Undo stack size
-         * @param redoSize Redo stack size
-         */
-        void commandChanged(int queueSize, int redoSize);
-    }
-
-    /**
      * Listener called when a state of this layer has changed.
      * @since 10600 (functional interface)
@@ -401,4 +388,5 @@
         CheckParameterUtil.ensureParameterNotNull(data, "data");
         this.data = data;
+        this.data.setName(name);
         this.setAssociatedFile(associatedFile);
         data.addDataSetListener(new DataSetListenerAdapter(this));
@@ -603,5 +591,5 @@
             return;
 
-        MainApplication.undoRedo.clean(this);
+        MainApplication.undoRedo.clean(data);
 
         // if uploaded, clean the modified flags as well
@@ -1146,3 +1134,11 @@
         invalidate();
     }
+
+    @Override
+    public void setName(String name) {
+        if (data != null) {
+            data.setName(name);
+        }
+        super.setName(name);
+    }
 }
Index: trunk/src/org/openstreetmap/josm/tools/Geometry.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Geometry.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/tools/Geometry.java	(revision 12718)
@@ -37,5 +37,4 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
@@ -103,5 +102,4 @@
         }
 
-        OsmDataLayer layer = MainApplication.getLayerManager().getEditLayer();
         DataSet dataset = ways.get(0).getDataSet();
 
@@ -210,5 +208,5 @@
 
                                 if (intNode == newNode) {
-                                    cmds.add(layer != null ? new AddCommand(layer, intNode) : new AddCommand(dataset, intNode));
+                                    cmds.add(new AddCommand(dataset, intNode));
                                 }
                             }
Index: trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(revision 12716)
+++ trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(revision 12718)
@@ -104,5 +104,5 @@
         }
         // Purge all other ways and relations so dataset only contains lefthand traffic data
-        PurgeCommand.build(null, toPurge, null).executeCommand();
+        PurgeCommand.build(toPurge, null).executeCommand();
         // Combine adjacent countries into a single polygon
         Collection<Way> optimizedWays = new ArrayList<>();
