diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
index 83e9b36..f509eac 100644
--- a/src/org/openstreetmap/josm/gui/MapView.java
+++ b/src/org/openstreetmap/josm/gui/MapView.java
@@ -57,9 +57,10 @@ import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.ImageryLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerPositionStrategy;
 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 import org.openstreetmap.josm.gui.layer.markerlayer.PlayHeadMarker;
@@ -346,33 +347,6 @@ implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer
     }
 
     /**
-     * Adds a GPX layer. A GPX layer is added below the lowest data layer.
-     * <p>
-     * Does not call {@link #fireLayerAdded(Layer)}.
-     *
-     * @param layer the GPX layer
-     */
-    protected void addGpxLayer(GpxLayer layer) {
-        synchronized (layers) {
-            if (layers.isEmpty()) {
-                layers.add(layer);
-                return;
-            }
-            for (int i = layers.size()-1; i >= 0; i--) {
-                if (layers.get(i) instanceof OsmDataLayer) {
-                    if (i == layers.size()-1) {
-                        layers.add(layer);
-                    } else {
-                        layers.add(i+1, layer);
-                    }
-                    return;
-                }
-            }
-            layers.add(0, layer);
-        }
-    }
-
-    /**
      * Add a layer to the current MapView. The layer will be added at topmost
      * position.
      * @param layer The layer to add
@@ -388,21 +362,10 @@ implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer
                 playHeadMarker = PlayHeadMarker.create();
             }
 
-            if (layer instanceof GpxLayer) {
-                addGpxLayer((GpxLayer) layer);
-            } else if (layers.isEmpty()) {
-                layers.add(layer);
-            } else if (layer.isBackgroundLayer()) {
-                int i = 0;
-                for (; i < layers.size(); i++) {
-                    if (layers.get(i).isBackgroundLayer()) {
-                        break;
-                    }
-                }
-                layers.add(i, layer);
-            } else {
-                layers.add(0, layer);
-            }
+            LayerPositionStrategy positionStrategy = layer.getDefaultLayerPosition();
+            int position = positionStrategy.getPosition(this);
+            checkPosition(position);
+            insertLayerAt(layer, position);
 
             if (isOsmDataLayer || oldActiveLayer == null) {
                 // autoselect the new layer
@@ -429,6 +392,30 @@ implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer
         }
     }
 
+    /**
+     * Check if the (new) position is valid
+     * @param position The position index
+     * @throws IndexOutOfBoundsException if it is not.
+     */
+    private void checkPosition(int position) {
+        if (position < 0 || position > layers.size()) {
+            throw new IndexOutOfBoundsException("Position " + position + " out of range.");
+        }
+    }
+
+    /**
+     * Insert a layer at a given position.
+     * @param layer The layer to add.
+     * @param position The position on which we should add it.
+     */
+    private void insertLayerAt(Layer layer, int position) {
+        if (position == layers.size()) {
+            layers.add(layer);
+        } else {
+            layers.add(position, layer);
+        }
+    }
+
     @Override
     protected DataSet getCurrentDataSet() {
         synchronized (layers) {
diff --git a/src/org/openstreetmap/josm/gui/layer/GpxLayer.java b/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
index 6bdf88a..4e4fde2 100644
--- a/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
+++ b/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
@@ -384,4 +384,8 @@ public class GpxLayer extends Layer {
         return SaveActionBase.createAndOpenSaveFileChooser(tr("Save GPX file"), GpxImporter.getFileFilter());
     }
 
+    @Override
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        return LayerPositionStrategy.AFTER_LAST_DATA_LAYER;
+    }
 }
diff --git a/src/org/openstreetmap/josm/gui/layer/Layer.java b/src/org/openstreetmap/josm/gui/layer/Layer.java
index 26842aa..0a5fcb5 100644
--- a/src/org/openstreetmap/josm/gui/layer/Layer.java
+++ b/src/org/openstreetmap/josm/gui/layer/Layer.java
@@ -580,4 +580,16 @@ public abstract class Layer implements Destroyable, MapViewPaintable, Projection
     protected long estimateMemoryUsage() {
         return 0;
     }
