diff --git a/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java b/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
index fcd933e..707537d 100644
--- a/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
+++ b/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
@@ -107,7 +107,7 @@ public class ExtensionFileFilter extends FileFilter implements java.io.FileFilte
             try {
                 FileExporter exporter = exporterClass.getConstructor().newInstance();
                 exporters.add(exporter);
-                MapView.addLayerChangeListener(exporter);
+                Main.getLayerManager().addAndFireActiveLayerChangeListener(exporter);
             } catch (ReflectiveOperationException e) {
                 if (Main.isDebugEnabled()) {
                     Main.debug(e.getMessage());
diff --git a/src/org/openstreetmap/josm/actions/JosmAction.java b/src/org/openstreetmap/josm/actions/JosmAction.java
index 5e450aa..76686c9 100644
--- a/src/org/openstreetmap/josm/actions/JosmAction.java
+++ b/src/org/openstreetmap/josm/actions/JosmAction.java
@@ -15,12 +15,11 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
-import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -183,7 +182,9 @@ public abstract class JosmAction extends AbstractAction implements Destroyable {
         if (sc != null) {
             Main.unregisterActionShortcut(this);
         }
-        MapView.removeLayerChangeListener(layerChangeAdapter);
+        if (layerChangeAdapter != null) {
+            Main.getLayerManager().removeActiveLayerChangeListener(layerChangeAdapter);
+        }
         DataSet.removeSelectionListener(selectionChangeAdapter);
     }
 
@@ -225,10 +226,9 @@ public abstract class JosmAction extends AbstractAction implements Destroyable {
 
     protected void installAdapters() {
         // make this action listen to layer change and selection change events
-        //
         layerChangeAdapter = new LayerChangeAdapter();
         selectionChangeAdapter = new SelectionChangeAdapter();
-        MapView.addLayerChangeListener(layerChangeAdapter);
+        Main.getLayerManager().addActiveLayerChangeListener(layerChangeAdapter);
         DataSet.addSelectionListener(selectionChangeAdapter);
         initEnabledState();
     }
@@ -290,41 +290,32 @@ public abstract class JosmAction extends AbstractAction implements Destroyable {
     }
 
     /**
-     * Adapter for layer change events
-     *
+     * Adapter for layer change events. Runs updateEnabledState() whenever the active layer changed.
      */
-    protected class LayerChangeAdapter implements MapView.LayerChangeListener {
-        private void updateEnabledStateInEDT() {
-            GuiHelper.runInEDT(new Runnable() {
-                @Override public void run() {
-                    updateEnabledState();
-                }
-            });
-        }
-
+    protected class LayerChangeAdapter implements ActiveLayerChangeListener {
         @Override
-        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-            updateEnabledStateInEDT();
+        public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+            updateEnabledState();
         }
 
         @Override
-        public void layerAdded(Layer newLayer) {
-            updateEnabledStateInEDT();
-        }
-
-        @Override
-        public void layerRemoved(Layer oldLayer) {
-            updateEnabledStateInEDT();
+        public String toString() {
+            return "LayerChangeAdapter [" + JosmAction.this.toString() + "]";
         }
     }
 
     /**
-     * Adapter for selection change events
+     * Adapter for selection change events. Runs updateEnabledState() whenever the selection changed.
      */
     protected class SelectionChangeAdapter implements SelectionChangedListener {
         @Override
         public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
             updateEnabledState(newSelection);
         }
+
+        @Override
+        public String toString() {
+            return "SelectionChangeAdapter [" + JosmAction.this.toString() + "]";
+        }
     }
 }
diff --git a/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java b/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
index 6c79832..f6e1fcb 100644
--- a/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
+++ b/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
@@ -20,10 +20,14 @@ import javax.swing.plaf.basic.BasicArrowButton;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.SideButton;
 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.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -32,7 +36,7 @@ import org.openstreetmap.josm.tools.Shortcut;
 /**
  * Action for accessing recent relations.
  */
-public class RecentRelationsAction implements ActionListener, CommandQueueListener, LayerChangeListener {
+public class RecentRelationsAction implements ActionListener, CommandQueueListener, LayerChangeListener, ActiveLayerChangeListener {
 
     private final SideButton editButton;
     private final BasicArrowButton arrow;
@@ -47,7 +51,8 @@ public class RecentRelationsAction implements ActionListener, CommandQueueListen
         arrow = editButton.createArrow(this);
         arrow.setToolTipText(tr("List of recent relations"));
         Main.main.undoRedo.addCommandQueueListener(this);
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
         enableArrow();
         shortcut = Shortcut.registerShortcut(
             "relationeditor:editrecentrelation",
@@ -108,17 +113,22 @@ public class RecentRelationsAction implements ActionListener, CommandQueueListen
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void layerAdded(LayerAddEvent e) {
         enableArrow();
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
         enableArrow();
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        enableArrow();
+    }
+
+    @Override
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
         enableArrow();
     }
 
@@ -181,4 +191,5 @@ public class RecentRelationsAction implements ActionListener, CommandQueueListen
             EditRelationAction.launchEditor(relation);
         }
     }
+
 }
diff --git a/src/org/openstreetmap/josm/data/UndoRedoHandler.java b/src/org/openstreetmap/josm/data/UndoRedoHandler.java
index bb07a61..c15ebfc 100644
--- a/src/org/openstreetmap/josm/data/UndoRedoHandler.java
+++ b/src/org/openstreetmap/josm/data/UndoRedoHandler.java
@@ -9,12 +9,15 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MapView;
 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.CommandQueueListener;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
-public class UndoRedoHandler implements MapView.LayerChangeListener {
+public class UndoRedoHandler implements LayerChangeListener {
 
     /**
      * All commands that were made on the dataset. Don't write from outside!
@@ -31,7 +34,7 @@ public class UndoRedoHandler implements MapView.LayerChangeListener {
      * Constructs a new {@code UndoRedoHandler}.
      */
     public UndoRedoHandler() {
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
     }
 
     /**
@@ -169,17 +172,17 @@ public class UndoRedoHandler implements MapView.LayerChangeListener {
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        clean(oldLayer);
+    public void layerRemoving(LayerRemoveEvent e) {
+        clean(e.getRemovedLayer());
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
+    public void layerAdded(LayerAddEvent e) {
         // Do nothing
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
         // Do nothing
     }
 
diff --git a/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java b/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java
index d76fc027..16650ca 100644
--- a/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java
+++ b/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java
@@ -27,10 +27,11 @@ import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.NavigatableComponent;
-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;
 
 /**
@@ -50,7 +51,7 @@ public final class MultipolygonCache implements DataSetListener, LayerChangeList
         this.selectedPolyData = new ArrayList<>();
         Main.addProjectionChangeListener(this);
         DataSet.addSelectionListener(this);
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
     }
 
     /**
@@ -285,19 +286,19 @@ public final class MultipolygonCache implements DataSetListener, LayerChangeList
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void layerAdded(LayerAddEvent e) {
         // Do nothing
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
         // Do nothing
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer instanceof OsmDataLayer) {
-            clear(((OsmDataLayer) oldLayer).data);
+    public void layerRemoving(LayerRemoveEvent e) {
+        if (e.getRemovedLayer() instanceof OsmDataLayer) {
+            clear(((OsmDataLayer) e.getRemovedLayer()).data);
         }
     }
 
diff --git a/src/org/openstreetmap/josm/gui/ImageryMenu.java b/src/org/openstreetmap/josm/gui/ImageryMenu.java
index 45ee187..a6359bc 100644
--- a/src/org/openstreetmap/josm/gui/ImageryMenu.java
+++ b/src/org/openstreetmap/josm/gui/ImageryMenu.java
@@ -32,9 +32,11 @@ import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
 import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
 import org.openstreetmap.josm.data.imagery.Shape;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.ImageryLayer;
-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.preferences.imagery.ImageryPreference;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -110,7 +112,7 @@ public class ImageryMenu extends JMenu implements LayerChangeListener {
         /* I18N: mnemonic: I */
         super(trc("menu", "Imagery"));
         setupMenuScroller();
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
         // build dynamically
         addMenuListener(new MenuListener() {
             @Override
@@ -209,11 +211,7 @@ public class ImageryMenu extends JMenu implements LayerChangeListener {
     }
 
     private JMenuItem getNewOffsetMenu() {
-        if (!Main.isDisplayingMapView()) {
-            offsetAction.setEnabled(false);
-            return singleOffset;
-        }
-        Collection<ImageryLayer> layers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
+        Collection<ImageryLayer> layers = Main.getLayerManager().getLayersOfType(ImageryLayer.class);
         if (layers.isEmpty()) {
             offsetAction.setEnabled(false);
             return singleOffset;
@@ -238,22 +236,22 @@ public class ImageryMenu extends JMenu implements LayerChangeListener {
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        // Do nothing
+    public void layerAdded(LayerAddEvent e) {
+        if (e.getAddedLayer() instanceof ImageryLayer) {
+            refreshOffsetMenu();
+        }
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        if (newLayer instanceof ImageryLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
+        if (e.getRemovedLayer() instanceof ImageryLayer) {
             refreshOffsetMenu();
         }
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer instanceof ImageryLayer) {
-            refreshOffsetMenu();
-        }
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        refreshOffsetMenu();
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/gui/MainFrame.java b/src/org/openstreetmap/josm/gui/MainFrame.java
index 8fa96e5..75ac489 100644
--- a/src/org/openstreetmap/josm/gui/MainFrame.java
+++ b/src/org/openstreetmap/josm/gui/MainFrame.java
@@ -113,7 +113,7 @@ public class MainFrame extends JFrame {
             public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
                 refreshTitle();
             }
-        }, false);
+        });
         Main.getLayerManager().addLayerChangeListener(new ManageLayerListeners(), true);
 
         refreshTitle();
diff --git a/src/org/openstreetmap/josm/gui/MainMenu.java b/src/org/openstreetmap/josm/gui/MainMenu.java
index 8ab7575..be35785 100644
--- a/src/org/openstreetmap/josm/gui/MainMenu.java
+++ b/src/org/openstreetmap/josm/gui/MainMenu.java
@@ -116,7 +116,8 @@ import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.gui.dialogs.MenuItemSearchDialog;
 import org.openstreetmap.josm.gui.io.RecentlyOpenedFilesMenu;
-import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.mappaint.MapPaintMenu;
 import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference;
 import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
@@ -821,7 +822,7 @@ public class MainMenu extends JMenuBar {
 
         windowMenu.addMenuListener(menuSeparatorHandler);
 
-        new PresetsMenuEnabler(presetsMenu).refreshEnabled();
+        new PresetsMenuEnabler(presetsMenu);
     }
 
     /**
@@ -885,34 +886,17 @@ public class MainMenu extends JMenuBar {
         }
     }
 
-    static class PresetsMenuEnabler implements MapView.LayerChangeListener {
+    static class PresetsMenuEnabler implements ActiveLayerChangeListener {
         private final JMenu presetsMenu;
 
         PresetsMenuEnabler(JMenu presetsMenu) {
-            MapView.addLayerChangeListener(this);
             this.presetsMenu = presetsMenu;
-        }
-
-        /**
-         * Refreshes the enabled state
-         */
-        protected void refreshEnabled() {
-            presetsMenu.setEnabled(Main.main.hasEditLayer());
-        }
-
-        @Override
-        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-            refreshEnabled();
-        }
-
-        @Override
-        public void layerAdded(Layer newLayer) {
-            refreshEnabled();
+            Main.getLayerManager().addAndFireActiveLayerChangeListener(this);
         }
 
         @Override
-        public void layerRemoved(Layer oldLayer) {
-            refreshEnabled();
+        public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+            presetsMenu.setEnabled(e.getSource().getEditLayer() != null);
         }
     }
 
diff --git a/src/org/openstreetmap/josm/gui/MapFrame.java b/src/org/openstreetmap/josm/gui/MapFrame.java
index 6c0e557..62030d9 100644
--- a/src/org/openstreetmap/josm/gui/MapFrame.java
+++ b/src/org/openstreetmap/josm/gui/MapFrame.java
@@ -37,7 +37,6 @@ import javax.swing.JPopupMenu;
 import javax.swing.JSplitPane;
 import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
 import javax.swing.border.Border;
 import javax.swing.event.PopupMenuEvent;
 import javax.swing.event.PopupMenuListener;
@@ -58,7 +57,6 @@ import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.ViewportData;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.dialogs.ChangesetDialog;
 import org.openstreetmap.josm.gui.dialogs.CommandStackDialog;
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
@@ -76,6 +74,12 @@ import org.openstreetmap.josm.gui.dialogs.ValidatorDialog;
 import org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.LayerManager;
+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.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.util.AdvancedKeyPressDetector;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.GBC;
@@ -89,7 +93,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  *
  * @author imi
  */
-public class MapFrame extends JPanel implements Destroyable, LayerChangeListener {
+public class MapFrame extends JPanel implements Destroyable, ActiveLayerChangeListener, LayerChangeListener {
 
     /**
      * The current mode, this frame operates.
@@ -284,7 +288,8 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
 
         // status line below the map
         statusLine = new MapStatus(this);
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
 
         boolean unregisterTab = Shortcut.findShortcut(KeyEvent.VK_TAB, 0) != null;
         if (unregisterTab) {
@@ -328,7 +333,8 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
      */
     @Override
     public void destroy() {
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
         dialogsPanel.destroy();
         Main.pref.removePreferenceChangeListener(sidetoolbarPreferencesChangedListener);
         for (int i = 0; i < toolBarActions.getComponentCount(); ++i) {
@@ -756,8 +762,9 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
         boolean modeChanged = false;
+        Layer newLayer = e.getSource().getActiveLayer();
         if (mapMode == null || !mapMode.layerIsSupported(newLayer)) {
             MapMode newMapMode = getLastMapMode(newLayer);
             modeChanged = newMapMode != mapMode;
@@ -770,7 +777,7 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
             }
         }
         // if this is really a change (and not the first active layer)
-        if (oldLayer != null) {
+        if (e.getPreviousActiveLayer() != null) {
             if (!modeChanged && mapMode != null) {
                 // Let mapmodes know about new active layer
                 mapMode.exitMode();
@@ -782,11 +789,7 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
 
         // After all listeners notice new layer, some buttons will be disabled/enabled
         // and possibly need to be hidden/shown.
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override public void run() {
-                validateToolBarsVisibility();
-            }
-        });
+        validateToolBarsVisibility();
     }
 
     private MapMode getLastMapMode(Layer newLayer) {
@@ -802,12 +805,18 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        // Do nothing
+    public void layerAdded(LayerAddEvent e) {
+        // ignored
+    }
+
+    @Override
+    public void layerRemoving(LayerRemoveEvent e) {
+        lastMapMode.remove(e.getRemovedLayer());
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        lastMapMode.remove(oldLayer);
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // ignored
     }
+
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java b/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
index 84ee5e8..f2ef962 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
@@ -185,11 +185,11 @@ public class LayerListDialog extends ToggleDialog {
         //
         DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
         selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-        model = new LayerListModel(selectionModel);
+        model = new LayerListModel(layerManager, selectionModel);
 
         // create the list control
         //
-        layerList = new LayerList(model, layerManager);
+        layerList = new LayerList(model);
         layerList.setSelectionModel(selectionModel);
         layerList.addMouseListener(new PopupMenuHandler());
         layerList.setBackground(UIManager.getColor("Button.background"));
@@ -329,7 +329,7 @@ public class LayerListDialog extends ToggleDialog {
 
     @Override
     public void showNotify() {
-        MapView.addLayerChangeListener(activateLayerAction);
+        layerManager.addActiveLayerChangeListener(activateLayerAction);
         layerManager.addLayerChangeListener(model);
         layerManager.addAndFireActiveLayerChangeListener(model);
         model.populate();
@@ -339,7 +339,7 @@ public class LayerListDialog extends ToggleDialog {
     public void hideNotify() {
         layerManager.removeLayerChangeListener(model);
         layerManager.removeActiveLayerChangeListener(model);
-        MapView.removeLayerChangeListener(activateLayerAction);
+        layerManager.removeActiveLayerChangeListener(activateLayerAction);
     }
 
     /**
@@ -648,13 +648,15 @@ public class LayerListDialog extends ToggleDialog {
         private final DefaultListSelectionModel selectionModel;
         private final CopyOnWriteArrayList<LayerListModelListener> listeners;
         private LayerList layerList;
+        private final MainLayerManager layerManager;
 
         /**
          * constructor
-         *
+         * @param layerManager The layer manager to use for the list.
          * @param selectionModel the list selection model
          */
-        LayerListModel(DefaultListSelectionModel selectionModel) {
+        LayerListModel(MainLayerManager layerManager, DefaultListSelectionModel selectionModel) {
+            this.layerManager = layerManager;
             this.selectionModel = selectionModel;
             listeners = new CopyOnWriteArrayList<>();
         }
@@ -663,13 +665,12 @@ public class LayerListDialog extends ToggleDialog {
             this.layerList = layerList;
         }
 
-        private MainLayerManager getLayerManager() {
-            // layerList should never be null. But if it is, we should not crash.
-            if (layerList == null) {
-                return new MainLayerManager();
-            } else {
-                return layerList.getLayerManager();
-            }
+        /**
+         * The layer manager this model is for.
+         * @return The layer manager.
+         */
+        public MainLayerManager getLayerManager() {
+            return layerManager;
         }
 
         /**
@@ -1124,11 +1125,9 @@ public class LayerListDialog extends ToggleDialog {
      * This component displays a list of layers and provides the methods needed by {@link LayerListModel}.
      */
     static class LayerList extends JTable {
-        private final transient MainLayerManager layerManager;
 
-        LayerList(LayerListModel dataModel, MainLayerManager layerManager) {
+        LayerList(LayerListModel dataModel) {
             super(dataModel);
-            this.layerManager = layerManager;
             dataModel.setLayerList(this);
         }
 
@@ -1141,15 +1140,6 @@ public class LayerListDialog extends ToggleDialog {
             rect.setLocation(rect.x - pt.x, rect.y - pt.y);
             viewport.scrollRectToVisible(rect);
         }
-
-        /**
-         * Gets you the layer manager used for this list.
-         * @return The layer manager.
-         * @since 10288
-         */
-        public MainLayerManager getLayerManager() {
-            return layerManager;
-        }
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java b/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java
index 7659768..56dde01 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java
@@ -38,12 +38,13 @@ import org.openstreetmap.josm.data.notes.Note;
 import org.openstreetmap.josm.data.notes.Note.State;
 import org.openstreetmap.josm.data.notes.NoteComment;
 import org.openstreetmap.josm.data.osm.NoteData;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.NoteInputDialog;
 import org.openstreetmap.josm.gui.NoteSortDialog;
 import org.openstreetmap.josm.gui.SideButton;
-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.NoteLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.date.DateUtils;
@@ -98,7 +99,7 @@ public class NotesDialog extends ToggleDialog implements LayerChangeListener {
         sortAction = new SortAction();
         uploadAction = new UploadNotesAction();
         buildDialog();
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
     }
 
     private void buildDialog() {
@@ -168,23 +169,19 @@ public class NotesDialog extends ToggleDialog implements LayerChangeListener {
         }
     }
 
-    @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        // Do nothing
-    }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        if (newLayer instanceof NoteLayer) {
-            noteData = ((NoteLayer) newLayer).getNoteData();
+    public void layerAdded(LayerAddEvent e) {
+        if (e.getAddedLayer() instanceof NoteLayer) {
+            noteData = ((NoteLayer) e.getAddedLayer()).getNoteData();
             model.setData(noteData.getNotes());
             setNotes(noteData.getSortedNotes());
         }
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer instanceof NoteLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
+        if (e.getRemovedLayer() instanceof NoteLayer) {
             noteData = null;
             model.clearData();
             if (Main.map.mapMode instanceof AddNoteAction) {
@@ -193,6 +190,11 @@ public class NotesDialog extends ToggleDialog implements LayerChangeListener {
         }
     }
 
+    @Override
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // ignored
+    }
+
     /**
      * Sets the list of notes to be displayed in the dialog.
      * The dialog should match the notes displayed in the note layer.
diff --git a/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java b/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java
index 57ac553..e452b71 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java
@@ -34,9 +34,10 @@ import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
-import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -49,7 +50,7 @@ import org.openstreetmap.josm.tools.Utils;
  * selection area, along with the number of objects.
  *
  */
-public class UserListDialog extends ToggleDialog implements SelectionChangedListener, MapView.LayerChangeListener {
+public class UserListDialog extends ToggleDialog implements SelectionChangedListener, ActiveLayerChangeListener {
 
     /**
      * The display list.
@@ -71,12 +72,12 @@ public class UserListDialog extends ToggleDialog implements SelectionChangedList
     @Override
     public void showNotify() {
         DataSet.addSelectionListener(this);
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
     }
 
     @Override
     public void hideNotify() {
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
         DataSet.removeSelectionListener(this);
     }
 
@@ -112,24 +113,15 @@ public class UserListDialog extends ToggleDialog implements SelectionChangedList
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        if (newLayer instanceof OsmDataLayer) {
-            refresh(((OsmDataLayer) newLayer).data.getAllSelected());
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        Layer activeLayer = e.getSource().getActiveLayer();
+        if (activeLayer instanceof OsmDataLayer) {
+            refresh(((OsmDataLayer) activeLayer).data.getAllSelected());
         } else {
             refresh(null);
         }
     }
 
-    @Override
-    public void layerAdded(Layer newLayer) {
-        // do nothing
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
-        // do nothing
-    }
-
     /**
      * Refreshes user list from given collection of OSM primitives.
      * @param fromPrimitives OSM primitives to fetch users from
diff --git a/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java b/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
index 93cd671..e49b466 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
@@ -41,13 +41,12 @@ import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.data.validation.OsmValidator;
 import org.openstreetmap.josm.data.validation.TestError;
 import org.openstreetmap.josm.data.validation.ValidatorVisitor;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.PopupMenuHandler;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.validator.ValidatorTreePanel;
-import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
@@ -65,7 +64,7 @@ import org.xml.sax.SAXException;
  *
  * @author frsantos
  */
-public class ValidatorDialog extends ToggleDialog implements SelectionChangedListener, LayerChangeListener {
+public class ValidatorDialog extends ToggleDialog implements SelectionChangedListener, ActiveLayerChangeListener {
 
     /** The display tree */
     public ValidatorTreePanel tree;
@@ -178,16 +177,12 @@ public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis
         if (ds != null) {
             updateSelection(ds.getAllSelected());
         }
-        MapView.addLayerChangeListener(this);
-        Layer activeLayer = Main.map.mapView.getActiveLayer();
-        if (activeLayer != null) {
-            activeLayerChange(null, activeLayer);
-        }
+        Main.getLayerManager().addAndFireActiveLayerChangeListener(this);
     }
 
     @Override
     public void hideNotify() {
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
         DataSet.removeSelectionListener(this);
     }
 
@@ -406,22 +401,12 @@ public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        if (newLayer instanceof OsmDataLayer) {
-            linkedLayer = (OsmDataLayer) newLayer;
-            tree.setErrorList(linkedLayer.validationErrors);
-        }
-    }
-
-    @Override
-    public void layerAdded(Layer newLayer) {
-        // Do nothing
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer == linkedLayer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        OsmDataLayer editLayer = e.getSource().getEditLayer();
+        if (editLayer == null) {
             tree.setErrorList(new ArrayList<TestError>());
+        } else {
+            tree.setErrorList(editLayer.validationErrors);
         }
     }
 
diff --git a/src/org/openstreetmap/josm/gui/dialogs/layer/ActivateLayerAction.java b/src/org/openstreetmap/josm/gui/dialogs/layer/ActivateLayerAction.java
index ad661ea..ddb5173 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/layer/ActivateLayerAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/layer/ActivateLayerAction.java
@@ -9,12 +9,12 @@ import java.util.List;
 
 import javax.swing.AbstractAction;
 
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel;
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -25,7 +25,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * The action to activate the currently selected layer
  */
 public final class ActivateLayerAction extends AbstractAction
-implements IEnabledStateUpdating, MapView.LayerChangeListener, MultikeyShortcutAction {
+implements IEnabledStateUpdating, ActiveLayerChangeListener, MultikeyShortcutAction {
     private transient Layer layer;
     private transient Shortcut multikeyShortcut;
     private final LayerListModel model;
@@ -76,14 +76,12 @@ implements IEnabledStateUpdating, MapView.LayerChangeListener, MultikeyShortcutA
 
     private void execute(Layer layer) {
         // model is going to be updated via LayerChangeListener and PropertyChangeEvents
-        Main.map.mapView.setActiveLayer(layer);
+        model.getLayerManager().setActiveLayer(layer);
         layer.setVisible(true);
     }
 
-    protected boolean isActiveLayer(Layer layer) {
-        if (!Main.isDisplayingMapView())
-            return false;
-        return Main.map.mapView.getActiveLayer() == layer;
+    boolean isActiveLayer(Layer layer) {
+        return model.getLayerManager().getActiveLayer() == layer;
     }
 
     @Override
@@ -105,17 +103,7 @@ implements IEnabledStateUpdating, MapView.LayerChangeListener, MultikeyShortcutA
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        updateEnabledState();
-    }
-
-    @Override
-    public void layerAdded(Layer newLayer) {
-        updateEnabledState();
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
         updateEnabledState();
     }
 
@@ -136,4 +124,5 @@ implements IEnabledStateUpdating, MapView.LayerChangeListener, MultikeyShortcutA
     public MultikeyInfo getLastMultikeyAction() {
         return null; // Repeating action doesn't make much sense for activating
     }
+
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java b/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
index 527a72a..001d244 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
@@ -617,9 +617,6 @@ implements SelectionChangedListener, ActiveLayerChangeListener, DataSetListenerA
     public void destroy() {
         super.destroy();
         Main.pref.removePreferenceChangeListener(this);
-        for (JosmAction action : josmActions) {
-            action.destroy();
-        }
         Container parent = pluginHook.getParent();
         if (parent != null) {
             parent.remove(pluginHook);
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java
index a2eb0a8..7f492f7 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java
@@ -10,16 +10,20 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.gui.MapView;
 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;
 
 /**
  * RelationDialogManager keeps track of the open relation editors.
  *
  */
-public class RelationDialogManager extends WindowAdapter implements MapView.LayerChangeListener {
+public class RelationDialogManager extends WindowAdapter implements LayerChangeListener {
 
     /** keeps track of open relation editors */
     private static RelationDialogManager relationDialogManager;
@@ -32,7 +36,7 @@ public class RelationDialogManager extends WindowAdapter implements MapView.Laye
     public static RelationDialogManager getRelationDialogManager() {
         if (RelationDialogManager.relationDialogManager == null) {
             RelationDialogManager.relationDialogManager = new RelationDialogManager();
-            MapView.addLayerChangeListener(RelationDialogManager.relationDialogManager);
+            Main.getLayerManager().addLayerChangeListener(RelationDialogManager.relationDialogManager);
         }
         return RelationDialogManager.relationDialogManager;
     }
@@ -166,12 +170,9 @@ public class RelationDialogManager extends WindowAdapter implements MapView.Laye
         return openDialogs.get(context);
     }
 
-    /**
-     * called when a layer is removed
-     *
-     */
     @Override
-    public void layerRemoved(Layer oldLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
+        Layer oldLayer = e.getRemovedLayer();
         if (!(oldLayer instanceof OsmDataLayer))
             return;
         OsmDataLayer dataLayer = (OsmDataLayer) oldLayer;
@@ -189,13 +190,13 @@ public class RelationDialogManager extends WindowAdapter implements MapView.Laye
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        // do nothing
+    public void layerAdded(LayerAddEvent e) {
+        // ignore
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        // do nothing
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // ignore
     }
 
     @Override
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableModel.java b/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableModel.java
index fe71e33..365e8ac 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableModel.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableModel.java
@@ -10,12 +10,16 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MapView;
-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.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
-public class SelectionTableModel extends AbstractTableModel implements SelectionChangedListener, MapView.LayerChangeListener {
+public class SelectionTableModel extends AbstractTableModel implements SelectionChangedListener, ActiveLayerChangeListener, LayerChangeListener {
 
     /** this selection table model only displays selected primitives in this layer */
     private final transient OsmDataLayer layer;
@@ -39,7 +43,7 @@ public class SelectionTableModel extends AbstractTableModel implements Selection
      */
     public void register() {
         DataSet.addSelectionListener(this);
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
     }
 
     /**
@@ -47,7 +51,7 @@ public class SelectionTableModel extends AbstractTableModel implements Selection
      */
     public void unregister() {
         DataSet.removeSelectionListener(this);
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
     }
 
     @Override
@@ -68,24 +72,24 @@ public class SelectionTableModel extends AbstractTableModel implements Selection
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        if (oldLayer  == layer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        if (e.getPreviousActiveLayer()  == layer) {
             cache.clear();
         }
-        if (newLayer == layer) {
-            cache.addAll(((OsmDataLayer) newLayer).data.getAllSelected());
+        if (e.getSource().getActiveLayer() == layer) {
+            cache.addAll(layer.data.getAllSelected());
         }
         fireTableDataChanged();
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
+    public void layerAdded(LayerAddEvent e) {
         // do nothing
     }
 
     @Override
-    public void layerRemoved(Layer oldLayer) {
-        if (oldLayer == layer) {
+    public void layerRemoving(LayerRemoveEvent e) {
+        if (e.getRemovedLayer() == layer) {
             unregister();
         }
         this.cache.clear();
@@ -93,6 +97,11 @@ public class SelectionTableModel extends AbstractTableModel implements Selection
     }
 
     @Override
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // do nothing
+    }
+
+    @Override
     public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
         if (layer == Main.main.getEditLayer()) {
             cache.clear();
@@ -127,4 +136,5 @@ public class SelectionTableModel extends AbstractTableModel implements Selection
     public OsmPrimitive getPrimitive(int row) {
         return cache.get(row);
     }
+
 }
diff --git a/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java b/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java
index 1aae5c4..73cdcfc 100644
--- a/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java
+++ b/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java
@@ -21,8 +21,10 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.data.osm.history.History;
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
-import org.openstreetmap.josm.gui.MapView;
-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.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 import org.openstreetmap.josm.tools.WindowGeometry;
@@ -32,7 +34,7 @@ import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
  * Manager allowing to show/hide history dialogs.
  * @since 2019
  */
-public final class HistoryBrowserDialogManager implements MapView.LayerChangeListener {
+public final class HistoryBrowserDialogManager implements LayerChangeListener {
 
     private static final String WINDOW_GEOMETRY_PREF = HistoryBrowserDialogManager.class.getName() + ".geometry";
 
@@ -53,7 +55,7 @@ public final class HistoryBrowserDialogManager implements MapView.LayerChangeLis
 
     protected HistoryBrowserDialogManager() {
         dialogs = new HashMap<>();
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
     }
 
     /**
@@ -152,23 +154,23 @@ public final class HistoryBrowserDialogManager implements MapView.LayerChangeLis
     /* LayerChangeListener                                                           */
     /* ----------------------------------------------------------------------------- */
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void layerAdded(LayerAddEvent e) {
         // Do nothing
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        // Do nothing
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
         // remove all history browsers if the number of layers drops to 0
-        if (Main.isDisplayingMapView() && Main.map.mapView.getNumLayers() == 0) {
+        if (e.getSource().getLayers().isEmpty()) {
             hideAll();
         }
     }
 
+    @Override
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // Do nothing
+    }
+
     /**
      * Show history dialog(s) for the given primitive(s).
      * @param primitives The primitive(s) for which history will be displayed
diff --git a/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java b/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
index 2b25290..ba4d0bd 100644
--- a/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
+++ b/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
@@ -40,9 +40,9 @@ import org.openstreetmap.josm.data.osm.history.HistoryRelation;
 import org.openstreetmap.josm.data.osm.history.HistoryWay;
 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.ChangeNotifier;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -73,7 +73,7 @@ import org.openstreetmap.josm.tools.date.DateUtils;
  *
  * @see HistoryBrowser
  */
-public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeListener, DataSetListener {
+public class HistoryBrowserModel extends ChangeNotifier implements ActiveLayerChangeListener, DataSetListener {
     /** the history of an OsmPrimitive */
     private History history;
     private HistoryOsmPrimitive reference;
@@ -110,7 +110,7 @@ public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeLi
                 editLayer.data.addDataSetListener(this);
             }
         }
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
     }
 
     /**
@@ -669,7 +669,7 @@ public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeLi
         if (editLayer != null) {
             editLayer.data.removeDataSetListener(this);
         }
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
     }
 
     /* ---------------------------------------------------------------------- */
@@ -746,14 +746,16 @@ public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeLi
     }
 
     /* ---------------------------------------------------------------------- */
-    /* LayerChangeListener                                                    */
+    /* ActiveLayerChangeListener                                              */
     /* ---------------------------------------------------------------------- */
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        Layer oldLayer = e.getPreviousActiveLayer();
         if (oldLayer instanceof OsmDataLayer) {
             OsmDataLayer l = (OsmDataLayer) oldLayer;
             l.data.removeDataSetListener(this);
         }
+        Layer newLayer = e.getSource().getActiveLayer();
         if (!(newLayer instanceof OsmDataLayer)) {
             latest = null;
             fireModelChange();
@@ -772,16 +774,6 @@ public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeLi
         fireModelChange();
     }
 
-    @Override
-    public void layerAdded(Layer newLayer) {
-        // Do nothing
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
-        // Do nothing
-    }
-
     /**
      * Creates a {@link HistoryOsmPrimitive} from a {@link OsmPrimitive}
      *
@@ -824,4 +816,5 @@ public class HistoryBrowserModel extends ChangeNotifier implements LayerChangeLi
             return clone;
         }
     }
+
 }
diff --git a/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java b/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
index 4b3a885..d475296 100644
--- a/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
+++ b/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
@@ -77,11 +77,14 @@ import org.openstreetmap.josm.data.preferences.IntegerProperty;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+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.progress.ProgressMonitor;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.io.WMSLayerImporter;
@@ -163,7 +166,6 @@ implements ImageObserver, TileLoaderListener, ZoomChangeListener {
         super(info);
         setBackgroundLayer(true);
         this.setVisible(true);
-        MapView.addZoomChangeListener(this);
     }
 
     protected abstract TileLoaderFactory getTileLoaderFactory();
@@ -625,29 +627,30 @@ implements ImageObserver, TileLoaderListener, ZoomChangeListener {
                 }
             }
         };
-        Main.map.mapView.addMouseListener(adapter);
+        Main.getLayerManager().addLayerChangeListener(new LayerChangeListener() {
 
-        MapView.addLayerChangeListener(new LayerChangeListener() {
             @Override
-            public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-                //
+            public void layerRemoving(LayerRemoveEvent e) {
+                if (e.getRemovedLayer() == AbstractTileSourceLayer.this) {
+                    Main.map.mapView.removeMouseListener(adapter);
+                    e.getSource().removeLayerChangeListener(this);
+                    MapView.removeZoomChangeListener(AbstractTileSourceLayer.this);
+                }
             }
 
             @Override
-            public void layerAdded(Layer newLayer) {
-                //
+            public void layerOrderChanged(LayerOrderChangeEvent e) {
+                // ignored
             }
 
             @Override
-            public void layerRemoved(Layer oldLayer) {
-                if (oldLayer == AbstractTileSourceLayer.this) {
-                    Main.map.mapView.removeMouseListener(adapter);
-                    MapView.removeLayerChangeListener(this);
-                    MapView.removeZoomChangeListener(AbstractTileSourceLayer.this);
+            public void layerAdded(LayerAddEvent e) {
+                if (e.getAddedLayer() == AbstractTileSourceLayer.this) {
+                    Main.map.mapView.addMouseListener(adapter);
+                    MapView.addZoomChangeListener(AbstractTileSourceLayer.this);
                 }
             }
         });
-
         // FIXME: why do we need this? Without this, if you add a WMS layer and do not move the mouse, sometimes, tiles do not
         // start loading.
         Main.map.repaint(500);
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
index 8a57ab9..f2a95b7 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
@@ -22,16 +22,20 @@ import javax.swing.JPanel;
 import javax.swing.JToggleButton;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.dialogs.DialogsPanel.Action;
 import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
 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.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.date.DateUtils;
 
-public final class ImageViewerDialog extends ToggleDialog implements LayerChangeListener {
+public final class ImageViewerDialog extends ToggleDialog implements LayerChangeListener, ActiveLayerChangeListener {
 
     private static final String COMMAND_ZOOM = "zoom";
     private static final String COMMAND_CENTERVIEW = "centre";
@@ -75,7 +79,8 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
         super(tr("Geotagged Images"), "geoimage", tr("Display geotagged images"), Shortcut.registerShortcut("tools:geotagged",
         tr("Tool: {0}", tr("Display geotagged images")), KeyEvent.VK_Y, Shortcut.DIRECT), 200);
         build();
-        MapView.addLayerChangeListener(this);
+        Main.getLayerManager().addActiveLayerChangeListener(this);
+        Main.getLayerManager().addLayerChangeListener(this);
     }
 
     protected void build() {
@@ -195,7 +200,8 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
 
     @Override
     public void destroy() {
-        MapView.removeLayerChangeListener(this);
+        Main.getLayerManager().removeActiveLayerChangeListener(this);
+        Main.getLayerManager().removeLayerChangeListener(this);
         super.destroy();
     }
 
@@ -409,28 +415,36 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        if (currentLayer == null && newLayer instanceof GeoImageLayer) {
-            ((GeoImageLayer) newLayer).showFirstPhoto();
-        }
+    public void layerAdded(LayerAddEvent e) {
+        showLayer(e.getAddedLayer());
     }
 
     @Override
-    public void layerAdded(Layer newLayer) {
-        if (currentLayer == null && newLayer instanceof GeoImageLayer) {
-            ((GeoImageLayer) newLayer).showFirstPhoto();
-        }
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
+    public void layerRemoving(LayerRemoveEvent e) {
         // Clear current image and layer if current layer is deleted
-        if (currentLayer != null && currentLayer.equals(oldLayer)) {
+        if (currentLayer != null && currentLayer.equals(e.getRemovedLayer())) {
             showImage(null, null);
         }
         // Check buttons state in case of layer merging
-        if (currentLayer != null && oldLayer instanceof GeoImageLayer) {
+        if (currentLayer != null && e.getRemovedLayer() instanceof GeoImageLayer) {
             currentLayer.checkPreviousNextButtons();
         }
     }
+
+    @Override
+    public void layerOrderChanged(LayerOrderChangeEvent e) {
+        // ignored
+    }
+
+    @Override
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        showLayer(e.getSource().getActiveLayer());
+    }
+
+    private void showLayer(Layer newLayer) {
+        if (currentLayer == null && newLayer instanceof GeoImageLayer) {
+            ((GeoImageLayer) newLayer).showFirstPhoto();
+        }
+    }
+
 }
diff --git a/src/org/openstreetmap/josm/io/FileExporter.java b/src/org/openstreetmap/josm/io/FileExporter.java
index 7191b92..fd8e09d 100644
--- a/src/org/openstreetmap/josm/io/FileExporter.java
+++ b/src/org/openstreetmap/josm/io/FileExporter.java
@@ -7,10 +7,11 @@ import java.io.File;
 import java.io.IOException;
 
 import org.openstreetmap.josm.actions.ExtensionFileFilter;
-import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 
-public abstract class FileExporter implements LayerChangeListener {
+public abstract class FileExporter implements ActiveLayerChangeListener {
 
     public final ExtensionFileFilter filter;
 
@@ -53,20 +54,10 @@ public abstract class FileExporter implements LayerChangeListener {
     }
 
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
         // To be overriden by subclasses if their enabled state depends of the active layer nature
     }
 
-    @Override
-    public void layerAdded(Layer newLayer) {
-        // To be overriden by subclasses if needed
-    }
-
-    @Override
-    public void layerRemoved(Layer oldLayer) {
-        // To be overriden by subclasses if needed
-    }
-
     /**
      * Determines if this exporter has been canceled during export.
      * @return true if this {@code FileExporter} has been canceled
diff --git a/src/org/openstreetmap/josm/io/WMSLayerExporter.java b/src/org/openstreetmap/josm/io/WMSLayerExporter.java
index 15e765a..ce0d46d 100644
--- a/src/org/openstreetmap/josm/io/WMSLayerExporter.java
+++ b/src/org/openstreetmap/josm/io/WMSLayerExporter.java
@@ -11,6 +11,7 @@ import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
 import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
@@ -46,8 +47,9 @@ public class WMSLayerExporter extends FileExporter {
 
     }
 
+
     @Override
-    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-        setEnabled(newLayer instanceof AbstractTileSourceLayer);
+    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+        setEnabled(e.getSource().getActiveLayer() instanceof AbstractTileSourceLayer);
     }
 }
