Ignore:
Timestamp:
2016-08-17T09:18:31+02:00 (8 years ago)
Author:
Don-vip
Message:

see #13309 - Caching and notifying preferences (patch by michael2402) - gsoc-core

Location:
trunk/src/org/openstreetmap/josm/data
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r10788 r10824  
    3737import java.util.SortedMap;
    3838import java.util.TreeMap;
    39 import java.util.concurrent.CopyOnWriteArrayList;
    4039import java.util.function.Predicate;
    4140import java.util.regex.Matcher;
    4241import java.util.regex.Pattern;
     42import java.util.stream.Stream;
    4343
    4444import javax.json.Json;
     
    5555
    5656import org.openstreetmap.josm.Main;
     57import org.openstreetmap.josm.data.preferences.BooleanProperty;
    5758import org.openstreetmap.josm.data.preferences.ColorProperty;
     59import org.openstreetmap.josm.data.preferences.DoubleProperty;
     60import org.openstreetmap.josm.data.preferences.IntegerProperty;
    5861import org.openstreetmap.josm.data.preferences.ListListSetting;
    5962import org.openstreetmap.josm.data.preferences.ListSetting;
     63import org.openstreetmap.josm.data.preferences.LongProperty;
    6064import org.openstreetmap.josm.data.preferences.MapListSetting;
    6165import org.openstreetmap.josm.data.preferences.PreferencesReader;
     
    6872import org.openstreetmap.josm.tools.ColorHelper;
    6973import org.openstreetmap.josm.tools.I18n;
     74import org.openstreetmap.josm.tools.ListenerList;
    7075import org.openstreetmap.josm.tools.MultiMap;
    71 import org.openstreetmap.josm.tools.SubclassFilteredCollection;
    7276import org.openstreetmap.josm.tools.Utils;
    7377import org.xml.sax.SAXException;
     
    215219    }
    216220
     221    /**
     222     * Old color interface
     223     * <p>
     224     * To be removed: end of 2016
     225     * @deprecated Use a {@link ColorProperty} instead.
     226     */
     227    @Deprecated
    217228    public interface ColorKey {
    218229        String getColorName();
     
    223234    }
    224235
    225     private final CopyOnWriteArrayList<PreferenceChangedListener> listeners = new CopyOnWriteArrayList<>();
     236    private final ListenerList<PreferenceChangedListener> listeners = ListenerList.create();
     237
     238    private final HashMap<String, ListenerList<PreferenceChangedListener>> keyListeners = new HashMap<>();
    226239
    227240    /**
     
    231244    public void addPreferenceChangeListener(PreferenceChangedListener listener) {
    232245        if (listener != null) {
    233             listeners.addIfAbsent(listener);
     246            listeners.addListener(listener);
    234247        }
    235248    }
     
    240253     */
    241254    public void removePreferenceChangeListener(PreferenceChangedListener listener) {
    242         listeners.remove(listener);
     255        listeners.removeListener(listener);
     256    }
     257
     258    /**
     259     * Adds a listener that only listens to changes in one preference
     260     * @param key The preference key to listen to
     261     * @param listener The listener to add.
     262     * @since 10824
     263     */
     264    public void addKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
     265        listenersForKey(key).addListener(listener);
     266    }
     267
     268    /**
     269     * Adds a weak listener that only listens to changes in one preference
     270     * @param key The preference key to listen to
     271     * @param listener The listener to add.
     272     * @since 10824
     273     */
     274    public void addWeakKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
     275        listenersForKey(key).addWeakListener(listener);
     276    }
     277
     278    private ListenerList<PreferenceChangedListener> listenersForKey(String key) {
     279        ListenerList<PreferenceChangedListener> keyListener = keyListeners.get(key);
     280        if (keyListener == null) {
     281            keyListener = ListenerList.create();
     282            keyListeners.put(key, keyListener);
     283        }
     284        return keyListener;
     285    }
     286
     287    /**
     288     * Removes a listener that only listens to changes in one preference
     289     * @param key The preference key to listen to
     290     * @param listener The listener to add.
     291     */
     292    public void removeKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
     293        ListenerList<PreferenceChangedListener> keyListener = keyListeners.get(key);
     294        if (keyListener == null) {
     295            throw new IllegalArgumentException("There are no listeners registered for " + key);
     296        }
     297        keyListener.removeListener(listener);
    243298    }
    244299
    245300    protected void firePreferenceChanged(String key, Setting<?> oldValue, Setting<?> newValue) {
    246         PreferenceChangeEvent evt = new DefaultPreferenceChangeEvent(key, oldValue, newValue);
    247         for (PreferenceChangedListener l : listeners) {
    248             l.preferenceChanged(evt);
     301        final PreferenceChangeEvent evt = new DefaultPreferenceChangeEvent(key, oldValue, newValue);
     302        listeners.fireEvent(listener -> listener.preferenceChanged(evt));
     303
     304        ListenerList<PreferenceChangedListener> forKey = keyListeners.get(key);
     305        if (forKey != null) {
     306            forKey.fireEvent(listener -> listener.preferenceChanged(evt));
    249307        }
    250308    }
     
    479537     */
    480538    public boolean put(final String key, String value) {
    481         if (value != null && value.isEmpty()) {
    482             value = null;
    483         }
    484         return putSetting(key, value == null ? null : new StringSetting(value));
    485     }
    486 
     539        return putSetting(key, value == null || value.isEmpty() ? null : new StringSetting(value));
     540    }
     541
     542    /**
     543     * Set a boolean value for a certain setting.
     544     * @param key the unique identifier for the setting
     545     * @param value The new value
     546     * @return {@code true}, if something has changed (i.e. value is different than before)
     547     * @see BooleanProperty
     548     */
    487549    public boolean put(final String key, final boolean value) {
    488550        return put(key, Boolean.toString(value));
    489551    }
    490552
     553    /**
     554     * Set a boolean value for a certain setting.
     555     * @param key the unique identifier for the setting
     556     * @param value The new value
     557     * @return {@code true}, if something has changed (i.e. value is different than before)
     558     * @see IntegerProperty
     559     */
    491560    public boolean putInteger(final String key, final Integer value) {
    492561        return put(key, Integer.toString(value));
    493562    }
    494563
     564    /**
     565     * Set a boolean value for a certain setting.
     566     * @param key the unique identifier for the setting
     567     * @param value The new value
     568     * @return {@code true}, if something has changed (i.e. value is different than before)
     569     * @see DoubleProperty
     570     */
    495571    public boolean putDouble(final String key, final Double value) {
    496572        return put(key, Double.toString(value));
    497573    }
    498574
     575    /**
     576     * Set a boolean value for a certain setting.
     577     * @param key the unique identifier for the setting
     578     * @param value The new value
     579     * @return {@code true}, if something has changed (i.e. value is different than before)
     580     * @see LongProperty
     581     */
    499582    public boolean putLong(final String key, final Long value) {
    500583        return put(key, Long.toString(value));
     
    506589     */
    507590    public synchronized void save() throws IOException {
    508         save(getPreferenceFile(),
    509                 new SubclassFilteredCollection<>(settingsMap.entrySet(), NO_DEFAULT_SETTINGS_ENTRY), false);
     591        save(getPreferenceFile(), settingsMap.entrySet().stream().filter(NO_DEFAULT_SETTINGS_ENTRY), false);
    510592    }
    511593
    512594    public synchronized void saveDefaults() throws IOException {
    513         save(getDefaultsCacheFile(), defaultsMap.entrySet(), true);
    514     }
    515 
    516     protected void save(File prefFile, Collection<Entry<String, Setting<?>>> settings, boolean defaults) throws IOException {
    517 
     595        save(getDefaultsCacheFile(), defaultsMap.entrySet().stream(), true);
     596    }
     597
     598    protected void save(File prefFile, Stream<Entry<String, Setting<?>>> settings, boolean defaults) throws IOException {
    518599        if (!defaults) {
    519600            /* currently unused, but may help to fix configuration issues in future */
     
    719800    /**
    720801     * Convenience method for accessing colour preferences.
     802     * <p>
     803     * To be removed: end of 2016
    721804     *
    722805     * @param colName name of the colour
    723806     * @param def default value
    724807     * @return a Color object for the configured colour, or the default value if none configured.
    725      */
     808     * @deprecated Use a {@link ColorProperty} instead.
     809     */
     810    @Deprecated
    726811    public synchronized Color getColor(String colName, Color def) {
    727812        return getColor(colName, null, def);
     
    743828    /**
    744829     * Returns the color for the given key.
     830     * <p>
     831     * To be removed: end of 2016
    745832     * @param key The color key
    746833     * @return the color
    747      */
     834     * @deprecated Use a {@link ColorProperty} instead.
     835     */
     836    @Deprecated
    748837    public Color getColor(ColorKey key) {
    749838        return getColor(key.getColorName(), key.getSpecialName(), key.getDefaultValue());
     
    752841    /**
    753842     * Convenience method for accessing colour preferences.
    754      *
     843     * <p>
     844     * To be removed: end of 2016
    755845     * @param colName name of the colour
    756846     * @param specName name of the special colour settings
    757847     * @param def default value
    758848     * @return a Color object for the configured colour, or the default value if none configured.
    759      */
     849     * @deprecated Use a {@link ColorProperty} instead.
     850     * You can replace this by: <code>new ColorProperty(colName, def).getChildColor(specName)</code>
     851     */
     852    @Deprecated
    760853    public synchronized Color getColor(String colName, String specName, Color def) {
    761854        String colKey = ColorProperty.getColorKey(colName);
    762         if (!colKey.equals(colName)) {
    763             colornames.put(colKey, colName);
    764         }
     855        registerColor(colKey, colName);
    765856        String colStr = specName != null ? get("color."+specName) : "";
    766857        if (colStr.isEmpty()) {
     
    771862        } else {
    772863            return def;
     864        }
     865    }
     866
     867    /**
     868     * Registers a color name conversion for the global color registry.
     869     * @param colKey The key
     870     * @param colName The name of the color.
     871     * @since 10824
     872     */
     873    public void registerColor(String colKey, String colName) {
     874        if (!colKey.equals(colName)) {
     875            colornames.put(colKey, colName);
    773876        }
    774877    }
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java

    r10378 r10824  
    77import java.util.List;
    88
    9 import org.openstreetmap.josm.Main;
    10 import org.openstreetmap.josm.data.Preferences.ColorKey;
     9import org.openstreetmap.josm.data.preferences.CachingProperty;
     10import org.openstreetmap.josm.data.preferences.ColorProperty;
    1111import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
    1212import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
    1313import org.openstreetmap.josm.gui.mappaint.StyleSource;
    1414
    15 public enum PaintColors implements ColorKey {
     15public enum PaintColors {
    1616
    1717    INACTIVE(marktr("inactive"), Color.darkGray),
     
    3434    private final String name;
    3535    private final Color defaultColor;
     36    private final CachingProperty<Color> property;
    3637
    3738    private static volatile Color backgroundColorCache;
    3839
    3940    private static final MapPaintSylesUpdateListener styleOverrideListener = new MapPaintSylesUpdateListener() {
    40 
     41        //TODO: Listen to wireframe map mode changes.
    4142        @Override
    4243        public void mapPaintStylesUpdated() {
     
    5556
    5657    PaintColors(String name, Color defaultColor) {
     58        property = new ColorProperty(name, defaultColor).cached();
    5759        this.name = name;
    5860        this.defaultColor = defaultColor;
    5961    }
    6062
    61     @Override
    62     public String getColorName() {
    63         return name;
    64     }
    65 
    66     @Override
    6763    public Color getDefaultValue() {
    68         return defaultColor;
    69     }
    70 
    71     @Override
    72     public String getSpecialName() {
    73         return null;
     64        return property.getDefaultValue();
    7465    }
    7566
    7667    public Color get() {
    77         return Main.pref.getColor(this);
    78     }
    79 
    80     public static void getColors() {
    81         for (PaintColors c:values()) {
    82             c.get();
    83         }
     68        return property.get();
    8469    }
    8570
     
    9883        }
    9984        if (backgroundColorCache == null) {
    100             backgroundColorCache = BACKGROUND.get();
     85            return BACKGROUND.get();
     86        } else {
     87            return backgroundColorCache;
    10188        }
    102         return backgroundColorCache;
    10389    }
    10490}
  • trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java

    r6069 r10824  
    33
    44import org.openstreetmap.josm.Main;
     5import org.openstreetmap.josm.data.Preferences;
     6import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
     7import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
    58
    69/**
     
    912 */
    1013public abstract class AbstractProperty<T> {
     14
     15    private final class PreferenceChangedListenerAdapter implements PreferenceChangedListener {
     16        private ValueChangeListener<? super T> listener;
     17
     18        PreferenceChangedListenerAdapter(ValueChangeListener<? super T> listener) {
     19            this.listener = listener;
     20        }
     21
     22        @Override
     23        public void preferenceChanged(PreferenceChangeEvent e) {
     24            listener.valueChanged(new ValueChangeEvent<>(e, AbstractProperty.this));
     25        }
     26
     27        @Override
     28        public int hashCode() {
     29            final int prime = 31;
     30            int result = 1;
     31            result = prime * result + getOuterType().hashCode();
     32            result = prime * result + ((listener == null) ? 0 : listener.hashCode());
     33            return result;
     34        }
     35
     36        @Override
     37        public boolean equals(Object obj) {
     38            if (this == obj)
     39                return true;
     40            if (obj == null)
     41                return false;
     42            if (getClass() != obj.getClass())
     43                return false;
     44            @SuppressWarnings("unchecked")
     45            PreferenceChangedListenerAdapter other = (PreferenceChangedListenerAdapter) obj;
     46            if (!getOuterType().equals(other.getOuterType()))
     47                return false;
     48            if (listener == null) {
     49                if (other.listener != null)
     50                    return false;
     51            } else if (!listener.equals(other.listener))
     52                return false;
     53            return true;
     54        }
     55
     56        private AbstractProperty<T> getOuterType() {
     57            return AbstractProperty.this;
     58        }
     59
     60        @Override
     61        public String toString() {
     62            return "PreferenceChangedListenerAdapter [listener=" + listener + ']';
     63        }
     64    }
     65
     66    /**
     67     * A listener that listens to changes in the properties value.
     68     * @author michael
     69     * @param <T> property type
     70     * @since 10824
     71     */
     72    public interface ValueChangeListener<T> {
     73        /**
     74         * Method called when a property value has changed.
     75         * @param e property change event
     76         */
     77        void valueChanged(ValueChangeEvent<? extends T> e);
     78    }
     79
     80    /**
     81     * An event that is triggered if the value of a property changes.
     82     * @author Michael Zangl
     83     * @param <T> property type
     84     * @since 10824
     85     */
     86    public static class ValueChangeEvent<T> {
     87        private final PreferenceChangeEvent base;
     88
     89        private final AbstractProperty<T> source;
     90
     91        ValueChangeEvent(PreferenceChangeEvent base, AbstractProperty<T> source) {
     92            this.base = base;
     93            this.source = source;
     94        }
     95
     96        /**
     97         * Get the property that was changed
     98         * @return The property.
     99         */
     100        public AbstractProperty<T> getProperty() {
     101            return source;
     102        }
     103    }
     104
     105    /**
     106     * An exception that is thrown if a preference value is invalid.
     107     * @author Michael Zangl
     108     * @since 10824
     109     */
     110    public static class InvalidPreferenceValueException extends RuntimeException {
     111
     112        /**
     113         * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message and cause.
     114         * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method).
     115         * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
     116         */
     117        public InvalidPreferenceValueException(String message, Throwable cause) {
     118            super(message, cause);
     119        }
     120
     121        /**
     122         * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message.
     123         * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}.
     124         *
     125         * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method.
     126         */
     127        public InvalidPreferenceValueException(String message) {
     128            super(message);
     129        }
     130
     131        /**
     132         * Constructs a new {@code InvalidPreferenceValueException} with the specified cause and a detail message of
     133         * <tt>(cause==null ? null : cause.toString())</tt> (which typically contains the class and detail message of <tt>cause</tt>).
     134         *
     135         * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
     136         */
     137        public InvalidPreferenceValueException(Throwable cause) {
     138            super(cause);
     139        }
     140    }
     141
     142    /**
     143     * The preferences object this property is for.
     144     */
     145    protected final Preferences preferences;
    11146    protected final String key;
    12147    protected final T defaultValue;
     
    19154     */
    20155    public AbstractProperty(String key, T defaultValue) {
     156        // Main.pref should not change in production but may change during tests.
     157        preferences = Main.pref;
    21158        this.key = key;
    22159        this.defaultValue = defaultValue;
     
    24161
    25162    /**
     163     * Store the default value to {@link Preferences}.
     164     */
     165    protected void storeDefaultValue() {
     166        if (getPreferences() != null) {
     167            get();
     168        }
     169    }
     170
     171    /**
    26172     * Replies the property key.
    27173     * @return The property key
     
    36182     */
    37183    public boolean isSet() {
    38         return !Main.pref.get(key).isEmpty();
     184        return !getPreferences().get(key).isEmpty();
    39185    }
    40186
     
    51197     */
    52198    public void remove() {
    53         Main.pref.put(getKey(), String.valueOf(getDefaultValue()));
     199        put(getDefaultValue());
    54200    }
    55201
     
    68214     */
    69215    public abstract boolean put(T value);
     216
     217    /**
     218     * Gets the preferences used for this property.
     219     * @return The preferences for this property.
     220     * @since 10824
     221     */
     222    protected Preferences getPreferences() {
     223        return preferences;
     224    }
     225
     226    /**
     227     * Adds a listener that listens only for changes to this preference key.
     228     * @param listener The listener to add.
     229     * @since 10824
     230     */
     231    public void addListener(ValueChangeListener<? super T> listener) {
     232        addListenerImpl(new PreferenceChangedListenerAdapter(listener));
     233    }
     234
     235    protected void addListenerImpl(PreferenceChangedListener adapter) {
     236        getPreferences().addKeyPreferenceChangeListener(getKey(), adapter);
     237    }
     238
     239    /**
     240     * Adds a weak listener that listens only for changes to this preference key.
     241     * @param listener The listener to add.
     242     * @since 10824
     243     */
     244    public void addWeakListener(ValueChangeListener<? super T> listener) {
     245        addWeakListenerImpl(new PreferenceChangedListenerAdapter(listener));
     246    }
     247
     248    protected void addWeakListenerImpl(PreferenceChangedListener adapter) {
     249        getPreferences().addWeakKeyPreferenceChangeListener(getKey(), adapter);
     250    }
     251
     252    /**
     253     * Removes a listener that listens only for changes to this preference key.
     254     * @param listener The listener to add.
     255     * @since 10824
     256     */
     257    public void removeListener(ValueChangeListener<? super T> listener) {
     258        removeListenerImpl(new PreferenceChangedListenerAdapter(listener));
     259    }
     260
     261    protected void removeListenerImpl(PreferenceChangedListener adapter) {
     262        getPreferences().removeKeyPreferenceChangeListener(getKey(), adapter);
     263    }
     264
     265    @Override
     266    public int hashCode() {
     267        final int prime = 31;
     268        int result = 1;
     269        result = prime * result + ((key == null) ? 0 : key.hashCode());
     270        result = prime * result + ((preferences == null) ? 0 : preferences.hashCode());
     271        return result;
     272    }
     273
     274    @Override
     275    public boolean equals(Object obj) {
     276        if (this == obj)
     277            return true;
     278        if (obj == null)
     279            return false;
     280        if (getClass() != obj.getClass())
     281            return false;
     282        AbstractProperty<?> other = (AbstractProperty<?>) obj;
     283        if (key == null) {
     284            if (other.key != null)
     285                return false;
     286        } else if (!key.equals(other.key))
     287            return false;
     288        if (preferences == null) {
     289            if (other.preferences != null)
     290                return false;
     291        } else if (!preferences.equals(other.preferences))
     292            return false;
     293        return true;
     294    }
    70295}
  • trunk/src/org/openstreetmap/josm/data/preferences/BooleanProperty.java

    r9689 r10824  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.preferences;
    3 
    4 import org.openstreetmap.josm.Main;
    53
    64/**
    75 * A property containing a {@code Boolean} value.
    86 */
    9 public class BooleanProperty extends AbstractProperty<Boolean> {
     7public class BooleanProperty extends AbstractToStringProperty<Boolean> {
    108
    119    /**
     
    1614    public BooleanProperty(String key, boolean defaultValue) {
    1715        super(key, defaultValue);
    18         if (Main.pref != null) {
    19             get();
    20         }
    2116    }
    2217
    2318    @Override
    2419    public Boolean get() {
    25         return Main.pref.getBoolean(getKey(), defaultValue);
     20        // Removing this implementation breaks binary compatibility
     21        return super.get();
    2622    }
    2723
    2824    @Override
    2925    public boolean put(Boolean value) {
    30         return Main.pref.put(getKey(), value);
     26        // Removing this implementation breaks binary compatibility
     27        return super.put(value);
     28    }
     29
     30    @Override
     31    protected Boolean fromString(String string) {
     32        return Boolean.valueOf(string);
     33    }
     34
     35    @Override
     36    protected String toString(Boolean t) {
     37        return t.toString();
    3138    }
    3239}
  • trunk/src/org/openstreetmap/josm/data/preferences/CachedProperty.java

    r7937 r10824  
    1414    protected CachedProperty(String key, String defaultValueAsString) {
    1515        super(key, null);
    16         Main.pref.addPreferenceChangeListener(this);
     16        Main.pref.addKeyPreferenceChangeListener(key, this);
    1717        this.defaultValueAsString = defaultValueAsString;
    1818        updateValue();
     
    6161
    6262    public String getAsString() {
    63         return Main.pref.get(getKey(), getDefaultValueAsString());
     63        return getPreferences().get(getKey(), getDefaultValueAsString());
    6464    }
    6565
  • trunk/src/org/openstreetmap/josm/data/preferences/CollectionProperty.java

    r9689 r10824  
    2525    @Override
    2626    public Collection<String> get() {
    27         return Main.pref.getCollection(getKey(), getDefaultValue());
     27        return getPreferences().getCollection(getKey(), getDefaultValue());
    2828    }
    2929
    3030    @Override
    3131    public boolean put(Collection<String> value) {
    32         return Main.pref.putCollection(getKey(), value);
     32        return getPreferences().putCollection(getKey(), value);
    3333    }
    3434}
  • trunk/src/org/openstreetmap/josm/data/preferences/ColorProperty.java

    r9689 r10824  
    55import java.util.Locale;
    66
    7 import org.openstreetmap.josm.Main;
    8 import org.openstreetmap.josm.data.Preferences.ColorKey;
     7import org.openstreetmap.josm.tools.ColorHelper;
    98
    109/**
     
    1211 * @since 5464
    1312 */
    14 public class ColorProperty extends AbstractProperty<Color> implements ColorKey {
     13public class ColorProperty extends AbstractToStringProperty<Color> {
    1514
    1615    private final String name;
     16
     17    /**
     18     * Constructs a new {@code ColorProperty}.
     19     * @param colName The color name
     20     * @param defaultValue The default value as HTML string
     21     */
     22    public ColorProperty(String colName, String defaultValue) {
     23        this(colName, ColorHelper.html2color(defaultValue));
     24    }
    1725
    1826    /**
     
    2432        super(getColorKey(colName), defaultValue);
    2533        this.name = colName;
    26         if (Main.pref != null) {
    27             get();
    28         }
     34        getPreferences().registerColor(getColorKey(colName), colName);
    2935    }
    3036
    3137    @Override
    3238    public Color get() {
    33         return Main.pref.getColor(this);
     39        // Removing this implementation breaks binary compatibility due to the way generics work
     40        return super.get();
    3441    }
    3542
    3643    @Override
    3744    public boolean put(Color value) {
    38         return Main.pref.putColor(getColorKey(name), value);
     45        // Removing this implementation breaks binary compatibility due to the way generics work
     46        return super.put(value);
     47    }
     48
     49    @Override
     50    protected Color fromString(String string) {
     51        return ColorHelper.html2color(string);
     52    }
     53
     54    @Override
     55    protected String toString(Color t) {
     56        return ColorHelper.color2html(t, true);
     57    }
     58
     59    /**
     60     * Gets a color of which the value can be set.
     61     * @param colorName the name of the color.
     62     * @return The child property that inherits this value if it is not set.
     63     */
     64    public AbstractToStringProperty<Color> getChildColor(String colorName) {
     65        return getChildProperty(getColorKey(colorName));
     66    }
     67
     68    /**
     69     * Gets the name this color was registered with.
     70     * @return The name.
     71     */
     72    public String getName() {
     73        return name;
    3974    }
    4075
     
    4580     */
    4681    public static String getColorKey(String colName) {
    47         return colName == null ? null : colName.toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9]+", ".");
     82        return colName == null ? null : "color." + colName.toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9]+", ".");
    4883    }
    4984
    5085    @Override
    51     public String getColorName() {
    52         return name;
    53     }
    54 
    55     @Override
    56     public String getSpecialName() {
    57         return null;
     86    public String toString() {
     87        return "ColorProperty [name=" + name + ", defaultValue=" + getDefaultValue() + "]";
    5888    }
    5989}
  • trunk/src/org/openstreetmap/josm/data/preferences/DoubleProperty.java

    r9818 r10824  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.preferences;
    3 
    4 import org.openstreetmap.josm.Main;
    53
    64/**
     
    86 * @since 3246
    97 */
    10 public class DoubleProperty extends AbstractProperty<Double> {
     8public class DoubleProperty extends AbstractToStringProperty<Double> {
    119
    1210    /**
     
    2119    @Override
    2220    public Double get() {
    23         return Main.pref.getDouble(getKey(), getDefaultValue());
     21        // Removing this implementation breaks binary compatibility
     22        return super.get();
    2423    }
    2524
    2625    @Override
    2726    public boolean put(Double value) {
    28         return Main.pref.putDouble(getKey(), value);
     27        // Removing this implementation breaks binary compatibility
     28        return super.put(value);
     29    }
     30
     31    @Override
     32    protected Double fromString(String string) {
     33        try {
     34            return Double.valueOf(string);
     35        } catch (NumberFormatException e) {
     36            throw new InvalidPreferenceValueException(e);
     37        }
     38    }
     39
     40    @Override
     41    protected String toString(Double t) {
     42        return t.toString();
    2943    }
    3044
  • trunk/src/org/openstreetmap/josm/data/preferences/IntegerProperty.java

    r9689 r10824  
    88 * @since 3246
    99 */
    10 public class IntegerProperty extends AbstractProperty<Integer> {
     10public class IntegerProperty extends AbstractToStringProperty<Integer> {
    1111
    1212    /**
     
    2424    @Override
    2525    public Integer get() {
    26         return Main.pref.getInteger(getKey(), getDefaultValue());
     26        // Removing this implementation breaks binary compatibility
     27        return super.get();
    2728    }
    2829
    2930    @Override
    3031    public boolean put(Integer value) {
    31         return Main.pref.putInteger(getKey(), value);
     32        // Removing this implementation breaks binary compatibility
     33        return super.put(value);
     34    }
     35
     36    @Override
     37    protected Integer fromString(String string) {
     38        try {
     39            return Integer.valueOf(string);
     40        } catch (NumberFormatException e) {
     41            throw new InvalidPreferenceValueException(e);
     42        }
     43    }
     44
     45    @Override
     46    protected String toString(Integer t) {
     47        return t.toString();
    3248    }
    3349
  • trunk/src/org/openstreetmap/josm/data/preferences/LongProperty.java

    r10087 r10824  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.preferences;
    3 
    4 import org.openstreetmap.josm.Main;
    53
    64/**
     
    97 *
    108 */
    11 public class LongProperty extends AbstractProperty<Long> {
     9public class LongProperty extends AbstractToStringProperty<Long> {
    1210
    1311    /**
     
    1816    public LongProperty(String key, long defaultValue) {
    1917        super(key, defaultValue);
    20         if (Main.pref != null) {
    21             get();
     18    }
     19
     20    @Override
     21    public Long get() {
     22        // Removing this implementation breaks binary compatibility
     23        return super.get();
     24    }
     25
     26    @Override
     27    public boolean put(Long value) {
     28        // Removing this implementation breaks binary compatibility
     29        return super.put(value);
     30    }
     31
     32    @Override
     33    protected Long fromString(String string) {
     34        try {
     35            return Long.valueOf(string);
     36        } catch (NumberFormatException e) {
     37            throw new InvalidPreferenceValueException(e);
    2238        }
    2339    }
    2440
    2541    @Override
    26     public Long get() {
    27         return Main.pref.getLong(getKey(), getDefaultValue());
     42    protected String toString(Long t) {
     43        return t.toString();
    2844    }
    29 
    30     @Override
    31     public boolean put(Long value) {
    32         return Main.pref.putLong(getKey(), value);
    33     }
    34 
    3545}
  • trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java

    r9828 r10824  
    66import java.util.List;
    77import java.util.Map;
     8import java.util.stream.Stream;
    89
    910import org.openstreetmap.josm.Main;
     
    3839     */
    3940    public void write(Collection<Map.Entry<String, Setting<?>>> settings) {
     41        write(settings.stream());
     42    }
     43
     44    /**
     45     * Write preferences.
     46     *
     47     * @param settings preferences settings to write as stream.
     48     */
     49    public void write(Stream<Map.Entry<String, Setting<?>>> settings) {
    4050        out.write(String.format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n"));
    4151        String rootElement = defaults ? "preferences-defaults" : "preferences";
     
    4555        }
    4656        out.write(String.format(" version='%d'>%n", Version.getInstance().getVersion()));
    47         for (Map.Entry<String, Setting<?>> e : settings) {
     57        settings.forEachOrdered(e -> {
    4858            setKey(e.getKey());
    4959            e.getValue().visit(this);
    50         }
     60        });
    5161        out.write(String.format("</%s>%n", rootElement));
    5262    }
  • trunk/src/org/openstreetmap/josm/data/preferences/StringProperty.java

    r9689 r10824  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.preferences;
    3 
    4 import org.openstreetmap.josm.Main;
    53
    64/**
    75 * A property containing an {@code String} value.
    86 */
    9 public class StringProperty extends AbstractProperty<String> {
     7public class StringProperty extends AbstractToStringProperty<String> {
    108
    119    /**
     
    1614    public StringProperty(String key, String defaultValue) {
    1715        super(key, defaultValue);
    18         if (Main.pref != null) {
    19             get();
    20         }
    2116    }
    2217
    2318    @Override
    2419    public String get() {
    25         return Main.pref.get(getKey(), getDefaultValue());
     20        // Removing this implementation breaks binary compatibility
     21        return super.get();
    2622    }
    2723
    2824    @Override
    2925    public boolean put(String value) {
    30         return Main.pref.put(getKey(), value);
     26        // Removing this implementation breaks binary compatibility
     27        return super.put(value);
     28    }
     29
     30    @Override
     31    protected String fromString(String string) {
     32        return string;
     33    }
     34
     35    @Override
     36    protected String toString(String string) {
     37        return string;
    3138    }
    3239}
Note: See TracChangeset for help on using the changeset viewer.