+
+    /**
+     * Gets the strategy that specifies where this layer should be inserted in a layer list.
+     * @return That strategy.
+     */
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        if (isBackgroundLayer()) {
+            return LayerPositionStrategy.BEFORE_FIRST_BACKGROUND_LAYER;
+        } else {
+            return LayerPositionStrategy.AFTER_LAST_VALIDATION_LAYER;
+        }
+    }
 }
diff --git a/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java b/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java
new file mode 100644
index 0000000..6aa94c4
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java
@@ -0,0 +1,111 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.layer;
+
+import java.util.List;
+
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.tools.Predicate;
+import org.openstreetmap.josm.tools.Predicates;
+
+/**
+ * This class defines a position to insert a given layer in the list of layers.
+ * @author Michael Zangl
+ */
+public abstract class LayerPositionStrategy {
+
+    /**
+     * always inserts at the front of the stack.
+     */
+    public static final LayerPositionStrategy IN_FRONT = new LayerPositionStrategy() {
+        @Override
+        public int getPosition(MapView manager) {
+            return 0;
+        }
+    };
+
+    /**
+     * A GPX layer is added below the lowest data layer.
+     */
+    public static final LayerPositionStrategy AFTER_LAST_DATA_LAYER = afterLast(new Predicate<Layer>() {
+        @Override
+        public boolean evaluate(Layer object) {
+            return object instanceof OsmDataLayer || object instanceof ValidatorLayer;
+        };
+    });
+
+    /**
+     * A normal layer is added after all validation layers.
+     */
+    public static final LayerPositionStrategy AFTER_LAST_VALIDATION_LAYER = afterLast(new Predicate<Layer>() {
+        @Override
+        public boolean evaluate(Layer object) {
+            return object instanceof ValidatorLayer;
+        };
+    });
+
+    /**
+     * The default for background layers: They are added before the first background layer in the list. If there is n one, they are added at the end of the list.
+     */
+    public static final LayerPositionStrategy BEFORE_FIRST_BACKGROUND_LAYER = inFrontOfFirst(new Predicate<Layer>() {
+        @Override
+        public boolean evaluate(Layer object) {
+            return object.isBackgroundLayer();
+        }
+    });
+
+    /**
+     * Gets a {@link LayerPositionStrategy} that inserts this layer in front of a given layer
+     * @param other The layer before which to insert this layer
+     * @return The strategy
+     */
+    public static LayerPositionStrategy inFrontOf(Layer other) {
+        return inFrontOfFirst(Predicates.equalTo(other));
+    }
+
+    /**
+     * Gets a {@link LayerPositionStrategy} that inserts the layer in front of the first layer that matches a condition.
+     * @param what The condition to match.
+     * @return The strategy.
+     */
+    public static LayerPositionStrategy inFrontOfFirst(final Predicate<Layer> what) {
+        return new LayerPositionStrategy() {
+            @Override
+            public int getPosition(MapView manager) {
+                List<Layer> layers = manager.getAllLayersAsList();
+                for (int i = 0; i < layers.size(); i++) {
+                    if (what.evaluate(layers.get(i))) {
+                        return i;
+                    }
+                }
+                return layers.size();
+            }
+        };
+    }
+
+    /**
+     * Creates a strategy that places the layer after the last layer of a given kind or at the beginning of the list if no such layer exists.
+     * @param what what to search for
+     * @return The strategy.
+     */
+    public static LayerPositionStrategy afterLast(final Predicate<Layer> what) {
+        return new LayerPositionStrategy() {
+            @Override
+            public int getPosition(MapView manager) {
+                List<Layer> layers = manager.getAllLayersAsList();
+                for (int i = layers.size() - 1; i >= 0; i--) {
+                    if (what.evaluate(layers.get(i))) {
+                        return i + 1;
+                    }
+                }
+                return 0;
+            }
+        };
+    }
+
+    /**
+     * Gets the position where the layer should be inserted
+     * @param manager The layer manager to insert the layer in.
+     * @return The position in the range 0...layers.size
+     */
+    public abstract int getPosition(MapView manager);
+}
diff --git a/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java b/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java
index 1f0c0be..82c57d6 100644
--- a/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java
+++ b/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java
@@ -159,4 +159,9 @@ public class ValidatorLayer extends Layer implements LayerChangeListener {
             OsmValidator.errorLayer = null;
         }
     }
+
+    @Override
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        return LayerPositionStrategy.IN_FRONT;
+    }
 }
