001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.preferences;
003
004import java.awt.Color;
005import java.util.Arrays;
006import java.util.List;
007
008import org.openstreetmap.josm.tools.CheckParameterUtil;
009import org.openstreetmap.josm.tools.ColorHelper;
010
011/**
012 * A property containing a {@link Color} value with additional information associated to it.
013 *
014 * The additional information is used to describe the color in the
015 * {@link org.openstreetmap.josm.gui.preferences.display.ColorPreference}, so it can be recognized
016 * and customized by the user.
017 * @since 12987
018 */
019public class NamedColorProperty extends AbstractProperty<Color> {
020
021    public static final String NAMED_COLOR_PREFIX = "clr.";
022
023    public static final String COLOR_CATEGORY_GENERAL = "general";
024    public static final String COLOR_CATEGORY_MAPPAINT = "mappaint";
025
026    private final String category;
027    private final String source;
028    private final String name;
029
030    /**
031     * Construct a new {@code NamedColorProperty}.
032     * @param category a category, can be any identifier, but the following values are recognized by
033     * the GUI preferences: {@link #COLOR_CATEGORY_GENERAL} and {@link #COLOR_CATEGORY_MAPPAINT}
034     * @param source a filename or similar associated with the color, can be null if not applicable
035     * @param name a short description of the color
036     * @param defaultValue the default value, can be null
037     */
038    public NamedColorProperty(String category, String source, String name, Color defaultValue) {
039        super(getKey(category, source, name), defaultValue);
040        CheckParameterUtil.ensureParameterNotNull(category, "category");
041        CheckParameterUtil.ensureParameterNotNull(name, "name");
042        this.category = category;
043        this.source = source;
044        this.name = name;
045    }
046
047    /**
048     * Construct a new {@code NamedColorProperty}.
049     * @param name a short description of the color
050     * @param defaultValue the default value, can be null
051     */
052    public NamedColorProperty(String name, Color defaultValue) {
053        this(COLOR_CATEGORY_GENERAL, null, name, defaultValue);
054    }
055
056    private static String getKey(String category, String source, String name) {
057        CheckParameterUtil.ensureParameterNotNull(category, "category");
058        CheckParameterUtil.ensureParameterNotNull(name, "name");
059        return NAMED_COLOR_PREFIX + category + "." + (source == null ? "" : source + ".") + name;
060    }
061
062    private List<String> getDefaultValuePref() {
063        return defaultValue == null ? null : getValuePref(defaultValue, category, source, name);
064    }
065
066    @Override
067    public Color get() {
068        List<String> data = getPreferences().getList(getKey(), getDefaultValuePref()); // store default value
069        if (super.isSet() && data != null && !data.isEmpty()) {
070            return ColorHelper.html2color(data.get(0));
071        }
072        return defaultValue;
073    }
074
075    @Override
076    public boolean isSet() {
077        get(); // trigger migration
078        return super.isSet();
079    }
080
081    /**
082     * Get the category for this color.
083     * @return the category
084     */
085    public String getCategory() {
086        return category;
087    }
088
089    /**
090     * Get the source, i.e.&nbsp;a filename or layer name associated with the color.
091     * May return null if not applicable.
092     * @return the source
093     */
094    public String getSource() {
095        return source;
096    }
097
098    /**
099     * Get the color name (a short description of the color).
100     * @return the color name
101     */
102    public String getName() {
103        return name;
104    }
105
106    private static List<String> getValuePref(Color color, String category, String source, String name) {
107        CheckParameterUtil.ensureParameterNotNull(color, "color");
108        CheckParameterUtil.ensureParameterNotNull(category, "category");
109        CheckParameterUtil.ensureParameterNotNull(name, "name");
110        return Arrays.asList(ColorHelper.color2html(color, true), category, source == null ? "" : source, name);
111    }
112
113    @Override
114    public boolean put(Color value) {
115        return getPreferences().putList(getKey(), value == null ? null : getValuePref(value, category, source, name));
116    }
117
118    /**
119     * Return a more specialized color, that will fall back to this color, if not set explicitly.
120     * @param category the category of the specialized color
121     * @param source the source of the specialized color
122     * @param name the name of the specialized color
123     * @return a {@link FallbackProperty} that will the return the specialized color, if set, but
124     * fall back to this property as default value
125     */
126    public FallbackProperty<Color> getChildColor(String category, String source, String name) {
127        return new FallbackProperty<>(new NamedColorProperty(category, source, name, defaultValue), this);
128    }
129
130    /**
131     * Return a more specialized color, that will fall back to this color, if not set explicitly.
132     * @param name the name of the specialized color
133     * @return a {@link FallbackProperty} that will the return the specialized color, if set, but
134     * fall back to this property as default value
135     */
136    public FallbackProperty<Color> getChildColor(String name) {
137        return getChildColor(category, source, name);
138    }
139}