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    public static final String COLOR_CATEGORY_LAYER = "layer";
026
027    private final String category;
028    private final String source;
029    private final String name;
030
031    /**
032     * Construct a new {@code NamedColorProperty}.
033     * @param category a category, can be any identifier, but the following values are recognized by
034     * the GUI preferences: {@link #COLOR_CATEGORY_GENERAL}, {@link #COLOR_CATEGORY_MAPPAINT} and
035     * {@link #COLOR_CATEGORY_LAYER}
036     * @param source a filename or similar associated with the color, can be null if not applicable
037     * @param name a short description of the color
038     * @param defaultValue the default value, can be null
039     */
040    public NamedColorProperty(String category, String source, String name, Color defaultValue) {
041        super(getKey(category, source, name), defaultValue);
042        CheckParameterUtil.ensureParameterNotNull(category, "category");
043        CheckParameterUtil.ensureParameterNotNull(name, "name");
044        this.category = category;
045        this.source = source;
046        this.name = name;
047    }
048
049    /**
050     * Construct a new {@code NamedColorProperty}.
051     * @param name a short description of the color
052     * @param defaultValue the default value, can be null
053     */
054    public NamedColorProperty(String name, Color defaultValue) {
055        this(COLOR_CATEGORY_GENERAL, null, name, defaultValue);
056    }
057
058    private static String getKey(String category, String source, String name) {
059        CheckParameterUtil.ensureParameterNotNull(category, "category");
060        CheckParameterUtil.ensureParameterNotNull(name, "name");
061        return NAMED_COLOR_PREFIX + category + "." + (source == null ? "" : source + ".") + name;
062    }
063
064    private List<String> getDefaultValuePref() {
065        return defaultValue == null ? null : getValuePref(defaultValue, category, source, name);
066    }
067
068    @Override
069    public Color get() {
070        List<String> data = getPreferences().getList(getKey(), getDefaultValuePref()); // store default value
071        if (super.isSet() && data != null && !data.isEmpty()) {
072            return ColorHelper.html2color(data.get(0));
073        }
074        return defaultValue;
075    }
076
077    @Override
078    public boolean isSet() {
079        get(); // trigger migration
080        return super.isSet();
081    }
082
083    /**
084     * Get the category for this color.
085     * @return the category
086     */
087    public String getCategory() {
088        return category;
089    }
090
091    /**
092     * Get the source, i.e.&nbsp;a filename or layer name associated with the color.
093     * May return null if not applicable.
094     * @return the source
095     */
096    public String getSource() {
097        return source;
098    }
099
100    /**
101     * Get the color name (a short description of the color).
102     * @return the color name
103     */
104    public String getName() {
105        return name;
106    }
107
108    private static List<String> getValuePref(Color color, String category, String source, String name) {
109        CheckParameterUtil.ensureParameterNotNull(color, "color");
110        CheckParameterUtil.ensureParameterNotNull(category, "category");
111        CheckParameterUtil.ensureParameterNotNull(name, "name");
112        return Arrays.asList(ColorHelper.color2html(color, true), category, source == null ? "" : source, name);
113    }
114
115    @Override
116    public boolean put(Color value) {
117        return getPreferences().putList(getKey(), value == null ? null : getValuePref(value, category, source, name));
118    }
119
120    /**
121     * Return a more specialized color, that will fall back to this color, if not set explicitly.
122     * @param category the category of the specialized color
123     * @param source the source of the specialized color
124     * @param name the name of the specialized color
125     * @return a {@link FallbackProperty} that will the return the specialized color, if set, but
126     * fall back to this property as default value
127     */
128    public FallbackProperty<Color> getChildColor(String category, String source, String name) {
129        return new FallbackProperty<>(new NamedColorProperty(category, source, name, defaultValue), this);
130    }
131
132    /**
133     * Return a more specialized color, that will fall back to this color, if not set explicitly.
134     * @param name the name of the specialized color
135     * @return a {@link FallbackProperty} that will the return the specialized color, if set, but
136     * fall back to this property as default value
137     */
138    public FallbackProperty<Color> getChildColor(String name) {
139        return getChildColor(category, source, name);
140    }
141}