Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 10007)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 10008)
@@ -58,7 +58,8 @@
 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.NativeScaleLayer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
@@ -347,31 +348,4 @@
 
     /**
-     * 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.
@@ -389,19 +363,8 @@
             }
 
-            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) {
@@ -427,4 +390,28 @@
         if (!listenersToFire.isEmpty()) {
             repaint();
+        }
+    }
+
+    /**
+     * 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);
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 10007)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 10008)
@@ -385,3 +385,7 @@
     }
 
+    @Override
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        return LayerPositionStrategy.AFTER_LAST_DATA_LAYER;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 10007)
+++ trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 10008)
@@ -581,3 +581,16 @@
         return 0;
     }
+
+    /**
+     * Gets the strategy that specifies where this layer should be inserted in a layer list.
+     * @return That strategy.
+     * @since 10008
+     */
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        if (isBackgroundLayer()) {
+            return LayerPositionStrategy.BEFORE_FIRST_BACKGROUND_LAYER;
+        } else {
+            return LayerPositionStrategy.AFTER_LAST_VALIDATION_LAYER;
+        }
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java	(revision 10008)
+++ trunk/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java	(revision 10008)
@@ -0,0 +1,113 @@
+// 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
+ * @since 10008
+ */
+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 none, 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);
+}
Index: trunk/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java	(revision 10007)
+++ trunk/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java	(revision 10008)
@@ -160,3 +160,8 @@
         }
     }
+
+    @Override
+    public LayerPositionStrategy getDefaultLayerPosition() {
+        return LayerPositionStrategy.IN_FRONT;
+    }
 }
