Index: trunk/src/org/openstreetmap/josm/actions/PreferenceToggleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/PreferenceToggleAction.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/actions/PreferenceToggleAction.java	(revision 12881)
@@ -7,6 +7,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 
@@ -52,5 +53,5 @@
 
     @Override
-    public void preferenceChanged(Preferences.PreferenceChangeEvent e) {
+    public void preferenceChanged(PreferenceChangeEvent e) {
         checkbox.setSelected(pref.get());
     }
Index: trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12881)
@@ -27,5 +27,5 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DatasetConsistencyTest;
-import org.openstreetmap.josm.data.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Setting;
 import org.openstreetmap.josm.data.preferences.sources.MapPaintPrefHelper;
 import org.openstreetmap.josm.data.preferences.sources.PresetPrefHelper;
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 12881)
@@ -12,6 +12,6 @@
 
 import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.MainApplication;
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 12881)
@@ -48,12 +48,12 @@
 import org.openstreetmap.josm.data.preferences.DoubleProperty;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
-import org.openstreetmap.josm.data.preferences.ListListSetting;
-import org.openstreetmap.josm.data.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
 import org.openstreetmap.josm.data.preferences.LongProperty;
-import org.openstreetmap.josm.data.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
 import org.openstreetmap.josm.data.preferences.PreferencesReader;
 import org.openstreetmap.josm.data.preferences.PreferencesWriter;
-import org.openstreetmap.josm.data.preferences.Setting;
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.data.preferences.sources.ExtendedSourceEntry;
 import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
