Index: trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java	(revision 12391)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java	(revision 12392)
@@ -16,4 +16,5 @@
 import javax.swing.ImageIcon;
 import javax.swing.JCheckBox;
+import javax.swing.JComponent;
 import javax.swing.JLabel;
 import javax.swing.JMenuItem;
@@ -51,7 +52,10 @@
     private final JPopupMenu popup;
     private SideButton sideButton;
-    private final JCheckBox visibilityCheckbox;
+    /**
+     * The real content, just to add a border
+     */
+    private final JPanel content = new JPanel();
     final OpacitySlider opacitySlider = new OpacitySlider();
-    private final ArrayList<FilterSlider<?>> sliders = new ArrayList<>();
+    private final ArrayList<LayerVisibilityMenuEntry> sliders = new ArrayList<>();
 
     /**
@@ -65,6 +69,4 @@
         popup.addMouseWheelListener(MouseWheelEvent::consume);
 
-        // just to add a border
-        JPanel content = new JPanel();
         popup.add(content);
         content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
@@ -74,23 +76,14 @@
         putValue(SHORT_DESCRIPTION, tr("Change visibility of the selected layer."));
 
-        visibilityCheckbox = new JCheckBox(tr("Show layer"));
-        visibilityCheckbox.addChangeListener(e -> setVisibleFlag(visibilityCheckbox.isSelected()));
-        content.add(visibilityCheckbox, GBC.eop());
-
-        addSlider(content, opacitySlider);
-        addSlider(content, new ColorfulnessSlider());
-        addSlider(content, new GammaFilterSlider());
-        addSlider(content, new SharpnessSlider());
-    }
-
-    private void addSlider(JPanel content, FilterSlider<?> slider) {
-        // wrap to a common content pane to allow for mouse wheel listener on label.
-        JPanel container = new JPanel(new GridBagLayout());
-        container.add(new JLabel(slider.getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0));
-        container.add(new JLabel(slider.getLabel()), GBC.eol());
-        container.add(slider, GBC.eol());
-        content.add(container, GBC.eop());
-
-        container.addMouseWheelListener(slider::mouseWheelMoved);
+        addContentEntry(new VisibilityCheckbox());
+
+        addContentEntry(opacitySlider);
+        addContentEntry(new ColorfulnessSlider());
+        addContentEntry(new GammaFilterSlider());
+        addContentEntry(new SharpnessSlider());
+    }
+
+    private void addContentEntry(LayerVisibilityMenuEntry slider) {
+        content.add(slider.getPanel(), GBC.eop());
         sliders.add(slider);
     }
@@ -118,5 +111,4 @@
         List<Layer> layers = model.getSelectedLayers();
 
-        visibilityCheckbox.setEnabled(!layers.isEmpty());
         boolean allVisible = true;
         boolean allHidden = true;
@@ -125,9 +117,7 @@
             allHidden &= !l.isVisible();
         }
-        // TODO: Indicate tristate.
-        visibilityCheckbox.setSelected(allVisible && !allHidden);
-
-        for (FilterSlider<?> slider : sliders) {
-            slider.updateSlider(layers, allHidden);
+
+        for (LayerVisibilityMenuEntry slider : sliders) {
+            slider.updateLayers(layers, allVisible, allHidden);
         }
     }
@@ -154,4 +144,45 @@
     public void setCorrespondingSideButton(SideButton sideButton) {
         this.sideButton = sideButton;
+    }
+
+    /**
+     * An entry in the visibility settings dropdown.
+     * @author Michael Zangl
+     */
+    private interface LayerVisibilityMenuEntry {
+
+        /**
+         * Update the displayed value depending on the current layers
+         * @param layers The layers
+         * @param allVisible <code>true</code> if all layers are visible
+         * @param allHidden <code>true</code> if all layers are hidden
+         */
+        void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden);
+
+        /**
+         * Get the panel that should be added to the menu
+         * @return The panel
+         */
+        JComponent getPanel();
+    }
+
+    private class VisibilityCheckbox extends JCheckBox implements LayerVisibilityMenuEntry {
+
+        VisibilityCheckbox() {
+            super(tr("Show layer"));
+            addChangeListener(e -> setVisibleFlag(isSelected()));
+        }
+
+        @Override
+        public void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden) {
+            setEnabled(!layers.isEmpty());
+            // TODO: Indicate tristate.
+            setSelected(allVisible && !allHidden);
+        }
+
+        @Override
+        public JComponent getPanel() {
+            return this;
+        }
     }
 
@@ -162,8 +193,10 @@
      * @param <T> The layer type.
      */
