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 javax.swing.UIManager; 009 010import org.openstreetmap.josm.tools.CheckParameterUtil; 011import org.openstreetmap.josm.tools.ColorHelper; 012import org.openstreetmap.josm.tools.Utils; 013 014/** 015 * A property containing a {@link Color} value with additional information associated to it. 016 * 017 * The additional information is used to describe the color in the 018 * {@link org.openstreetmap.josm.gui.preferences.display.ColorPreference}, so it can be recognized 019 * and customized by the user. 020 * @since 12987 021 */ 022public class NamedColorProperty extends AbstractToStringProperty<Color> { 023 024 public static final String NAMED_COLOR_PREFIX = "clr."; 025 026 public static final String COLOR_CATEGORY_GENERAL = "general"; 027 public static final String COLOR_CATEGORY_MAPPAINT = "mappaint"; 028 029 private final String category; 030 private final String source; 031 private final String name; 032 033 /** 034 * Construct a new {@code NamedColorProperty}. 035 * 036 * The priority for getting the color is: 1. a set property, 2. {@link UIManager#getColor}, 3. the given {@code defaultValue} 037 * @param category a category, can be any identifier, but the following values are recognized by 038 * the GUI preferences: {@link #COLOR_CATEGORY_GENERAL} and {@link #COLOR_CATEGORY_MAPPAINT} 039 * @param source a filename or similar associated with the color, can be null if not applicable 040 * @param name a short description of the color 041 * @param defaultValue the default value, can be null 042 */ 043 public NamedColorProperty(String category, String source, String name, Color defaultValue) { 044 super(getKey(category, source, name), getUIColor("JOSM." + getKey(category, source, name), defaultValue)); 045 CheckParameterUtil.ensureParameterNotNull(category, "category"); 046 CheckParameterUtil.ensureParameterNotNull(name, "name"); 047 this.category = category; 048 this.source = source; 049 this.name = name; 050 } 051 052 /** 053 * Construct a new {@code NamedColorProperty}. 054 * @param name a short description of the color 055 * @param defaultValue the default value, can be null 056 */ 057 public NamedColorProperty(String name, Color defaultValue) { 058 this(COLOR_CATEGORY_GENERAL, null, name, defaultValue); 059 } 060 061 private static String getKey(String category, String source, String name) { 062 CheckParameterUtil.ensureParameterNotNull(category, "category"); 063 CheckParameterUtil.ensureParameterNotNull(name, "name"); 064 return NAMED_COLOR_PREFIX + category + "." + (source == null ? "" : source + ".") + name; 065 } 066 067 private static Color getUIColor(String uiKey, Color defaultValue) { 068 Color color = UIManager.getColor(uiKey); 069 return color != null ? color : defaultValue; 070 } 071 072 private List<String> getDefaultValuePref() { 073 return defaultValue == null ? null : getValuePref(defaultValue, category, source, name); 074 } 075 076 @Override 077 protected void storeDefaultValue() { 078 // This is required due to the super() initializer calling this method. 079 if (category != null) { 080 super.storeDefaultValue(); 081 } 082 } 083 084 @Override 085 public Color get() { 086 List<String> data = getPreferences().getList(getKey(), getDefaultValuePref()); // store default value 087 if (super.isSet() && !Utils.isEmpty(data)) { 088 return ColorHelper.html2color(data.get(0)); 089 } 090 return defaultValue; 091 } 092 093 @Override 094 public boolean isSet() { 095 get(); // trigger migration 096 return super.isSet(); 097 } 098 099 /** 100 * Get the category for this color. 101 * @return the category 102 */ 103 public String getCategory() { 104 return category; 105 } 106 107 /** 108 * Get the source, i.e. a filename or layer name associated with the color. 109 * May return null if not applicable. 110 * @return the source 111 */ 112 public String getSource() { 113 return source; 114 } 115 116 /** 117 * Get the color name (a short description of the color). 118 * @return the color name 119 */ 120 public String getName() { 121 return name; 122 } 123 124 private static List<String> getValuePref(Color color, String category, String source, String name) { 125 CheckParameterUtil.ensureParameterNotNull(color, "color"); 126 CheckParameterUtil.ensureParameterNotNull(category, "category"); 127 CheckParameterUtil.ensureParameterNotNull(name, "name"); 128 return Arrays.asList(ColorHelper.color2html(color, true), category, source == null ? "" : source, name); 129 } 130 131 @Override 132 public boolean put(Color value) { 133 return getPreferences().putList(getKey(), value == null ? null : getValuePref(value, category, source, name)); 134 } 135 136 /** 137 * Return a more specialized color, that will fall back to this color, if not set explicitly. 138 * @param category the category of the specialized color 139 * @param source the source of the specialized color 140 * @param name the name of the specialized color 141 * @return a {@link FallbackProperty} that will the return the specialized color, if set, but 142 * fall back to this property as default value 143 */ 144 public FallbackProperty<Color> getChildColor(String category, String source, String name) { 145 return new FallbackProperty<>(new NamedColorProperty(category, source, name, defaultValue), this); 146 } 147 148 /** 149 * Return a more specialized color, that will fall back to this color, if not set explicitly. 150 * @param name the name of the specialized color 151 * @return a {@link FallbackProperty} that will the return the specialized color, if set, but 152 * fall back to this property as default value 153 */ 154 public FallbackProperty<Color> getChildColor(String name) { 155 return getChildColor(category, source, name); 156 } 157 158 @Override 159 protected Color fromString(String string) { 160 return ColorHelper.html2color(string); 161 } 162 163 @Override 164 protected String toString(Color color) { 165 return ColorHelper.color2html(color); 166 } 167}