@@ -157,5 +157,7 @@
     /**
      * Event triggered when a preference entry value changes.
-     */
+     * @deprecated use {@link org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent}
+     */
+    @Deprecated
     public interface PreferenceChangeEvent {
         /**
@@ -181,6 +183,8 @@
      * Listener to preference change events.
      * @since 10600 (functional interface)
+     * @deprecated use {@link org.openstreetmap.josm.spi.preferences.PreferenceChangedListener}
      */
     @FunctionalInterface
+    @Deprecated
     public interface PreferenceChangedListener {
         /**
@@ -191,4 +195,5 @@
     }
 
+    @Deprecated
     private static class DefaultPreferenceChangeEvent implements PreferenceChangeEvent {
         private final String key;
@@ -218,7 +223,13 @@
     }
 
-    private final ListenerList<PreferenceChangedListener> listeners = ListenerList.create();
-
-    private final HashMap<String, ListenerList<PreferenceChangedListener>> keyListeners = new HashMap<>();
+    private final ListenerList<org.openstreetmap.josm.spi.preferences.PreferenceChangedListener> listeners = ListenerList.create();
+
+    private final HashMap<String, ListenerList<org.openstreetmap.josm.spi.preferences.PreferenceChangedListener>> keyListeners = new HashMap<>();
+
+    @Deprecated
+    private final ListenerList<Preferences.PreferenceChangedListener> listenersDeprecated = ListenerList.create();
+
+    @Deprecated
+    private final HashMap<String, ListenerList<Preferences.PreferenceChangedListener>> keyListenersDeprecated = new HashMap<>();
 
     /**
@@ -243,7 +254,8 @@
      * Adds a new preferences listener.
      * @param listener The listener to add
+     * @since xxx
      */
     @Override
-    public void addPreferenceChangeListener(PreferenceChangedListener listener) {
+    public void addPreferenceChangeListener(org.openstreetmap.josm.spi.preferences.PreferenceChangedListener listener) {
         if (listener != null) {
             listeners.addListener(listener);
@@ -252,10 +264,44 @@
 
     /**
+     * Adds a new preferences listener.
+     * @param listener The listener to add
+     * @deprecated use {@link #addPreferenceChangeListener(org.openstreetmap.josm.spi.preferences.PreferenceChangedListener)}
+     */
+    @Deprecated
+    public void addPreferenceChangeListener(Preferences.PreferenceChangedListener listener) {
+        if (listener != null) {
+            listenersDeprecated.addListener(listener);
+        }
+    }
+
+    /**
      * Removes a preferences listener.
      * @param listener The listener to remove
+     * @since xxx
      */
     @Override
-    public void removePreferenceChangeListener(PreferenceChangedListener listener) {
+    public void removePreferenceChangeListener(org.openstreetmap.josm.spi.preferences.PreferenceChangedListener listener) {
         listeners.removeListener(listener);
+    }
+
+    /**
+     * Removes a preferences listener.
+     * @param listener The listener to remove
+     * @deprecated use {@link #removePreferenceChangeListener(org.openstreetmap.josm.spi.preferences.PreferenceChangedListener)}
+     */
+    @Deprecated
+    public void removePreferenceChangeListener(Preferences.PreferenceChangedListener listener) {
+        listenersDeprecated.removeListener(listener);
+    }
+
+    /**
+     * Adds a listener that only listens to changes in one preference
+     * @param key The preference key to listen to
+     * @param listener The listener to add.
+     * @since xxx
+     */
+    @Override
+    public void addKeyPreferenceChangeListener(String key, org.openstreetmap.josm.spi.preferences.PreferenceChangedListener listener) {
+        listenersForKey(key).addListener(listener);
     }
 
@@ -265,8 +311,9 @@
      * @param listener The listener to add.
      * @since 10824
-     */
-    @Override
-    public void addKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
-        listenersForKey(key).addListener(listener);
+     * @deprecated use {@link #addKeyPreferenceChangeListener(java.lang.String, org.openstreetmap.josm.spi.preferences.PreferenceChangedListener)}
+     */
+    @Deprecated
+    public void addKeyPreferenceChangeListener(String key, Preferences.PreferenceChangedListener listener) {
+        listenersForKeyDeprecated(key).addListener(listener);
     }
 
@@ -277,10 +324,15 @@
      * @since 10824
      */
-    public void addWeakKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
+    public void addWeakKeyPreferenceChangeListener(String key, org.openstreetmap.josm.spi.preferences.PreferenceChangedListener listener) {
         listenersForKey(key).addWeakListener(listener);
     }
 
-    private ListenerList<PreferenceChangedListener> listenersForKey(String key) {
+    private ListenerList<org.openstreetmap.josm.spi.preferences.PreferenceChangedListener> listenersForKey(String key) {
         return keyListeners.computeIfAbsent(key, k -> ListenerList.create());
+    }
+
+    @Deprecated
+    private ListenerList<Preferences.PreferenceChangedListener> listenersForKeyDeprecated(String key) {
+        return keyListenersDeprecated.computeIfAbsent(key, k -> ListenerList.create());
     }
 
@@ -289,7 +341,8 @@
      * @param key The preference key to listen to
      * @param listener The listener to add.
+     * @since xxx
      */
     @Override
-    public void removeKeyPreferenceChangeListener(String key, PreferenceChangedListener listener) {
+    public void removeKeyPreferenceChangeListener(String key, org.openstreetmap.josm.spi.preferences.PreferenceChangedListener listener) {
         Optional.ofNullable(keyListeners.get(key)).orElseThrow(
                 () -> new IllegalArgumentException("There are no listeners registered for " + key))
@@ -297,11 +350,36 @@
     }
 
+    /**
+     * Removes a listener that only listens to changes in one preference
+     * @param key The preference key to listen to
+     * @param listener The listener to add.
+     * @deprecated use {@link #removeKeyPreferenceChangeListener(java.lang.String, org.openstreetmap.josm.spi.preferences.PreferenceChangedListener)}
+     */
+    @Deprecated
+    public void removeKeyPreferenceChangeListener(String key, Preferences.PreferenceChangedListener listener) {
+        Optional.ofNullable(keyListenersDeprecated.get(key)).orElseThrow(
+                () -> new IllegalArgumentException("There are no listeners registered for " + key))
+        .removeListener(listener);
+    }
+
     protected void firePreferenceChanged(String key, Setting<?> oldValue, Setting<?> newValue) {
-        final PreferenceChangeEvent evt = new DefaultPreferenceChangeEvent(key, oldValue, newValue);
+        final org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent evt = new org.openstreetmap.josm.spi.preferences.DefaultPreferenceChangeEvent(key, oldValue, newValue);
         listeners.fireEvent(listener -> listener.preferenceChanged(evt));
 
-        ListenerList<PreferenceChangedListener> forKey = keyListeners.get(key);
+        ListenerList<org.openstreetmap.josm.spi.preferences.PreferenceChangedListener> forKey = keyListeners.get(key);
         if (forKey != null) {
             forKey.fireEvent(listener -> listener.preferenceChanged(evt));
+        }
+        firePreferenceChangedDeprecated(key, oldValue, newValue);
+    }
+
+    @Deprecated
+    private void firePreferenceChangedDeprecated(String key, Setting<?> oldValue, Setting<?> newValue) {
+        final Preferences.PreferenceChangeEvent evtDeprecated = new Preferences.DefaultPreferenceChangeEvent(key, oldValue, newValue);
+        listenersDeprecated.fireEvent(listener -> listener.preferenceChanged(evtDeprecated));
+
+        ListenerList<Preferences.PreferenceChangedListener> forKeyDeprecated = keyListenersDeprecated.get(key);
+        if (forKeyDeprecated != null) {
+            forKeyDeprecated.fireEvent(listener -> listener.preferenceChanged(evtDeprecated));
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/PreferencesUtils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/PreferencesUtils.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/PreferencesUtils.java	(revision 12881)
@@ -18,9 +18,9 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.preferences.ListListSetting;
-import org.openstreetmap.josm.data.preferences.ListSetting;
-import org.openstreetmap.josm.data.preferences.MapListSetting;
-import org.openstreetmap.josm.data.preferences.Setting;
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
Index: trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java	(revision 12881)
@@ -7,10 +7,10 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.UserInfo;
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.io.OnlineResource;
Index: trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 12881)
@@ -12,6 +12,6 @@
 import java.util.stream.Collectors;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.spi.preferences.Config;
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintSettings.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintSettings.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPaintSettings.java	(revision 12881)
@@ -4,6 +4,6 @@
 import java.awt.Color;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.spi.preferences.Config;
 
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java	(revision 12881)
@@ -15,6 +15,6 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.osm.DataSet;
Index: trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java	(revision 12881)
@@ -4,6 +4,6 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Preferences;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.tools.ListenableWeakReference;
 import org.openstreetmap.josm.tools.bugreport.BugReport;
Index: trunk/src/org/openstreetmap/josm/data/preferences/AbstractSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/AbstractSetting.java	(revision 12880)
+++ 	(revision )
@@ -1,69 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-import java.util.Objects;
-
-/**
- * Base abstract class of all settings, holding the setting value.
- *
- * @param <T> The setting type
- * @since 9759
- */
-public abstract class AbstractSetting<T> implements Setting<T> {
-    protected final T value;
-    protected Long time;
-    protected boolean isNew;
-    /**
-     * Constructs a new {@code AbstractSetting} with the given value
-     * @param value The setting value
-     */
-    public AbstractSetting(T value) {
-        this.value = value;
-        this.time = null;
-        this.isNew = false;
-    }
-
-    @Override
-    public T getValue() {
-        return value;
-    }
-
-    @Override
-    public void setTime(Long time) {
-        this.time = time;
-    }
-
-    @Override
-    public Long getTime() {
-        return this.time;
-    }
-
-    @Override
-    public void setNew(boolean isNew) {
-        this.isNew = isNew;
-    }
-
-    @Override
-    public boolean isNew() {
-        return isNew;
-    }
-
-    @Override
-    public String toString() {
-        return value != null ? value.toString() : "null";
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(value);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null || getClass() != obj.getClass())
-            return false;
-        return Objects.equals(value, ((AbstractSetting<?>) obj).value);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/AbstractToStringProperty.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/AbstractToStringProperty.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/preferences/AbstractToStringProperty.java	(revision 12881)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.data.preferences;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Logging;
Index: trunk/src/org/openstreetmap/josm/data/preferences/CachedProperty.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/CachedProperty.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/preferences/CachedProperty.java	(revision 12881)
@@ -2,6 +2,6 @@
 package org.openstreetmap.josm.data.preferences;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.spi.preferences.Config;
 
Index: trunk/src/org/openstreetmap/josm/data/preferences/ListListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/ListListSetting.java	(revision 12880)
+++ 	(revision )
@@ -1,74 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Setting containing a {@link List} of {@code List}s of {@link String} values.
- * @since 9759
- */
-public class ListListSetting extends AbstractSetting<List<List<String>>> {
-
-    /**
-     * Constructs a new {@code ListListSetting} with the given value
-     * @param value The setting value
-     */
-    public ListListSetting(List<List<String>> value) {
-        super(value);
-        consistencyTest();
-    }
-
-    /**
-     * Convenience factory method.
-     * @param value the value
-     * @return a corresponding ListListSetting object
-     */
-    public static ListListSetting create(Collection<Collection<String>> value) {
-        if (value != null) {
-            List<List<String>> valueList = new ArrayList<>(value.size());
-            for (Collection<String> lst : value) {
-                valueList.add(new ArrayList<>(lst));
-            }
-            return new ListListSetting(valueList);
-        }
-        return new ListListSetting(null);
-    }
-
-    @Override
-    public ListListSetting copy() {
-        if (value == null)
-            return new ListListSetting(null);
-
-        List<List<String>> copy = new ArrayList<>(value.size());
-        for (Collection<String> lst : value) {
-            List<String> lstCopy = new ArrayList<>(lst);
-            copy.add(Collections.unmodifiableList(lstCopy));
-        }
-        return new ListListSetting(Collections.unmodifiableList(copy));
-    }
-
-    private void consistencyTest() {
-        if (value != null) {
-            if (value.contains(null))
-                throw new IllegalArgumentException("Error: Null as list element in preference setting");
-            for (Collection<String> lst : value) {
-                if (lst.contains(null)) {
-                    throw new IllegalArgumentException("Error: Null as inner list element in preference setting");
-                }
-            }
-        }
-    }
-
-    @Override
-    public void visit(SettingVisitor visitor) {
-        visitor.visit(this);
-    }
-
-    @Override
-    public ListListSetting getNullInstance() {
-        return new ListListSetting(null);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/ListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/ListSetting.java	(revision 12880)
+++ 	(revision )
@@ -1,51 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Setting containing a {@link List} of {@link String} values.
- * @since 9759
- */
-public class ListSetting extends AbstractSetting<List<String>> {
-    /**
-     * Constructs a new {@code ListSetting} with the given value
-     * @param value The setting value
-     */
-    public ListSetting(List<String> value) {
-        super(value);
-        consistencyTest();
-    }
-
-    /**
-     * Convenience factory method.
-     * @param value the value
-     * @return a corresponding ListSetting object
-     */
-    public static ListSetting create(Collection<String> value) {
-        return new ListSetting(value == null ? null : Collections.unmodifiableList(new ArrayList<>(value)));
-    }
-
-    @Override
-    public ListSetting copy() {
-        return ListSetting.create(value);
-    }
-
-    private void consistencyTest() {
-        if (value != null && value.contains(null))
-            throw new IllegalArgumentException("Error: Null as list element in preference setting");
-    }
-
-    @Override
-    public void visit(SettingVisitor visitor) {
-        visitor.visit(this);
-    }
-
-    @Override
-    public ListSetting getNullInstance() {
-        return new ListSetting(null);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/MapListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/MapListSetting.java	(revision 12880)
+++ 	(revision )
@@ -1,59 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Setting containing a {@link List} of {@link Map}s of {@link String} values.
- * @since 9759
- */
-public class MapListSetting extends AbstractSetting<List<Map<String, String>>> {
-
-    /**
-     * Constructs a new {@code MapListSetting} with the given value
-     * @param value The setting value
-     */
-    public MapListSetting(List<Map<String, String>> value) {
-        super(value);
-        consistencyTest();
-    }
-
-    @Override
-    public MapListSetting copy() {
-        if (value == null)
-            return new MapListSetting(null);
-        List<Map<String, String>> copy = new ArrayList<>(value.size());
-        for (Map<String, String> map : value) {
-            Map<String, String> mapCopy = new LinkedHashMap<>(map);
-            copy.add(Collections.unmodifiableMap(mapCopy));
-        }
-        return new MapListSetting(Collections.unmodifiableList(copy));
-    }
-
-    private void consistencyTest() {
-        if (value == null)
-            return;
-        if (value.contains(null))
-            throw new IllegalArgumentException("Error: Null as list element in preference setting");
-        for (Map<String, String> map : value) {
-            if (map.containsKey(null))
-                throw new IllegalArgumentException("Error: Null as map key in preference setting");
-            if (map.containsValue(null))
-                throw new IllegalArgumentException("Error: Null as map value in preference setting");
-        }
-    }
-
-    @Override
-    public void visit(SettingVisitor visitor) {
-        visitor.visit(this);
-    }
-
-    @Override
-    public MapListSetting getNullInstance() {
-        return new MapListSetting(null);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java	(revision 12881)
@@ -32,4 +32,9 @@
 import org.openstreetmap.josm.io.CachedFile;
 import org.openstreetmap.josm.io.XmlStreamParsingException;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.tools.Logging;
 import org.xml.sax.SAXException;
Index: trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 12881)
@@ -12,4 +12,10 @@
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.io.XmlWriter;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.SettingVisitor;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 
 /**
Index: trunk/src/org/openstreetmap/josm/data/preferences/Setting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/Setting.java	(revision 12880)
+++ 	(revision )
@@ -1,88 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-import org.openstreetmap.josm.data.Preferences;
-
-/**
- * Interface for a preference value.
- *
- * Implementations must provide a proper <code>equals</code> method.
- *
- * @param <T> the data type for the value
- * @since 9759
- */
-public interface Setting<T> {
-    /**
-     * Returns the value of this setting.
-     *
-     * @return the value of this setting
-     */
-    T getValue();
-
-    /**
-     * Check if the value of this Setting object is equal to the given value.
-     * @param otherVal the other value
-     * @return true if the values are equal
-     */
-    default boolean equalVal(T otherVal) {
-        return getValue() == null ? (otherVal == null) : getValue().equals(otherVal);
-    }
-
-    /**
-     * Clone the current object.
-     * @return an identical copy of the current object
-     */
-    Setting<T> copy();
-
-    /**
-     * Enable usage of the visitor pattern.
-     *
-     * @param visitor the visitor
-     */
-    void visit(SettingVisitor visitor);
-
-    /**
-     * Returns a setting whose value is null.
-     *
-     * Cannot be static, because there is no static inheritance.
-     * @return a Setting object that isn't null itself, but returns null
-     * for {@link #getValue()}
-     */
-    Setting<T> getNullInstance();
-
-    /**
-     * Set the time for this setting.
-     *
-     * For default preferences. They are saved in a cache file. Keeping the
-     * time allows to discard very old default settings.
-     * @param time the time in seconds since epoch
-     */
-    void setTime(Long time);
-
-    /**
-     * Get the time for this setting.
-     * @return the time for this setting
-     * @see #setTime(java.lang.Long)
-     */
-    Long getTime();
-
-    /**
-     * Mark setting as new.
-     *
-     * For default preferences. A setting is marked as new, if it has been seen
-     * in the current session.
-     * Methods like {@link Preferences#get(java.lang.String, java.lang.String)},
-     * can be called from different parts of the code with the same key. In this case,
-     * the supplied default value must match. However, this is only an error if the mismatching
-     * default value has been seen in the same session (and not loaded from cache).
-     * @param isNew true, if it is new
-     */
-    void setNew(boolean isNew);
-
-    /**
-     * Return if the setting has been marked as new.
-     * @return true, if the setting has been marked as new
-     * @see #setNew(boolean)
-     */
-    boolean isNew();
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/SettingVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/SettingVisitor.java	(revision 12880)
+++ 	(revision )
@@ -1,32 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-/**
- * Visitor interface for {@link Setting} implementations.
- * @since 9759
- */
-public interface SettingVisitor {
-    /**
-     * Visitor call for {@link StringSetting}.
-     * @param value string setting
-     */
-    void visit(StringSetting value);
-
-    /**
-     * Visitor call for {@link ListSetting}.
-     * @param value list setting
-     */
-    void visit(ListSetting value);
-
-    /**
-     * Visitor call for {@link ListListSetting}.
-     * @param value list list setting
-     */
-    void visit(ListListSetting value);
-
-    /**
-     * Visitor call for {@link MapListSetting}.
-     * @param value map list setting
-     */
-    void visit(MapListSetting value);
-}
Index: trunk/src/org/openstreetmap/josm/data/preferences/StringSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/StringSetting.java	(revision 12880)
+++ 	(revision )
@@ -1,31 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.preferences;
-
-/**
- * Setting containing a {@link String} value.
- * @since 9759
- */
-public class StringSetting extends AbstractSetting<String> {
-    /**
-     * Constructs a new {@code StringSetting} with the given value
-     * @param value The setting value
-     */
-    public StringSetting(String value) {
-        super(value);
-    }
-
-    @Override
-    public StringSetting copy() {
-        return new StringSetting(value);
-    }
-
-    @Override
-    public void visit(SettingVisitor visitor) {
-        visitor.visit(this);
-    }
-
-    @Override
-    public StringSetting getNullInstance() {
-        return new StringSetting(null);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java	(revision 12881)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.gui;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.osm.User;
Index: trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 12881)
@@ -51,5 +51,5 @@
 import org.openstreetmap.josm.actions.mapmode.SelectAction;
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
Index: trunk/src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 12881)
@@ -19,6 +19,6 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.mapmode.SelectAction;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
Index: trunk/src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 12881)
@@ -56,6 +56,6 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.SystemOfMeasurement.SoMChangeListener;
Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 12881)
@@ -41,6 +41,6 @@
 import org.openstreetmap.josm.actions.mapmode.MapMode;
 import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.ViewportData;
Index: trunk/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java	(revision 12881)
@@ -22,6 +22,6 @@
 
 import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.osm.BBox;
 import org.openstreetmap.josm.data.osm.DataSet;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 12881)
@@ -50,6 +50,6 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.data.preferences.ParametrizedEnumProperty;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 12881)
@@ -63,5 +63,5 @@
 import org.openstreetmap.josm.command.ChangePropertyCommand;
 import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
Index: trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java	(revision 12881)
@@ -45,5 +45,5 @@
 import org.openstreetmap.josm.data.PreferencesUtils;
 import org.openstreetmap.josm.data.Version;
-import org.openstreetmap.josm.data.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Setting;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.plugins.PluginDownloadTask;
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 12881)
@@ -43,11 +43,11 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.APIDataSet;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Setting;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
Index: trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(revision 12881)
@@ -24,5 +24,5 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.coor.CachedLatLon;
 import org.openstreetmap.josm.data.coor.EastNorth;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 12881)
@@ -11,6 +11,6 @@
 import java.util.Map.Entry;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LabelCompositionStrategy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LabelCompositionStrategy.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LabelCompositionStrategy.java	(revision 12881)
@@ -8,6 +8,6 @@
 import java.util.Objects;
 
-import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.spi.preferences.Config;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 12881)
@@ -40,6 +40,6 @@
 import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.PreferencesUtils;
-import org.openstreetmap.josm.data.preferences.Setting;
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.gui.dialogs.LogShowDialog;
 import org.openstreetmap.josm.gui.io.CustomConfigurator;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ExportProfileAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ExportProfileAction.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ExportProfileAction.java	(revision 12881)
@@ -20,5 +20,5 @@
 import org.openstreetmap.josm.actions.DiskAccessAction;
 import org.openstreetmap.josm.data.Preferences;
-import org.openstreetmap.josm.data.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Setting;
 import org.openstreetmap.josm.gui.io.CustomConfigurator;
 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListEditor.java	(revision 12881)
@@ -16,5 +16,5 @@
 import javax.swing.table.AbstractTableModel;
 
-import org.openstreetmap.josm.data.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.tools.GBC;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/ListListEditor.java	(revision 12881)
@@ -12,5 +12,5 @@
 import javax.swing.table.AbstractTableModel;
 
-import org.openstreetmap.josm.data.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
 
 /**
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/MapListEditor.java	(revision 12881)
@@ -16,5 +16,5 @@
 import javax.swing.table.AbstractTableModel;
 
-import org.openstreetmap.josm.data.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
 
 /**
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PrefEntry.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PrefEntry.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PrefEntry.java	(revision 12881)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.gui.preferences.advanced;
 
-import org.openstreetmap.josm.data.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Setting;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTable.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTable.java	(revision 12881)
@@ -30,9 +30,9 @@
 
 import org.openstreetmap.josm.data.preferences.ColorProperty;
-import org.openstreetmap.josm.data.preferences.ListListSetting;
-import org.openstreetmap.josm.data.preferences.ListSetting;
-import org.openstreetmap.josm.data.preferences.MapListSetting;
-import org.openstreetmap.josm.data.preferences.Setting;
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.ListListSetting;
+import org.openstreetmap.josm.spi.preferences.ListSetting;
+import org.openstreetmap.josm.spi.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.util.GuiHelper;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/StringEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/StringEditor.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/StringEditor.java	(revision 12881)
@@ -10,5 +10,5 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.data.preferences.StringSetting;
+import org.openstreetmap.josm.spi.preferences.StringSetting;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
Index: trunk/src/org/openstreetmap/josm/spi/preferences/AbstractPreferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/AbstractPreferences.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/AbstractPreferences.java	(revision 12881)
@@ -5,9 +5,4 @@
 import java.util.Map;
 
-import org.openstreetmap.josm.data.preferences.ListListSetting;
-import org.openstreetmap.josm.data.preferences.ListSetting;
-import org.openstreetmap.josm.data.preferences.MapListSetting;
-import org.openstreetmap.josm.data.preferences.Setting;
-import org.openstreetmap.josm.data.preferences.StringSetting;
 import org.openstreetmap.josm.tools.Logging;
 
Index: trunk/src/org/openstreetmap/josm/spi/preferences/AbstractSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/AbstractSetting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/AbstractSetting.java	(revision 12881)
@@ -0,0 +1,69 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+import java.util.Objects;
+
+/**
+ * Base abstract class of all settings, holding the setting value.
+ *
+ * @param <T> The setting type
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public abstract class AbstractSetting<T> implements Setting<T> {
+    protected final T value;
+    protected Long time;
+    protected boolean isNew;
+    /**
+     * Constructs a new {@code AbstractSetting} with the given value
+     * @param value The setting value
+     */
+    public AbstractSetting(T value) {
+        this.value = value;
+        this.time = null;
+        this.isNew = false;
+    }
+
+    @Override
+    public T getValue() {
+        return value;
+    }
+
+    @Override
+    public void setTime(Long time) {
+        this.time = time;
+    }
+
+    @Override
+    public Long getTime() {
+        return this.time;
+    }
+
+    @Override
+    public void setNew(boolean isNew) {
+        this.isNew = isNew;
+    }
+
+    @Override
+    public boolean isNew() {
+        return isNew;
+    }
+
+    @Override
+    public String toString() {
+        return value != null ? value.toString() : "null";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        return Objects.equals(value, ((AbstractSetting<?>) obj).value);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/DefaultPreferenceChangeEvent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/DefaultPreferenceChangeEvent.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/DefaultPreferenceChangeEvent.java	(revision 12881)
@@ -0,0 +1,35 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Default implementation of the {@link PreferenceChangeEvent} interface.
+ * @since xxx
+ */
+public class DefaultPreferenceChangeEvent implements PreferenceChangeEvent {
+    
+    private final String key;
+    private final Setting<?> oldValue;
+    private final Setting<?> newValue;
+
+    public DefaultPreferenceChangeEvent(String key, Setting<?> oldValue, Setting<?> newValue) {
+        this.key = key;
+        this.oldValue = oldValue;
+        this.newValue = newValue;
+    }
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @Override
+    public Setting<?> getOldValue() {
+        return oldValue;
+    }
+
+    @Override
+    public Setting<?> getNewValue() {
+        return newValue;
+    }
+    
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/IPreferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/IPreferences.java	(revision 12880)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/IPreferences.java	(revision 12881)
@@ -5,6 +5,4 @@
 import java.util.List;
 import java.util.Map;
-
-import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 
 /**
Index: trunk/src/org/openstreetmap/josm/spi/preferences/ListListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/ListListSetting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/ListListSetting.java	(revision 12881)
@@ -0,0 +1,74 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Setting containing a {@link List} of {@code List}s of {@link String} values.
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public class ListListSetting extends AbstractSetting<List<List<String>>> {
+
+    /**
+     * Constructs a new {@code ListListSetting} with the given value
+     * @param value The setting value
+     */
+    public ListListSetting(List<List<String>> value) {
+        super(value);
+        consistencyTest();
+    }
+
+    /**
+     * Convenience factory method.
+     * @param value the value
+     * @return a corresponding ListListSetting object
+     */
+    public static ListListSetting create(Collection<Collection<String>> value) {
+        if (value != null) {
+            List<List<String>> valueList = new ArrayList<>(value.size());
+            for (Collection<String> lst : value) {
+                valueList.add(new ArrayList<>(lst));
+            }
+            return new ListListSetting(valueList);
+        }
+        return new ListListSetting(null);
+    }
+
+    @Override
+    public ListListSetting copy() {
+        if (value == null)
+            return new ListListSetting(null);
+
+        List<List<String>> copy = new ArrayList<>(value.size());
+        for (Collection<String> lst : value) {
+            List<String> lstCopy = new ArrayList<>(lst);
+            copy.add(Collections.unmodifiableList(lstCopy));
+        }
+        return new ListListSetting(Collections.unmodifiableList(copy));
+    }
+
+    private void consistencyTest() {
+        if (value != null) {
+            if (value.contains(null))
+                throw new IllegalArgumentException("Error: Null as list element in preference setting");
+            for (Collection<String> lst : value) {
+                if (lst.contains(null)) {
+                    throw new IllegalArgumentException("Error: Null as inner list element in preference setting");
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visit(SettingVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public ListListSetting getNullInstance() {
+        return new ListListSetting(null);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/ListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/ListSetting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/ListSetting.java	(revision 12881)
@@ -0,0 +1,51 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Setting containing a {@link List} of {@link String} values.
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public class ListSetting extends AbstractSetting<List<String>> {
+    /**
+     * Constructs a new {@code ListSetting} with the given value
+     * @param value The setting value
+     */
+    public ListSetting(List<String> value) {
+        super(value);
+        consistencyTest();
+    }
+
+    /**
+     * Convenience factory method.
+     * @param value the value
+     * @return a corresponding ListSetting object
+     */
+    public static ListSetting create(Collection<String> value) {
+        return new ListSetting(value == null ? null : Collections.unmodifiableList(new ArrayList<>(value)));
+    }
+
+    @Override
+    public ListSetting copy() {
+        return ListSetting.create(value);
+    }
+
+    private void consistencyTest() {
+        if (value != null && value.contains(null))
+            throw new IllegalArgumentException("Error: Null as list element in preference setting");
+    }
+
+    @Override
+    public void visit(SettingVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public ListSetting getNullInstance() {
+        return new ListSetting(null);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/MapListSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/MapListSetting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/MapListSetting.java	(revision 12881)
@@ -0,0 +1,59 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Setting containing a {@link List} of {@link Map}s of {@link String} values.
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public class MapListSetting extends AbstractSetting<List<Map<String, String>>> {
+
+    /**
+     * Constructs a new {@code MapListSetting} with the given value
+     * @param value The setting value
+     */
+    public MapListSetting(List<Map<String, String>> value) {
+        super(value);
+        consistencyTest();
+    }
+
+    @Override
+    public MapListSetting copy() {
+        if (value == null)
+            return new MapListSetting(null);
+        List<Map<String, String>> copy = new ArrayList<>(value.size());
+        for (Map<String, String> map : value) {
+            Map<String, String> mapCopy = new LinkedHashMap<>(map);
+            copy.add(Collections.unmodifiableMap(mapCopy));
+        }
+        return new MapListSetting(Collections.unmodifiableList(copy));
+    }
+
+    private void consistencyTest() {
+        if (value == null)
+            return;
+        if (value.contains(null))
+            throw new IllegalArgumentException("Error: Null as list element in preference setting");
+        for (Map<String, String> map : value) {
+            if (map.containsKey(null))
+                throw new IllegalArgumentException("Error: Null as map key in preference setting");
+            if (map.containsValue(null))
+                throw new IllegalArgumentException("Error: Null as map value in preference setting");
+        }
+    }
+
+    @Override
+    public void visit(SettingVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public MapListSetting getNullInstance() {
+        return new MapListSetting(null);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangeEvent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangeEvent.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangeEvent.java	(revision 12881)
@@ -0,0 +1,28 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Event triggered when a preference entry value changes.
+ * @since xxx
+ */
+public interface PreferenceChangeEvent {
+
+    /**
+     * Returns the preference key.
+     * @return the preference key
+     */
+    String getKey();
+
+    /**
+     * Returns the old preference value.
+     * @return the old preference value
+     */
+    Setting<?> getOldValue();
+
+    /**
+     * Returns the new preference value.
+     * @return the new preference value
+     */
+    Setting<?> getNewValue();
+    
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangedListener.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangedListener.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangedListener.java	(revision 12881)
@@ -0,0 +1,17 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Listener to preference change events.
+ * @since xxx
+ */
+@FunctionalInterface
+public interface PreferenceChangedListener {
+
+    /**
+     * Triggered when a preference entry value changes.
+     * @param e the preference change event
+     */
+    void preferenceChanged(PreferenceChangeEvent e);
+    
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/Setting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/Setting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/Setting.java	(revision 12881)
@@ -0,0 +1,86 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Interface for a preference value.
+ *
+ * Implementations must provide a proper <code>equals</code> method.
+ *
+ * @param <T> the data type for the value
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public interface Setting<T> {
+    /**
+     * Returns the value of this setting.
+     *
+     * @return the value of this setting
+     */
+    T getValue();
+
+    /**
+     * Check if the value of this Setting object is equal to the given value.
+     * @param otherVal the other value
+     * @return true if the values are equal
+     */
+    default boolean equalVal(T otherVal) {
+        return getValue() == null ? (otherVal == null) : getValue().equals(otherVal);
+    }
+
+    /**
+     * Clone the current object.
+     * @return an identical copy of the current object
+     */
+    Setting<T> copy();
+
+    /**
+     * Enable usage of the visitor pattern.
+     *
+     * @param visitor the visitor
+     */
+    void visit(SettingVisitor visitor);
+
+    /**
+     * Returns a setting whose value is null.
+     *
+     * Cannot be static, because there is no static inheritance.
+     * @return a Setting object that isn't null itself, but returns null
+     * for {@link #getValue()}
+     */
+    Setting<T> getNullInstance();
+
+    /**
+     * Set the time for this setting.
+     *
+     * For default preferences. They are saved in a cache file. Keeping the
+     * time allows to discard very old default settings.
+     * @param time the time in seconds since epoch
+     */
+    void setTime(Long time);
+
+    /**
+     * Get the time for this setting.
+     * @return the time for this setting
+     * @see #setTime(java.lang.Long)
+     */
+    Long getTime();
+
+    /**
+     * Mark setting as new.
+     *
+     * For default preferences. A setting is marked as new, if it has been seen
+     * in the current session.
+     * Methods like {@link IPreferences#get(java.lang.String, java.lang.String)},
+     * can be called from different parts of the code with the same key. In this case,
+     * the supplied default value must match. However, this is only an error if the mismatching
+     * default value has been seen in the same session (and not loaded from cache).
+     * @param isNew true, if it is new
+     */
+    void setNew(boolean isNew);
+
+    /**
+     * Return if the setting has been marked as new.
+     * @return true, if the setting has been marked as new
+     * @see #setNew(boolean)
+     */
+    boolean isNew();
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/SettingVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/SettingVisitor.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/SettingVisitor.java	(revision 12881)
@@ -0,0 +1,32 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Visitor interface for {@link Setting} implementations.
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public interface SettingVisitor {
+    /**
+     * Visitor call for {@link StringSetting}.
+     * @param value string setting
+     */
+    void visit(StringSetting value);
+
+    /**
+     * Visitor call for {@link ListSetting}.
+     * @param value list setting
+     */
+    void visit(ListSetting value);
+
+    /**
+     * Visitor call for {@link ListListSetting}.
+     * @param value list list setting
+     */
+    void visit(ListListSetting value);
+
+    /**
+     * Visitor call for {@link MapListSetting}.
+     * @param value map list setting
+     */
+    void visit(MapListSetting value);
+}
Index: trunk/src/org/openstreetmap/josm/spi/preferences/StringSetting.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/StringSetting.java	(revision 12881)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/StringSetting.java	(revision 12881)
@@ -0,0 +1,31 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Setting containing a {@link String} value.
+ * @since xxx (moved from package {@code org.openstreetmap.josm.data.preferences})
+ */
+public class StringSetting extends AbstractSetting<String> {
+    /**
+     * Constructs a new {@code StringSetting} with the given value
+     * @param value The setting value
+     */
+    public StringSetting(String value) {
+        super(value);
+    }
+
+    @Override
+    public StringSetting copy() {
+        return new StringSetting(value);
+    }
+
+    @Override
+    public void visit(SettingVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public StringSetting getNullInstance() {
+        return new StringSetting(null);
+    }
+}
