Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 15730)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 15731)
@@ -25,6 +25,4 @@
 import java.util.Collection;
 import java.util.List;
-import java.util.Map.Entry;
-import java.util.stream.Collectors;
 
 import javax.swing.AbstractAction;
@@ -63,8 +61,5 @@
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
-import org.openstreetmap.josm.gui.mappaint.StyleSetting;
-import org.openstreetmap.josm.gui.mappaint.StyleSetting.StyleSettingGroup;
 import org.openstreetmap.josm.gui.mappaint.StyleSettingGroupGui;
-import org.openstreetmap.josm.gui.mappaint.StyleSettingGuiFactory;
 import org.openstreetmap.josm.gui.mappaint.StyleSource;
 import org.openstreetmap.josm.gui.mappaint.loader.MapPaintStyleLoader;
@@ -694,14 +689,9 @@
             } else {
                 // Add settings groups
-                for (Entry<StyleSettingGroup, List<StyleSetting>> e : style.settingGroups.entrySet()) {
-                    new StyleSettingGroupGui(e.getKey(), e.getValue()).addMenuEntry(setMenu);
-                }
+                style.settingGroups.forEach((group, settings) -> new StyleSettingGroupGui(group, settings).addMenuEntry(setMenu));
                 // Add settings not in groups
-                final List<StyleSetting> allStylesInGroups = style.settingGroups.values().stream()
-                        .flatMap(List<StyleSetting>::stream).collect(Collectors.toList());
-                for (StyleSetting s : style.settings.stream()
-                        .filter(s -> !allStylesInGroups.contains(s)).collect(Collectors.toList())) {
-                    StyleSettingGuiFactory.getStyleSettingGui(s).addMenuEntry(setMenu);
-                }
+                style.settings.stream()
+                        .filter(s -> style.settingGroups.values().stream().flatMap(List::stream).noneMatch(s::equals))
+                        .forEach(s -> s.getStyleSettingGui().addMenuEntry(setMenu));
             }
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/PropertyStyleSettingGui.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/PropertyStyleSettingGui.java	(revision 15731)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/PropertyStyleSettingGui.java	(revision 15731)
@@ -0,0 +1,53 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import java.awt.event.ActionEvent;
+import java.util.Collections;
+import java.util.Objects;
+
+import javax.swing.AbstractAction;
+import javax.swing.JMenu;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.mappaint.StyleSetting.PropertyStyleSetting;
+import org.openstreetmap.josm.gui.mappaint.loader.MapPaintStyleLoader;
+
+/**
+ * GUI elements for a {@link PropertyStyleSetting} class.
+ * @since 15731
+ */
+class PropertyStyleSettingGui<T> implements StyleSettingGui {
+
+    private final PropertyStyleSetting<T> setting;
+
+    /**
+     * Constructs a new {@code BooleanStyleSettingGui}.
+     * @param setting boolean style setting
+     */
+    PropertyStyleSettingGui(PropertyStyleSetting<T> setting) {
+        this.setting = Objects.requireNonNull(setting);
+    }
+
+    class PropertyStyleSettingAction extends AbstractAction {
+
+        PropertyStyleSettingAction() {
+            super(setting.label);
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            final String initialValue = String.valueOf(setting.getValue());
+            final String userInput = JOptionPane.showInputDialog(setting.label, initialValue);
+            if (userInput != null && !initialValue.equals(userInput)) {
+                setting.setStringValue(userInput);
+                MainApplication.worker.submit(new MapPaintStyleLoader(Collections.singletonList(setting.parentStyle)));
+            }
+        }
+    }
+
+    @Override
+    public void addMenuEntry(JMenu menu) {
+        menu.add(new PropertyStyleSettingAction());
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingHelper.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingHelper.java	(revision 15730)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingHelper.java	(revision 15731)
@@ -121,15 +121,15 @@
                 }
                 for (String key : sd.settings.keySet()) {
-                    StyleSetting.BooleanStyleSetting match = source.settings.stream()
-                            .filter(s -> s instanceof StyleSetting.BooleanStyleSetting)
-                            .map(s -> (StyleSetting.BooleanStyleSetting) s)
-                            .filter(bs -> bs.prefKey.endsWith(":" + key))
+                    StyleSetting.PropertyStyleSetting<?> match = source.settings.stream()
+                            .filter(s -> s instanceof StyleSetting.PropertyStyleSetting)
+                            .map(s -> (StyleSetting.PropertyStyleSetting<?>) s)
+                            .filter(bs -> bs.getKey().endsWith(":" + key))
                             .findFirst().orElse(null);
                     if (match == null) {
                         Logging.warn(tr("Style setting not found: ''{0}''", key));
                     } else {
-                        boolean value = Boolean.parseBoolean(sd.settings.get(key));
+                        String value = sd.settings.get(key);
                         Logging.trace("setting applied: ''{0}:{1}''", key, value);
-                        match.setValue(value);
+                        match.setStringValue(value);
                     }
                 }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSetting.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSetting.java	(revision 15730)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSetting.java	(revision 15731)
@@ -7,5 +7,5 @@
 import javax.swing.Icon;
 
-import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.data.preferences.AbstractToStringProperty;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
@@ -39,4 +39,13 @@
      */
     Object getValue();
+
+    /**
+     * Create a matching {@link StyleSettingGui} instances for a given {@link StyleSetting} object.
+     * @return matching {@code StyleSettingGui}
+     * @throws UnsupportedOperationException when class of {@link StyleSetting} is not supported
+     */
+    default StyleSettingGui getStyleSettingGui() {
+        throw new UnsupportedOperationException(getClass() + " not supported");
+    }
 
     /**
@@ -84,5 +93,5 @@
         public final Icon icon;
 
-        public StyleSettingGroup(StyleSource parentStyle, String label, String key, Icon icon) {
+        StyleSettingGroup(StyleSource parentStyle, String label, String key, Icon icon) {
             super(parentStyle, label);
             this.key = Objects.requireNonNull(key);
@@ -100,5 +109,5 @@
             String label = c.get("label", null, String.class);
             if (label == null) {
-                Logging.warn("property 'label' required for boolean style setting");
+                Logging.warn("property 'label' required for StyleSettingGroup");
                 return null;
             }
@@ -109,56 +118,60 @@
     }
 
+    class PropertyStyleSetting<T> extends LabeledStyleSetting implements StyleSetting {
+        private final Class<T> type;
+        private final AbstractToStringProperty<T> property;
+
+        PropertyStyleSetting(StyleSource parentStyle, String label, Class<T> type, AbstractToStringProperty<T> property) {
+            super(parentStyle, label);
+            this.type = type;
+            this.property = property;
+        }
+
+        /**
+         * Replies the property key.
+         * @return The property key
+         */
+        public String getKey() {
+            return property.getKey();
+        }
+
+        @Override
+        public T getValue() {
+            return property.get();
+        }
+
+        /**
+         * Sets this property to the specified value.
+         * @param value The new value of this property
+         */
+        public void setValue(T value) {
+            property.put(value);
+        }
+
+        /**
+         * Sets this property to the specified string value.
+         * @param value The new string value of this property
+         */
+        public void setStringValue(String value) {
+            setValue(Cascade.convertTo(value, type));
+        }
+
+        @Override
+        public StyleSettingGui getStyleSettingGui() {
+            return new PropertyStyleSettingGui<>(this);
+        }
+    }
+
     /**
      * A style setting for boolean value (yes / no).
      */
