001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.mappaint; 003 004import java.awt.Color; 005import java.util.function.BiFunction; 006 007import org.openstreetmap.josm.data.preferences.BooleanProperty; 008import org.openstreetmap.josm.data.preferences.DoubleProperty; 009import org.openstreetmap.josm.data.preferences.NamedColorProperty; 010import org.openstreetmap.josm.data.preferences.StringProperty; 011import org.openstreetmap.josm.tools.Logging; 012 013/** 014 * Factory to create matching {@link StyleSetting} instances. 015 * @since 15731 016 */ 017public final class StyleSettingFactory { 018 019 private StyleSettingFactory() { 020 // private constructor for factory classes 021 } 022 023 /** 024 * Creates a new {@code StyleSetting} based on the specified type by {@code c}. 025 * The type must be supported by {@link Cascade#convertTo} as well as {@link org.openstreetmap.josm.data.preferences.AbstractProperty}. 026 * @param c cascade 027 * @param parentStyle parent style source 028 * @param key setting identifier 029 * @return newly created {@code StyleSetting} 030 */ 031 public static StyleSetting create(Cascade c, StyleSource parentStyle, String key) { 032 final String type = c.get("type", null, String.class); 033 final String qualifiedKey = String.join(":", parentStyle.url, type, key); 034 switch (type) { 035 case "boolean": 036 return forLabelAndDefault(c, Boolean.class, (label, defaultValue) -> { 037 final BooleanProperty property = new BooleanProperty(qualifiedKey, defaultValue); 038 return new StyleSetting.BooleanStyleSetting(parentStyle, label, property); 039 }); 040 case "double": 041 return forLabelAndDefault(c, Double.class, (label, defaultValue) -> { 042 final DoubleProperty property = new DoubleProperty(qualifiedKey, defaultValue); 043 return new StyleSetting.PropertyStyleSetting<>(parentStyle, label, Double.class, property); 044 }); 045 case "string": 046 return forLabelAndDefault(c, String.class, (label, defaultValue) -> { 047 final StringProperty property = new StringProperty(qualifiedKey, defaultValue); 048 return new StyleSetting.PropertyStyleSetting<>(parentStyle, label, String.class, property); 049 }); 050 case "color": 051 return forLabelAndDefault(c, Color.class, (label, defaultValue) -> { 052 final NamedColorProperty property = new NamedColorProperty(NamedColorProperty.COLOR_CATEGORY_MAPPAINT, 053 parentStyle.title == null ? "MapCSS" : parentStyle.title, label, defaultValue); 054 return new StyleSetting.ColorStyleSetting(parentStyle, label, property); 055 }); 056 default: 057 Logging.warn("Unknown setting type {0} for style {1}", type, parentStyle.url); 058 return null; 059 } 060 } 061 062 private static <T> StyleSetting forLabelAndDefault(Cascade c, final Class<T> type, BiFunction<String, T, StyleSetting> function) { 063 String label = c.get("label", null, String.class); 064 if (label == null) { 065 Logging.warn("property 'label' required for style setting of type " + type); 066 return null; 067 } 068 T defaultValue = c.get("default", null, type); 069 if (defaultValue == null) { 070 Logging.warn("property 'default' required for style setting of type " + type); 071 return null; 072 } 073 return function.apply(label, defaultValue); 074 } 075}