-    private abstract class FilterSlider<T extends Layer> extends JSlider {
+    private abstract class AbstractFilterSlider<T extends Layer> extends JPanel implements LayerVisibilityMenuEntry {
         private final double minValue;
         private final double maxValue;
         private final Class<T> layerClassFilter;
+
+        protected final JSlider slider = new JSlider(JSlider.HORIZONTAL);
 
         /**
@@ -173,21 +206,27 @@
          * @param layerClassFilter The type of layer influenced by this filter.
          */
-        FilterSlider(double minValue, double maxValue, Class<T> layerClassFilter) {
-            super(JSlider.HORIZONTAL);
+        AbstractFilterSlider(double minValue, double maxValue, Class<T> layerClassFilter) {
+            super(new GridBagLayout());
             this.minValue = minValue;
             this.maxValue = maxValue;
             this.layerClassFilter = layerClassFilter;
-            setMaximum(SLIDER_STEPS);
+
+            add(new JLabel(getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0));
+            add(new JLabel(getLabel()), GBC.eol());
+            add(slider, GBC.eol());
+            addMouseWheelListener(this::mouseWheelMoved);
+
+            slider.setMaximum(SLIDER_STEPS);
             int tick = convertFromRealValue(1);
-            setMinorTickSpacing(tick);
-            setMajorTickSpacing(tick);
-            setPaintTicks(true);
-
-            addChangeListener(e -> onStateChanged());
+            slider.setMinorTickSpacing(tick);
+            slider.setMajorTickSpacing(tick);
+            slider.setPaintTicks(true);
+
+            slider.addChangeListener(e -> onStateChanged());
         }
 
         /**
          * Called whenever the state of the slider was changed.
-         * @see #getValueIsAdjusting()
+         * @see JSlider#getValueIsAdjusting()
          * @see #getRealValue()
          */
@@ -206,5 +245,5 @@
             }
             double rotation = -1 * e.getPreciseWheelRotation();
-            double destinationValue = getValue() + rotation * SLIDER_WHEEL_INCREMENT;
+            double destinationValue = slider.getValue() + rotation * SLIDER_WHEEL_INCREMENT;
             if (rotation < 0) {
                 destinationValue = Math.floor(destinationValue);
@@ -212,5 +251,5 @@
                 destinationValue = Math.ceil(destinationValue);
             }
-            setValue(Utils.clamp((int) destinationValue, getMinimum(), getMaximum()));
+            slider.setValue(Utils.clamp((int) destinationValue, slider.getMinimum(), slider.getMaximum()));
         }
 
@@ -218,5 +257,5 @@
 
         protected double getRealValue() {
-            return convertToRealValue(getValue());
+            return convertToRealValue(slider.getValue());
         }
 
@@ -227,10 +266,10 @@
 
         protected void setRealValue(double value) {
-            setValue(convertFromRealValue(value));
+            slider.setValue(convertFromRealValue(value));
         }
 
         protected int convertFromRealValue(double value) {
             int i = (int) ((value - minValue) / (maxValue - minValue) * SLIDER_STEPS + .5);
-            return Utils.clamp(i, getMinimum(), getMaximum());
+            return Utils.clamp(i, slider.getMinimum(), slider.getMaximum());
         }
 
@@ -239,10 +278,11 @@
         public abstract String getLabel();
 
-        public void updateSlider(List<Layer> layers, boolean allHidden) {
+        @Override
+        public void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden) {
             Collection<? extends Layer> usedLayers = filterLayers(layers);
-            if (usedLayers.isEmpty() || allHidden) {
-                setEnabled(false);
+            if (!usedLayers.stream().anyMatch(Layer::isVisible)) {
+                slider.setEnabled(false);
             } else {
-                setEnabled(true);
+                slider.setEnabled(true);
                 updateSliderWhileEnabled(usedLayers, allHidden);
             }
@@ -254,4 +294,9 @@
 
         protected abstract void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden);
+
+        @Override
+        public JComponent getPanel() {
+            return this;
+        }
     }
 
@@ -262,5 +307,5 @@
      * @see Layer#setOpacity(double)
      */
-    class OpacitySlider extends FilterSlider<Layer> {
+    class OpacitySlider extends AbstractFilterSlider<Layer> {
         /**
          * Creaate a new {@link OpacitySlider}.
@@ -268,10 +313,10 @@
         OpacitySlider() {
             super(0, 1, Layer.class);
-            setToolTipText(tr("Adjust opacity of the layer."));
+            slider.setToolTipText(tr("Adjust opacity of the layer."));
         }
 
         @Override
         protected void onStateChanged() {
-            if (getRealValue() <= 0.001 && !getValueIsAdjusting()) {
+            if (getRealValue() <= 0.001 && !slider.getValueIsAdjusting()) {
                 setVisibleFlag(false);
             } else {
@@ -333,5 +378,5 @@
      * @see ImageryFilterSettings#setGamma(double)
      */
-    private class GammaFilterSlider extends FilterSlider<ImageryLayer> {
+    private class GammaFilterSlider extends AbstractFilterSlider<ImageryLayer> {
 
         /**
@@ -340,5 +385,5 @@
         GammaFilterSlider() {
             super(-1, 1, ImageryLayer.class);
-            setToolTipText(tr("Adjust gamma value of the layer."));
+            slider.setToolTipText(tr("Adjust gamma value of the layer."));
         }
 
@@ -392,5 +437,5 @@
      * @see ImageryFilterSettings#setSharpenLevel(double)
      */
-    private class SharpnessSlider extends FilterSlider<ImageryLayer> {
+    private class SharpnessSlider extends AbstractFilterSlider<ImageryLayer> {
 
         /**
@@ -399,5 +444,5 @@
         SharpnessSlider() {
             super(0, MAX_SHARPNESS_FACTOR, ImageryLayer.class);
-            setToolTipText(tr("Adjust sharpness/blur value of the layer."));
+            slider.setToolTipText(tr("Adjust sharpness/blur value of the layer."));
         }
 
@@ -429,5 +474,5 @@
      * @see ImageryFilterSettings#setColorfulness(double)
      */
-    private class ColorfulnessSlider extends FilterSlider<ImageryLayer> {
+    private class ColorfulnessSlider extends AbstractFilterSlider<ImageryLayer> {
 
         /**
@@ -436,5 +481,5 @@
         ColorfulnessSlider() {
             super(0, MAX_COLORFUL_FACTOR, ImageryLayer.class);
-            setToolTipText(tr("Adjust colorfulness of the layer."));
+            slider.setToolTipText(tr("Adjust colorfulness of the layer."));
         }
 