-    class BooleanStyleSetting extends LabeledStyleSetting implements StyleSetting {
-        public final String prefKey;
-        public final boolean def;
-
-        public BooleanStyleSetting(StyleSource parentStyle, String prefKey, String label, boolean def) {
-            super(parentStyle, label);
-            this.prefKey = Objects.requireNonNull(prefKey);
-            this.def = def;
-        }
-
-        /**
-         * Creates a new {@code BooleanStyleSetting}.
-         * @param c cascade
-         * @param parentStyle parent style source
-         * @param key setting identifier
-         * @return newly created {@code BooleanStyleSetting}
-         */
-        public static BooleanStyleSetting create(Cascade c, StyleSource parentStyle, String key) {
-            String label = c.get("label", null, String.class);
-            if (label == null) {
-                Logging.warn("property 'label' required for boolean style setting");
-                return null;
-            }
-            Boolean def = c.get("default", null, Boolean.class);
-            if (def == null) {
-                Logging.warn("property 'default' required for boolean style setting");
-                return null;
-            }
-            String prefKey = parentStyle.url + ":boolean:" + key;
-            return new BooleanStyleSetting(parentStyle, prefKey, label, def);
+    class BooleanStyleSetting extends PropertyStyleSetting<Boolean> {
+        BooleanStyleSetting(StyleSource parentStyle, String label, AbstractToStringProperty<Boolean> property) {
+            super(parentStyle, label, Boolean.class, property);
         }
 
         @Override
-        public Object getValue() {
-            String val = Config.getPref().get(prefKey, null);
-            if (val == null) return def;
-            return Boolean.valueOf(val);
-        }
-
-        public void setValue(Object o) {
-            if (!(o instanceof Boolean)) {
-                throw new IllegalArgumentException();
-            }
-            boolean b = (Boolean) o;
-            if (b == def) {
-                Config.getPref().put(prefKey, null);
-            } else {
-                Config.getPref().putBoolean(prefKey, b);
-            }
+        public StyleSettingGui getStyleSettingGui() {
+            return new BooleanStyleSettingGui(this);
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingFactory.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingFactory.java	(revision 15731)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingFactory.java	(revision 15731)
@@ -0,0 +1,67 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import java.util.function.BiFunction;
+
+import org.openstreetmap.josm.data.preferences.BooleanProperty;
+import org.openstreetmap.josm.data.preferences.DoubleProperty;
+import org.openstreetmap.josm.data.preferences.StringProperty;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Factory to create matching {@link StyleSetting} instances.
+ * @since 15731
+ */
+public final class StyleSettingFactory {
+
+    private StyleSettingFactory() {
+        // private constructor for factory classes
+    }
+
+    /**
+     * Creates a new {@code StyleSetting} based on the specified type by {@code c}.
+     * The type must be supported by {@link Cascade#convertTo} as well as {@link org.openstreetmap.josm.data.preferences.AbstractProperty}.
+     * @param c cascade
+     * @param parentStyle parent style source
+     * @param key setting identifier
+     * @return newly created {@code StyleSetting}
+     */
+    public static StyleSetting create(Cascade c, StyleSource parentStyle, String key) {
+        final String type = c.get("type", null, String.class);
+        final String qualifiedKey = String.join(":", parentStyle.url, type, key);
+        switch (type) {
+            case "boolean":
+                return forLabelAndDefault(c, Boolean.class, (label, defaultValue) -> {
+                    final BooleanProperty property = new BooleanProperty(qualifiedKey, defaultValue);
+                    return new StyleSetting.BooleanStyleSetting(parentStyle, label, property);
+                });
+            case "double":
+                return forLabelAndDefault(c, Double.class, (label, defaultValue) -> {
+                    final DoubleProperty property = new DoubleProperty(qualifiedKey, defaultValue);
+                    return new StyleSetting.PropertyStyleSetting<>(parentStyle, label, Double.class, property);
+                });
+            case "string":
+                return forLabelAndDefault(c, String.class, (label, defaultValue) -> {
+                    final StringProperty property = new StringProperty(qualifiedKey, defaultValue);
+                    return new StyleSetting.PropertyStyleSetting<>(parentStyle, label, String.class, property);
+                });
+            default:
+                Logging.warn("Unknown setting type {0} for style {1}", type, parentStyle.url);
+                return null;
+        }
+    }
+
+    private static <T> StyleSetting forLabelAndDefault(Cascade c, final Class<T> type, BiFunction<String, T, StyleSetting> function) {
+        String label = c.get("label", null, String.class);
+        if (label == null) {
+            Logging.warn("property 'label' required for style setting of type " + type);
+            return null;
+        }
+        T defaultValue = c.get("default", null, type);
+        if (defaultValue == null) {
+            Logging.warn("property 'default' required for style setting of type " + type);
+            return null;
+        }
+        return function.apply(label, defaultValue);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingGroupGui.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingGroupGui.java	(revision 15730)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingGroupGui.java	(revision 15731)
@@ -64,5 +64,5 @@
         // Add individual settings
         for (StyleSetting s : settings) {
-            StyleSettingGuiFactory.getStyleSettingGui(s).addMenuEntry(submenu);
+            s.getStyleSettingGui().addMenuEntry(submenu);
         }
         menu.add(submenu);
Index: unk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingGuiFactory.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSettingGuiFactory.java	(revision 15730)
+++ 	(revision )
@@ -1,32 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.mappaint;
-
-import org.openstreetmap.josm.gui.mappaint.StyleSetting.BooleanStyleSetting;
-
-/**
- * Factory to create matching {@link StyleSettingGui} instances for given
- * {@link StyleSetting} objects.
- * @since 12831
- */
-public final class StyleSettingGuiFactory {
-
-    private StyleSettingGuiFactory() {
-        // hide constructor
-    }
-
-    /**
-     * Create a matching {@link StyleSettingGui} instances for a given
-     * {@link StyleSetting} object.
-     * @param setting the {@code StyleSetting} object
-     * @return matching {@code StyleSettingGui}
-     * @throws UnsupportedOperationException when class of {@link StyleSetting}
-     * is not supported
-     */
-    public static StyleSettingGui getStyleSettingGui(StyleSetting setting) {
-        if (setting instanceof BooleanStyleSetting) {
-            return new BooleanStyleSettingGui((BooleanStyleSetting) setting);
-        }
-        throw new UnsupportedOperationException("class " + setting.getClass() + " not supported");
-    }
-
-}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 15730)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 15731)
@@ -49,6 +49,6 @@
 import org.openstreetmap.josm.gui.mappaint.StyleKeys;
 import org.openstreetmap.josm.gui.mappaint.StyleSetting;
-import org.openstreetmap.josm.gui.mappaint.StyleSetting.BooleanStyleSetting;
 import org.openstreetmap.josm.gui.mappaint.StyleSetting.StyleSettingGroup;
+import org.openstreetmap.josm.gui.mappaint.StyleSettingFactory;
 import org.openstreetmap.josm.gui.mappaint.StyleSource;
 import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyCondition;
@@ -624,11 +624,5 @@
             }
             Cascade c = e.getValue();
-            String type = c.get("type", null, String.class);
-            StyleSetting set = null;
-            if ("boolean".equals(type)) {
-                set = BooleanStyleSetting.create(c, this, e.getKey());
-            } else {
-                Logging.warn("Unknown setting type: {0}", type);
-            }
+            StyleSetting set = StyleSettingFactory.create(c, this, e.getKey());
             if (set != null) {
                 settings.add(set);
@@ -636,6 +630,9 @@
                 String groupId = c.get("group", null, String.class);
                 if (groupId != null) {
-                    settingGroups.get(settingGroups.keySet().stream().filter(g -> g.key.equals(groupId)).findAny()
-                            .orElseThrow(() -> new IllegalArgumentException("Unknown settings group: " + groupId))).add(set);
+                    final StyleSettingGroup group = settingGroups.keySet().stream()
+                            .filter(g -> g.key.equals(groupId))
+                            .findAny()
+                            .orElseThrow(() -> new IllegalArgumentException("Unknown settings group: " + groupId));
+                    settingGroups.get(group).add(set);
                 }
             }
Index: /trunk/test/performance/org/openstreetmap/josm/gui/mappaint/MapRendererPerformanceTest.java
===================================================================
--- /trunk/test/performance/org/openstreetmap/josm/gui/mappaint/MapRendererPerformanceTest.java	(revision 15730)
+++ /trunk/test/performance/org/openstreetmap/josm/gui/mappaint/MapRendererPerformanceTest.java	(revision 15731)
@@ -19,4 +19,5 @@
 import javax.imageio.ImageIO;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.junit.AfterClass;
 import org.junit.Assert;
@@ -48,6 +49,4 @@
 import org.openstreetmap.josm.tools.Logging;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
 /**
  * Performance test of map renderer.
@@ -117,5 +116,5 @@
         for (StyleSetting set : filterStyle.settings) {
             BooleanStyleSetting bset = (BooleanStyleSetting) set;
-            String prefKey = bset.prefKey;
+            String prefKey = bset.getKey();
             boolean found = false;
             for (Feature f : Feature.values()) {
@@ -143,5 +142,5 @@
             if (set instanceof BooleanStyleSetting) {
                 BooleanStyleSetting bset = (BooleanStyleSetting) set;
-                if (bset.prefKey.endsWith(":hide_icons")) {
+                if (bset.getKey().endsWith(":hide_icons")) {
                     hideIconsSetting = bset;
                 }
