Index: trunk/src/org/openstreetmap/josm/actions/ValidateAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ValidateAction.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/actions/ValidateAction.java	(revision 6529)
@@ -18,5 +18,5 @@
 import org.openstreetmap.josm.data.validation.util.AggregatePrimitivesVisitor;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.io.OsmTransferException;
Index: trunk/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java	(revision 6529)
@@ -24,5 +24,5 @@
 import org.openstreetmap.josm.gui.dialogs.validator.ValidatorTreePanel;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.tools.GBC;
Index: trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 6529)
@@ -29,5 +29,4 @@
 import org.openstreetmap.josm.data.validation.tests.Coastlines;
 import org.openstreetmap.josm.data.validation.tests.CrossingWays;
-import org.openstreetmap.josm.data.validation.tests.DeprecatedTags;
 import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
 import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
@@ -59,6 +58,6 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.ValidatorLayer;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -219,7 +218,7 @@
     }
 
-    /** 
-     * Gets a map from simple names to all tests. 
-     * @return A map of all tests, indexed by the simple name of their Java class 
+    /**
+     * Gets a map from simple names to all tests.
+     * @return A map of all tests, indexed by the simple name of their Java class
      */
     public static Map<String, Test> getAllTestsMap() {
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/DeprecatedTags.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/DeprecatedTags.java	(revision 6528)
+++ 	(revision )
@@ -1,348 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.validation.tests;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.openstreetmap.josm.command.ChangePropertyCommand;
-import org.openstreetmap.josm.command.ChangePropertyKeyCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Tag;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.validation.Severity;
-import org.openstreetmap.josm.data.validation.Test;
-import org.openstreetmap.josm.data.validation.TestError;
-import org.openstreetmap.josm.tools.Utils;
-
-/**
- * Checks and corrects deprecated and unnecessary tags.
- * @since 4442
- */
-public class DeprecatedTags extends Test {
-
-    private final List<DeprecationCheck> checks = new LinkedList<DeprecationCheck>();
-
-    /**
-     * Constructs a new {@code DeprecatedTags} test.
-     */
-    public DeprecatedTags() {
-        super(tr("Deprecated Tags"), tr("Checks and corrects deprecated tags."));
-        checks.add(new DeprecationCheck(2101).
-                testAndRemove("barrier", "wire_fence").
-                add("barrier", "fence").
-                add("fence_type", "chain_link"));
-        checks.add(new DeprecationCheck(2102).
-                testAndRemove("barrier", "wood_fence").
-                add("barrier", "fence").
-                add("fence_type", "wood"));
-        checks.add(new DeprecationCheck(2103).
-                testAndRemove("highway", "ford").
-                add("ford", "yes"));
-        // from http://wiki.openstreetmap.org/wiki/Deprecated_features
-        checks.add(new DeprecationCheck(2104).
-                test("class").
-                alternative("highway"));
-        checks.add(new DeprecationCheck(2105).
-                testAndRemove("highway", "stile").
-                add("barrier", "stile"));
-        checks.add(new DeprecationCheck(2106).
-                test("highway", "incline").
-                alternative("incline"));
-        checks.add(new DeprecationCheck(2107).
-                test("highway", "incline").
-                alternative("incline"));
-        checks.add(new DeprecationCheck(2108).
-                testAndRemove("highway", "unsurfaced").
-                add("highway", "road").
-                add("incline", "unpaved"));
-        checks.add(new DeprecationCheck(2109).
-                test("landuse", "wood").
-                alternative("landuse", "forest").
-                alternative("natural", "wood"));
-        checks.add(new DeprecationCheck(2110).
-                testAndRemove("natural", "marsh").
-                add("natural", "wetland").
-                add("wetland", "marsh"));
-        checks.add(new DeprecationCheck(2111).
-                test("highway", "byway"));
-        checks.add(new DeprecationCheck(2112).
-                test("power_source").
-                alternative("generator:source"));
-        checks.add(new DeprecationCheck(2113).
-                test("power_rating").
-                alternative("generator:output"));
-        // from http://wiki.openstreetmap.org/wiki/Tag:shop=organic
-        checks.add(new DeprecationCheck(2114).
-                testAndRemove("shop", "organic").
-                add("shop", "supermarket").
-                add("organic", "only"));
-        // from http://wiki.openstreetmap.org/wiki/Key:bicycle_parking
-        checks.add(new DeprecationCheck(2115).
-                testAndRemove("bicycle_parking", "sheffield").
-                add("bicycle_parking", "stands"));
-        // http://wiki.openstreetmap.org/wiki/Tag:emergency=phone
-        checks.add(new DeprecationCheck(2116).
-                testAndRemove("amenity", "emergency_phone").
-                add("emergency", "phone"));
-        // fix #8132 - http://wiki.openstreetmap.org/wiki/Tag:sport=gaelic_football
-        checks.add(new DeprecationCheck(2117).
-                testAndRemove("sport", "gaelic_football").
-                add("sport", "gaelic_games"));
-        // see #8847 / #8961 - http://wiki.openstreetmap.org/wiki/Tag:power=station
-        checks.add(new DeprecationCheck(2118).
-                test("power", "station").
-                alternative("power", "plant").
-                alternative("power", "sub_station"));
-        checks.add(new DeprecationCheck(2119).
-                testAndRemove("generator:method", "dam").
-                add("generator:method", "water-storage"));
-        checks.add(new DeprecationCheck(2120).
-                testAndRemove("generator:method", "pumped-storage").
-                add("generator:method", "water-pumped-storage"));
-        checks.add(new DeprecationCheck(2121).
-                testAndRemove("generator:method", "pumping").
-                add("generator:method", "water-pumped-storage"));
-        // see #8962 - http://wiki.openstreetmap.org/wiki/Key:fence_type
-        checks.add(new DeprecationCheck(2122).
-                test("fence_type", "chain").
-                alternative("barrier", "chain").
-                alternative("fence_type", "chain_link"));
-        // see #9000 - http://wiki.openstreetmap.org/wiki/Key:entrance
-        checks.add(new DeprecationCheck(2123).
-                test("building", "entrance").
-                alternative("entrance"));
-        // see #9213 - Useless tag proposed in internal preset for years
-        checks.add(new DeprecationCheck(2124).
-                testAndRemove("board_type", "board"));
-        // see #8434 - http://wiki.openstreetmap.org/wiki/Proposed_features/monitoring_station
-        checks.add(new DeprecationCheck(2125).
-                testAndRemove("man_made", "measurement_station").
-                add("man_made", "monitoring_station"));
-        checks.add(new DeprecationCheck(2126).
-                testAndRemove("measurement", "water_level").
-                add("monitoring:water_level", "yes"));
-        checks.add(new DeprecationCheck(2127).
-                testAndRemove("measurement", "weather").
-                add("monitoring:weather", "yes"));
-        checks.add(new DeprecationCheck(2128).
-                testAndRemove("measurement", "seismic").
-                add("monitoring:seismic_activity", "yes"));
-        checks.add(new DeprecationCheck(2129).
-                test("monitoring:river_level").
-                changeKey("monitoring:river_level", "monitoring:water_level"));
-        // see #9365 - Useless tag layer=0
-        checks.add(new UnnecessaryTagCheck(2130).
-                testAndRemove("layer", "0"));
-    }
-
-    /**
-     * Visiting call for primitives.
-     * @param p The primitive to inspect.
-     */
-    public void visit(OsmPrimitive p) {
-        for (DeprecationCheck check : checks) {
-            if (check.matchesPrimitive(p)) {
-                errors.add(new DeprecationError(p, check));
-            }
-        }
-    }
-
-    @Override
-    public void visit(Node n) {
-        visit((OsmPrimitive) n);
-    }
-
-    @Override
-    public void visit(Way w) {
-        visit((OsmPrimitive) w);
-    }
-
-    @Override
-    public void visit(Relation r) {
-        visit((OsmPrimitive) r);
-    }
-
-    /**
-     * Represents on deprecation check consisting of a series of {@code test}s,
-     * automatic {@code change}s/{@code keyChange}s (fixes for the deprecated tag),
-     * or a suggestion of tagging {@code alternatives}.
-     */
-    private static class DeprecationCheck {
-
-        private int code;
-        protected final List<Tag> test = new LinkedList<Tag>();
-        protected final List<Tag> change = new LinkedList<Tag>();
-        protected final Map<String, String> keyChange = new LinkedHashMap<String, String>();
-        protected final List<Tag> alternatives = new LinkedList<Tag>();
-
-        /**
-         * Creates a new {@code DeprecationCheck}.
-         * @param code {@link TestError#code}
-         */
-        public DeprecationCheck(int code) {
-            this.code = code;
-        }
-
-        /**
-         * Adds a test criterion which matches primitives with tag {@code key=value}.
-         * @return {@code this}
-         */
-        DeprecationCheck test(String key, String value) {
-            test.add(new Tag(key, value));
-            return this;
-        }
-
-        /**
-         * Adds a test criterion which matches primitives with key {@code key}.
-         * @return {@code this}
-         */
-        DeprecationCheck test(String key) {
-            return test(key, null);
-        }
-
-        /**
-         * Adds an automatic fix which sets/adds the tag {@code key=value}.
-         * @return {@code this}
-         * @see #alternative(String, String)
-         * @see #alternative(String)
-         */
-        DeprecationCheck add(String key, String value) {
-            change.add(new Tag(key, value));
-            return this;
-        }
-
-        /**
-         * Adds an automatic fix which removes the key {@code key}.
-         * @return {@code this}
-         */
-        DeprecationCheck remove(String key) {
-            change.add(new Tag(key));
-            return this;
-        }
-
-        /**
-         * Adds an automatic fix which changes the key {@code oldKey} to {@code newKey}.
-         * @return {@code this}
-         */
-        DeprecationCheck changeKey(String oldKey, String newKey) {
-            keyChange.put(oldKey, newKey);
-            return this;
-        }
-
-        /**
-         * Adds a test criterion which matches primitives with tag {@code key=value},
-         * and an automatic fix which removes the key {@code key}.
-         * Equivalent to {@link #test(String, String)} plus {@link #remove(String)}.
-         * @return {@code this}
-         */
-        DeprecationCheck testAndRemove(String key, String value) {
-            return test(key, value).remove(key);
-        }
-
-        /**
-         * Adds a suggestion to use an alternative tag {@code key=value} instead of the deprecated tag.
-         * This is used for cases where no automatic fix is sensible.
-         * @return {@code this}
-         */
-        DeprecationCheck alternative(String key, String value) {
-            alternatives.add(new Tag(key, value));
-            return this;
-        }
-
-        /**
-         * Adds a suggestion to use an alternative key {@code key} instead of the deprecated tag.
-         * This is used for cases where no automatic fix is sensible.
-         * @return {@code this}
-         */
-        DeprecationCheck alternative(String key) {
-            return alternative(key, null);
-        }
-
-        /**
-         * Tests whether the {@link OsmPrimitive} contains a deprecated tag which is represented by this {@code DeprecationCheck}.
-         * @param p the primitive to test
-         * @return true when the primitive contains a deprecated tag
-         */
-        boolean matchesPrimitive(OsmPrimitive p) {
-            for (Tag tag : test) {
-                String key = tag.getKey();
-                String value = tag.getValue();
-                if (value.isEmpty() && !p.hasKey(key))
-                    return false;
-                if (!value.isEmpty() && !value.equals(p.get(key)))
-                    return false;
-            }
-            return true;
-        }
-
-        /**
-         * Constructs a fix in terms of a {@link Command} for the {@link OsmPrimitive}.
-         * @param p the primitive to construct the fix for
-         * @return the fix
-         */
-        Command fixPrimitive(OsmPrimitive p) {
-            Collection<Command> cmds = new LinkedList<Command>();
-            for (Tag tag : change) {
-                cmds.add(new ChangePropertyCommand(p, tag.getKey(), tag.getValue()));
-            }
-            for (Map.Entry<String, String> i : keyChange.entrySet()) {
-                cmds.add(new ChangePropertyKeyCommand(p, i.getKey(), i.getValue()));
-            }
-            return new SequenceCommand(tr("Deprecation fix of {0}", Utils.join(", ", test)), cmds);
-        }
-
-        /**
-         * Constructs a localized description for this deprecation check.
-         * @return a localized description
-         */
-        String getDescription() {
-            if (alternatives.isEmpty())
-                return tr("{0} is deprecated", Utils.join(", ", test));
-            else
-                return tr("{0} is deprecated, use {1} instead", Utils.join(", ", test), Utils.join(tr(" or "), alternatives));
-        }
-    }
-    
-    private static class UnnecessaryTagCheck extends DeprecationCheck {
-
-        public UnnecessaryTagCheck(int code) {
-            super(code);
-        }
-
-        @Override
-        String getDescription() {
-            return tr("{0} is unnecessary", Utils.join(", ", test));
-        }
-    }
-
-    private class DeprecationError extends TestError {
-
-        private OsmPrimitive p;
-        private DeprecationCheck check;
-
-        public DeprecationError(OsmPrimitive p, DeprecationCheck check) {
-            super(DeprecatedTags.this, Severity.WARNING, check.getDescription(), check.code, p);
-            this.p = p;
-            this.check = check;
-        }
-
-        @Override
-        public boolean isFixable() {
-            return !check.change.isEmpty() || !check.keyChange.isEmpty();
-        }
-
-        @Override
-        public Command getFix() {
-            return check.fixPrimitive(p);
-        }
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(revision 6529)
@@ -1,4 +1,17 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.validation.tests;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 import org.openstreetmap.josm.command.ChangePropertyCommand;
@@ -27,18 +40,13 @@
 import org.openstreetmap.josm.tools.Utils;
 
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
+/**
+ * MapCSS-based tag checker/fixer.
+ * @since 6506
+ */
 public class MapCSSTagChecker extends Test {
 
+    /**
+     * Constructs a new {@code MapCSSTagChecker}.
+     */
     public MapCSSTagChecker() {
         super(tr("Tag checker (new)"), tr("This test checks for errors in tag keys and values."));
@@ -222,12 +230,27 @@
     }
 
+    /**
+     * Adds a new MapCSS config file from the given {@code Reader}.
+     * @param css The reader
+     * @throws ParseException if the config file does not match MapCSS syntax
+     */
     public void addMapCSS(Reader css) throws ParseException {
         checks.addAll(TagCheck.readMapCSS(css));
     }
 
+    /**
+     * Adds a new MapCSS config file from the given internal filename.
+     * @param internalConfigFile the filename in data/validator
+     * @throws ParseException if the config file does not match MapCSS syntax
+     * @throws UnsupportedEncodingException if UTF-8 charset is not supported on the platform
+     */
+    private void addMapCSS(String internalConfigFile) throws ParseException, UnsupportedEncodingException {
+        addMapCSS(new InputStreamReader(getClass().getResourceAsStream("/data/validator/"+internalConfigFile), "UTF-8"));
+    }
+
     @Override
     public void initialize() throws Exception {
-        addMapCSS(new InputStreamReader(getClass().getResourceAsStream("/data/validator/deprecated.mapcss"), "UTF-8"));
-        addMapCSS(new InputStreamReader(getClass().getResourceAsStream("/data/validator/highway.mapcss"), "UTF-8"));
+        addMapCSS("deprecated.mapcss");
+        addMapCSS("highway.mapcss");
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 6529)
@@ -52,6 +52,6 @@
 import org.openstreetmap.josm.data.validation.TestError;
 import org.openstreetmap.josm.data.validation.util.Entities;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
 import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.gui.tagging.TaggingPreset;
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java	(revision 6529)
@@ -29,5 +29,5 @@
 import org.openstreetmap.josm.data.validation.Test;
 import org.openstreetmap.josm.data.validation.TestError;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 6529)
@@ -47,5 +47,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 6529)
@@ -29,5 +29,5 @@
 import org.openstreetmap.josm.data.validation.TestError;
 import org.openstreetmap.josm.data.validation.util.MultipleNameVisitor;
-import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.MultiMap;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java	(revision 6528)
+++ 	(revision )
@@ -1,145 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.preferences;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.GridBagLayout;
-
-import javax.swing.Box;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.tools.GBC;
-
-/*
- * marker.audiosampleminsecs
- * marker.audiosampleminmetres
- * marker.buttonlabels
- * markers.namedtrackpoints
- * audio.forwardbackamount
- * audio.leadin
- * audio.menuinvisible
- * marker.audiotraceVisible
- * audio.toolbar ??
- */
-
-public final class AudioPreference extends DefaultTabPreferenceSetting {
-
-    public static class Factory implements PreferenceSettingFactory {
-        @Override
-        public PreferenceSetting createPreferenceSetting() {
-            return new AudioPreference();
-        }
-    }
-
-    private AudioPreference() {
-        super("audio", tr("Audio Settings"), tr("Settings for the audio player and audio markers."));
-    }
-
-    private JCheckBox audioMenuVisible = new JCheckBox(tr("Display the Audio menu."));
-    private JCheckBox markerButtonLabels = new JCheckBox(tr("Label audio (and image and web) markers."));
-    private JCheckBox markerAudioTraceVisible = new JCheckBox(tr("Display live audio trace."));
-
-    // various methods of making markers on import audio
-    private JCheckBox audioMarkersFromExplicitWaypoints = new JCheckBox(tr("Explicit waypoints with valid timestamps."));
-    private JCheckBox audioMarkersFromUntimedWaypoints = new JCheckBox(tr("Explicit waypoints with time estimated from track position."));
-    private JCheckBox audioMarkersFromNamedTrackpoints = new JCheckBox(tr("Named trackpoints."));
-    private JCheckBox audioMarkersFromWavTimestamps = new JCheckBox(tr("Modified times (time stamps) of audio files."));
-    private JCheckBox audioMarkersFromStart = new JCheckBox(tr("Start of track (will always do this if no other markers available)."));
-
-    private JosmTextField audioLeadIn = new JosmTextField(8);
-    private JosmTextField audioForwardBackAmount = new JosmTextField(8);
-    private JosmTextField audioFastForwardMultiplier = new JosmTextField(8);
-    private JosmTextField audioCalibration = new JosmTextField(8);
-
-    @Override
-    public void addGui(PreferenceTabbedPane gui) {
-        JPanel audio = new JPanel(new GridBagLayout());
-
-        // audioMenuVisible
-        audioMenuVisible.setSelected(! Main.pref.getBoolean("audio.menuinvisible"));
-        audioMenuVisible.setToolTipText(tr("Show or hide the audio menu entry on the main menu bar."));
-        audio.add(audioMenuVisible, GBC.eol().insets(0,0,0,0));
-
-        // audioTraceVisible
-        markerAudioTraceVisible.setSelected(Main.pref.getBoolean("marker.traceaudio", true));
-        markerAudioTraceVisible.setToolTipText(tr("Display a moving icon representing the point on the synchronized track where the audio currently playing was recorded."));
-        audio.add(markerAudioTraceVisible, GBC.eol().insets(0,0,0,0));
-
-        // buttonLabels
-        markerButtonLabels.setSelected(Main.pref.getBoolean("marker.buttonlabels", true));
-        markerButtonLabels.setToolTipText(tr("Put text labels against audio (and image and web) markers as well as their button icons."));
-        audio.add(markerButtonLabels, GBC.eol().insets(0,0,0,0));
-
-        audio.add(new JLabel(tr("When importing audio, make markers from...")), GBC.eol());
-
-        // audioMarkersFromExplicitWaypoints
-        audioMarkersFromExplicitWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromexplicitwaypoints", true));
-        audioMarkersFromExplicitWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer."));
-        audio.add(audioMarkersFromExplicitWaypoints, GBC.eol().insets(10,0,0,0));
-
-        // audioMarkersFromUntimedWaypoints
-        audioMarkersFromUntimedWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromuntimedwaypoints", true));
-        audioMarkersFromUntimedWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer."));
-        audio.add(audioMarkersFromUntimedWaypoints, GBC.eol().insets(10,0,0,0));
-
-        // audioMarkersFromNamedTrackpoints
-        audioMarkersFromNamedTrackpoints.setSelected(Main.pref.getBoolean("marker.audiofromnamedtrackpoints", false));
-        audioMarkersFromNamedTrackpoints.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions."));
-        audio.add(audioMarkersFromNamedTrackpoints, GBC.eol().insets(10,0,0,0));
-
-        // audioMarkersFromWavTimestamps
-        audioMarkersFromWavTimestamps.setSelected(Main.pref.getBoolean("marker.audiofromwavtimestamps", false));
-        audioMarkersFromWavTimestamps.setToolTipText(tr("Create audio markers at the position on the track corresponding to the modified time of each audio WAV file imported."));
-        audio.add(audioMarkersFromWavTimestamps, GBC.eol().insets(10,0,0,0));
-
-        // audioMarkersFromStart
-        audioMarkersFromStart.setSelected(Main.pref.getBoolean("marker.audiofromstart"));
-        audioMarkersFromStart.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions."));
-        audio.add(audioMarkersFromStart, GBC.eol().insets(10,0,0,0));
-
-        audioForwardBackAmount.setText(Main.pref.get("audio.forwardbackamount", "10.0"));
-        audioForwardBackAmount.setToolTipText(tr("The number of seconds to jump forward or back when the relevant button is pressed"));
-        audio.add(new JLabel(tr("Forward/back time (seconds)")), GBC.std());
-        audio.add(audioForwardBackAmount, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-
-        audioFastForwardMultiplier.setText(Main.pref.get("audio.fastfwdmultiplier", "1.3"));
-        audioFastForwardMultiplier.setToolTipText(tr("The amount by which the speed is multiplied for fast forwarding"));
-        audio.add(new JLabel(tr("Fast forward multiplier")), GBC.std());
-        audio.add(audioFastForwardMultiplier, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-
-        audioLeadIn.setText(Main.pref.get("audio.leadin", "1.0"));
-        audioLeadIn.setToolTipText(tr("Playback starts this number of seconds before (or after, if negative) the audio track position requested"));
-        audio.add(new JLabel(tr("Lead-in time (seconds)")), GBC.std());
-        audio.add(audioLeadIn, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-
-        audioCalibration.setText(Main.pref.get("audio.calibration", "1.0"));
-        audioCalibration.setToolTipText(tr("The ratio of voice recorder elapsed time to true elapsed time"));
-        audio.add(new JLabel(tr("Voice recorder calibration")), GBC.std());
-        audio.add(audioCalibration, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-
-        audio.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
-
-        createPreferenceTabWithScrollPane(gui, audio);
-    }
-
-    @Override
-    public boolean ok() {
-        Main.pref.put("audio.menuinvisible", ! audioMenuVisible.isSelected());
-        Main.pref.put("marker.traceaudio", markerAudioTraceVisible.isSelected());
-        Main.pref.put("marker.buttonlabels", markerButtonLabels.isSelected());
-        Main.pref.put("marker.audiofromexplicitwaypoints", audioMarkersFromExplicitWaypoints.isSelected());
-        Main.pref.put("marker.audiofromuntimedwaypoints", audioMarkersFromUntimedWaypoints.isSelected());
-        Main.pref.put("marker.audiofromnamedtrackpoints", audioMarkersFromNamedTrackpoints.isSelected());
-        Main.pref.put("marker.audiofromwavtimestamps", audioMarkersFromWavTimestamps.isSelected());
-        Main.pref.put("marker.audiofromstart", audioMarkersFromStart.isSelected());
-        Main.pref.put("audio.forwardbackamount", audioForwardBackAmount.getText());
-        Main.pref.put("audio.fastfwdmultiplier", audioFastForwardMultiplier.getText());
-        Main.pref.put("audio.leadin", audioLeadIn.getText());
-        Main.pref.put("audio.calibration", audioCalibration.getText());
-        return false;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java	(revision 6528)
+++ 	(revision )
@@ -1,551 +1,0 @@
-//License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.preferences;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.awt.BorderLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.GridLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.swing.AbstractAction;
-import javax.swing.BorderFactory;
-import javax.swing.DefaultListModel;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Version;
-import org.openstreetmap.josm.gui.HelpAwareOptionPane;
-import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
-import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.PreferencePanel;
-import org.openstreetmap.josm.gui.preferences.plugin.PluginListPanel;
-import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesModel;
-import org.openstreetmap.josm.gui.preferences.plugin.PluginUpdatePolicyPanel;
-import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
-import org.openstreetmap.josm.plugins.PluginDownloadTask;
-import org.openstreetmap.josm.plugins.PluginInformation;
-import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask;
-import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask;
-import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-public final class PluginPreference extends DefaultTabPreferenceSetting {
-    public static class Factory implements PreferenceSettingFactory {
-        @Override
-        public PreferenceSetting createPreferenceSetting() {
-            return new PluginPreference();
-        }
-    }
-
-    private PluginPreference() {
-        super("plugin", tr("Plugins"), tr("Configure available plugins."), false, new JTabbedPane());
-    }
-
-    public static String buildDownloadSummary(PluginDownloadTask task) {
-        Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
-        Collection<PluginInformation> failed = task.getFailedPlugins();
-        StringBuilder sb = new StringBuilder();
-        if (! downloaded.isEmpty()) {
-            sb.append(trn(
-                    "The following plugin has been downloaded <strong>successfully</strong>:",
-                    "The following {0} plugins have been downloaded <strong>successfully</strong>:",
-                    downloaded.size(),
-                    downloaded.size()
-                    ));
-            sb.append("<ul>");
-            for(PluginInformation pi: downloaded) {
-                sb.append("<li>").append(pi.name).append(" (").append(pi.version).append(")").append("</li>");
-            }
-            sb.append("</ul>");
-        }
-        if (! failed.isEmpty()) {
-            sb.append(trn(
-                    "Downloading the following plugin has <strong>failed</strong>:",
-                    "Downloading the following {0} plugins has <strong>failed</strong>:",
-                    failed.size(),
-                    failed.size()
-                    ));
-            sb.append("<ul>");
-            for(PluginInformation pi: failed) {
-                sb.append("<li>").append(pi.name).append("</li>");
-            }
-            sb.append("</ul>");
-        }
-        return sb.toString();
-    }
-
-    private JosmTextField tfFilter;
-    private PluginListPanel pnlPluginPreferences;
-    private PluginPreferencesModel model;
-    private JScrollPane spPluginPreferences;
-    private PluginUpdatePolicyPanel pnlPluginUpdatePolicy;
-
-    /**
-     * is set to true if this preference pane has been selected
-     * by the user
-     */
-    private boolean pluginPreferencesActivated = false;
-
-    protected JPanel buildSearchFieldPanel() {
-        JPanel pnl  = new JPanel(new GridBagLayout());
-        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-        GridBagConstraints gc = new GridBagConstraints();
-
-        gc.anchor = GridBagConstraints.NORTHWEST;
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.weightx = 0.0;
-        gc.insets = new Insets(0,0,0,3);
-        pnl.add(new JLabel(tr("Search:")), gc);
-
-        gc.gridx = 1;
-        gc.weightx = 1.0;
-        pnl.add(tfFilter = new JosmTextField(), gc);
-        tfFilter.setToolTipText(tr("Enter a search expression"));
-        SelectAllOnFocusGainedDecorator.decorate(tfFilter);
-        tfFilter.getDocument().addDocumentListener(new SearchFieldAdapter());
-        return pnl;
-    }
-
-    protected JPanel buildActionPanel() {
-        JPanel pnl = new JPanel(new GridLayout(1,3));
-
-        pnl.add(new JButton(new DownloadAvailablePluginsAction()));
-        pnl.add(new JButton(new UpdateSelectedPluginsAction()));
-        pnl.add(new JButton(new ConfigureSitesAction()));
-        return pnl;
-    }
-
-    protected JPanel buildPluginListPanel() {
-        JPanel pnl = new JPanel(new BorderLayout());
-        pnl.add(buildSearchFieldPanel(), BorderLayout.NORTH);
-        model  = new PluginPreferencesModel();
-        spPluginPreferences = new JScrollPane(pnlPluginPreferences = new PluginListPanel(model));
-        spPluginPreferences.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
-        spPluginPreferences.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
-        spPluginPreferences.getVerticalScrollBar().addComponentListener(
-                new ComponentAdapter(){
-                    @Override
-                    public void componentShown(ComponentEvent e) {
-                        spPluginPreferences.setBorder(UIManager.getBorder("ScrollPane.border"));
-                    }
-                    @Override
-                    public void componentHidden(ComponentEvent e) {
-                        spPluginPreferences.setBorder(null);
-                    }
-                }
-                );
-
-        pnl.add(spPluginPreferences, BorderLayout.CENTER);
-        pnl.add(buildActionPanel(), BorderLayout.SOUTH);
-        return pnl;
-    }
-
-    protected JTabbedPane buildContentPane() {
-        JTabbedPane pane = getTabPane();
-        pane.addTab(tr("Plugins"), buildPluginListPanel());
-        pane.addTab(tr("Plugin update policy"), pnlPluginUpdatePolicy = new PluginUpdatePolicyPanel());
-        return pane;
-    }
-
-    @Override
-    public void addGui(final PreferenceTabbedPane gui) {
-        GridBagConstraints gc = new GridBagConstraints();
-        gc.weightx = 1.0;
-        gc.weighty = 1.0;
-        gc.anchor = GridBagConstraints.NORTHWEST;
-        gc.fill = GridBagConstraints.BOTH;
-        PreferencePanel plugins = gui.createPreferenceTab(this);
-        plugins.add(buildContentPane(), gc);
-        readLocalPluginInformation();
-        pluginPreferencesActivated = true;
-    }
-
-    private void configureSites() {
-        ButtonSpec[] options = new ButtonSpec[] {
-                new ButtonSpec(
-                        tr("OK"),
-                        ImageProvider.get("ok"),
-                        tr("Accept the new plugin sites and close the dialog"),
-                        null /* no special help topic */
-                        ),
-                        new ButtonSpec(
-                                tr("Cancel"),
-                                ImageProvider.get("cancel"),
-                                tr("Close the dialog"),
-                                null /* no special help topic */
-                                )
-        };
-        PluginConfigurationSitesPanel pnl = new PluginConfigurationSitesPanel();
-
-        int answer = HelpAwareOptionPane.showOptionDialog(
-                pnlPluginPreferences,
-                pnl,
-                tr("Configure Plugin Sites"),
-                JOptionPane.QUESTION_MESSAGE,
-                null,
-                options,
-                options[0],
-                null /* no help topic */
-                );
-        if (answer != 0 /* OK */)
-            return;
-        List<String> sites = pnl.getUpdateSites();
-        Main.pref.setPluginSites(sites);
-    }
-
-    /**
-     * Replies the list of plugins waiting for update or download
-     *
-     * @return the list of plugins waiting for update or download
-     */
-    public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() {
-        return model != null ? model.getPluginsScheduledForUpdateOrDownload() : null;
-    }
-
-    @Override
-    public boolean ok() {
-        if (! pluginPreferencesActivated)
-            return false;
-        pnlPluginUpdatePolicy.rememberInPreferences();
-        if (model.isActivePluginsChanged()) {
-            LinkedList<String> l = new LinkedList<String>(model.getSelectedPluginNames());
-            Collections.sort(l);
-            Main.pref.putCollection("plugins", l);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Reads locally available information about plugins from the local file system.
-     * Scans cached plugin lists from plugin download sites and locally available
-     * plugin jar files.
-     *
-     */
-    public void readLocalPluginInformation() {
-        final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask();
-        Runnable r = new Runnable() {
-            @Override
-            public void run() {
-                if (task.isCanceled()) return;
-                SwingUtilities.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        model.setAvailablePlugins(task.getAvailablePlugins());
-                        pnlPluginPreferences.refreshView();
-                    }
-                });
-            }
-        };
-        Main.worker.submit(task);
-        Main.worker.submit(r);
-    }
-
-    /**
-     * The action for downloading the list of available plugins
-     *
-     */
-    class DownloadAvailablePluginsAction extends AbstractAction {
-
-        public DownloadAvailablePluginsAction() {
-            putValue(NAME,tr("Download list"));
-            putValue(SHORT_DESCRIPTION, tr("Download the list of available plugins"));
-            putValue(SMALL_ICON, ImageProvider.get("download"));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
-            Runnable continuation = new Runnable() {
-                @Override
-                public void run() {
-                    if (task.isCanceled()) return;
-                    SwingUtilities.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            model.updateAvailablePlugins(task.getAvailablePlugins());
-                            pnlPluginPreferences.refreshView();
-                            Main.pref.putInteger("pluginmanager.version", Version.getInstance().getVersion()); // fix #7030
-                        }
-                    });
-                }
-            };
-            Main.worker.submit(task);
-            Main.worker.submit(continuation);
-        }
-    }
-
-    /**
-     * The action for downloading the list of available plugins
-     *
-     */
-    class UpdateSelectedPluginsAction extends AbstractAction {
-        public UpdateSelectedPluginsAction() {
-            putValue(NAME,tr("Update plugins"));
-            putValue(SHORT_DESCRIPTION, tr("Update the selected plugins"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
-        }
-
-        protected void notifyDownloadResults(PluginDownloadTask task) {
-            final Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
-            final Collection<PluginInformation> failed = task.getFailedPlugins();
-            final StringBuilder sb = new StringBuilder();
-            sb.append("<html>");
-            sb.append(buildDownloadSummary(task));
-            if (!downloaded.isEmpty()) {
-                sb.append(tr("Please restart JOSM to activate the downloaded plugins."));
-            }
-            sb.append("</html>");
-            GuiHelper.runInEDTAndWait(new Runnable() {
-                @Override
-                public void run() {
-                    HelpAwareOptionPane.showOptionDialog(
-                            pnlPluginPreferences,
-                            sb.toString(),
-                            tr("Update plugins"),
-                            !failed.isEmpty() ? JOptionPane.WARNING_MESSAGE : JOptionPane.INFORMATION_MESSAGE,
-                                    HelpUtil.ht("/Preferences/Plugins")
-                            );
-                }
-            });
-        }
-
-        protected void alertNothingToUpdate() {
-            try {
-                SwingUtilities.invokeAndWait(new Runnable() {
-                    @Override
-                    public void run() {
-                        HelpAwareOptionPane.showOptionDialog(
-                                pnlPluginPreferences,
-                                tr("All installed plugins are up to date. JOSM does not have to download newer versions."),
-                                tr("Plugins up to date"),
-                                JOptionPane.INFORMATION_MESSAGE,
-                                null // FIXME: provide help context
-                                );
-                    }
-                });
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            final List<PluginInformation> toUpdate = model.getSelectedPlugins();
-            // the async task for downloading plugins
-            final PluginDownloadTask pluginDownloadTask = new PluginDownloadTask(
-                    pnlPluginPreferences,
-                    toUpdate,
-                    tr("Update plugins")
-                    );
-            // the async task for downloading plugin information
-            final ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
-
-            // to be run asynchronously after the plugin download
-            //
-            final Runnable pluginDownloadContinuation = new Runnable() {
-                @Override
-                public void run() {
-                    if (pluginDownloadTask.isCanceled())
-                        return;
-                    notifyDownloadResults(pluginDownloadTask);
-                    model.refreshLocalPluginVersion(pluginDownloadTask.getDownloadedPlugins());
-                    model.clearPendingPlugins(pluginDownloadTask.getDownloadedPlugins());
-                    GuiHelper.runInEDT(new Runnable() {
-                        @Override
-                        public void run() {
-                            pnlPluginPreferences.refreshView();                        }
-                    });
-                }
-            };
-
-            // to be run asynchronously after the plugin list download
-            //
-            final Runnable pluginInfoDownloadContinuation = new Runnable() {
-                @Override
-                public void run() {
-                    if (pluginInfoDownloadTask.isCanceled())
-                        return;
-                    model.updateAvailablePlugins(pluginInfoDownloadTask.getAvailablePlugins());
-                    // select plugins which actually have to be updated
-                    //
-                    Iterator<PluginInformation> it = toUpdate.iterator();
-                    while(it.hasNext()) {
-                        PluginInformation pi = it.next();
-                        if (!pi.isUpdateRequired()) {
-                            it.remove();
-                        }
-                    }
-                    if (toUpdate.isEmpty()) {
-                        alertNothingToUpdate();
-                        return;
-                    }
-                    pluginDownloadTask.setPluginsToDownload(toUpdate);
-                    Main.worker.submit(pluginDownloadTask);
-                    Main.worker.submit(pluginDownloadContinuation);
-                }
-            };
-
-            Main.worker.submit(pluginInfoDownloadTask);
-            Main.worker.submit(pluginInfoDownloadContinuation);
-        }
-    }
-
-
-    /**
-     * The action for configuring the plugin download sites
-     *
-     */
-    class ConfigureSitesAction extends AbstractAction {
-        public ConfigureSitesAction() {
-            putValue(NAME,tr("Configure sites..."));
-            putValue(SHORT_DESCRIPTION, tr("Configure the list of sites where plugins are downloaded from"));
-            putValue(SMALL_ICON, ImageProvider.get("dialogs", "settings"));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            configureSites();
-        }
-    }
-
-    /**
-     * Applies the current filter condition in the filter text field to the
-     * model
-     */
-    class SearchFieldAdapter implements DocumentListener {
-        public void filter() {
-            String expr = tfFilter.getText().trim();
-            if (expr.isEmpty()) {
-                expr = null;
-            }
-            model.filterDisplayedPlugins(expr);
-            pnlPluginPreferences.refreshView();
-        }
-
-        @Override
-        public void changedUpdate(DocumentEvent arg0) {
-            filter();
-        }
-
-        @Override
-        public void insertUpdate(DocumentEvent arg0) {
-            filter();
-        }
-
-        @Override
-        public void removeUpdate(DocumentEvent arg0) {
-            filter();
-        }
-    }
-
-    static private class PluginConfigurationSitesPanel extends JPanel {
-
-        private DefaultListModel model;
-
-        protected void build() {
-            setLayout(new GridBagLayout());
-            add(new JLabel(tr("Add JOSM Plugin description URL.")), GBC.eol());
-            model = new DefaultListModel();
-            for (String s : Main.pref.getPluginSites()) {
-                model.addElement(s);
-            }
-            final JList list = new JList(model);
-            add(new JScrollPane(list), GBC.std().fill());
-            JPanel buttons = new JPanel(new GridBagLayout());
-            buttons.add(new JButton(new AbstractAction(tr("Add")){
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    String s = JOptionPane.showInputDialog(
-                            JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
-                            tr("Add JOSM Plugin description URL."),
-                            tr("Enter URL"),
-                            JOptionPane.QUESTION_MESSAGE
-                            );
-                    if (s != null) {
-                        model.addElement(s);
-                    }
-                }
-            }), GBC.eol().fill(GBC.HORIZONTAL));
-            buttons.add(new JButton(new AbstractAction(tr("Edit")){
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    if (list.getSelectedValue() == null) {
-                        JOptionPane.showMessageDialog(
-                                JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
-                                tr("Please select an entry."),
-                                tr("Warning"),
-                                JOptionPane.WARNING_MESSAGE
-                                );
-                        return;
-                    }
-                    String s = (String)JOptionPane.showInputDialog(
-                            Main.parent,
-                            tr("Edit JOSM Plugin description URL."),
-                            tr("JOSM Plugin description URL"),
-                            JOptionPane.QUESTION_MESSAGE,
-                            null,
-                            null,
-                            list.getSelectedValue()
-                            );
-                    if (s != null) {
-                        model.setElementAt(s, list.getSelectedIndex());
-                    }
-                }
-            }), GBC.eol().fill(GBC.HORIZONTAL));
-            buttons.add(new JButton(new AbstractAction(tr("Delete")){
-                @Override
-                public void actionPerformed(ActionEvent event) {
-                    if (list.getSelectedValue() == null) {
-                        JOptionPane.showMessageDialog(
-                                JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
-                                tr("Please select an entry."),
-                                tr("Warning"),
-                                JOptionPane.WARNING_MESSAGE
-                                );
-                        return;
-                    }
-                    model.removeElement(list.getSelectedValue());
-                }
-            }), GBC.eol().fill(GBC.HORIZONTAL));
-            add(buttons, GBC.eol());
-        }
-
-        public PluginConfigurationSitesPanel() {
-            build();
-        }
-
-        public List<String> getUpdateSites() {
-            if (model.getSize() == 0) return Collections.emptyList();
-            List<String> ret = new ArrayList<String>(model.getSize());
-            for (int i=0; i< model.getSize();i++){
-                ret.add((String)model.get(i));
-            }
-            return ret;
-        }
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java	(revision 6529)
@@ -34,4 +34,5 @@
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.preferences.advanced.AdvancedPreference;
+import org.openstreetmap.josm.gui.preferences.audio.AudioPreference;
 import org.openstreetmap.josm.gui.preferences.display.ColorPreference;
 import org.openstreetmap.josm.gui.preferences.display.DisplayPreference;
@@ -44,8 +45,12 @@
 import org.openstreetmap.josm.gui.preferences.map.MapPreference;
 import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
+import org.openstreetmap.josm.gui.preferences.plugin.PluginPreference;
 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
+import org.openstreetmap.josm.gui.preferences.remotecontrol.RemoteControlPreference;
 import org.openstreetmap.josm.gui.preferences.server.AuthenticationPreference;
 import org.openstreetmap.josm.gui.preferences.server.ProxyPreference;
+import org.openstreetmap.josm.gui.preferences.server.ServerAccessPreference;
 import org.openstreetmap.josm.gui.preferences.shortcut.ShortcutPreference;
+import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.plugins.PluginDownloadTask;
 import org.openstreetmap.josm.plugins.PluginHandler;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/RemoteControlPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/RemoteControlPreference.java	(revision 6528)
+++ 	(revision )
@@ -1,134 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.preferences;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.swing.BorderFactory;
-import javax.swing.Box;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JSeparator;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
-import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
-import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * Preference settings for the Remote Control plugin
- *
- * @author Frederik Ramm
- */
-public final class RemoteControlPreference extends DefaultTabPreferenceSetting {
-
-    /**
-     * Factory used to build a new instance of this preference setting
-     */
-    public static class Factory implements PreferenceSettingFactory {
-
-        @Override
-        public PreferenceSetting createPreferenceSetting() {
-            return new RemoteControlPreference();
-        }
-    }
-
-    private RemoteControlPreference() {
-        super("remotecontrol", tr("Remote Control"), tr("Settings for the remote control feature."));
-        for (PermissionPrefWithDefault p : PermissionPrefWithDefault.getPermissionPrefs()) {
-            JCheckBox cb = new JCheckBox(p.preferenceText);
-            cb.setSelected(p.isAllowed());
-            prefs.put(p, cb);
-        }
-    }
-    private final Map<PermissionPrefWithDefault, JCheckBox> prefs =
-            new LinkedHashMap<PermissionPrefWithDefault, JCheckBox>();
-    private JCheckBox enableRemoteControl;
-    private JCheckBox loadInNewLayer = new JCheckBox(tr("Download objects to new layer"));
-    private JCheckBox alwaysAskUserConfirm = new JCheckBox(tr("Confirm all Remote Control actions manually"));
-
-    @Override
-    public void addGui(final PreferenceTabbedPane gui) {
-
-        JPanel remote = new JPanel(new GridBagLayout());
-
-        final JLabel descLabel = new JLabel("<html>"
-                + tr("Allows JOSM to be controlled from other applications, e.g. from a web browser.")
-                + "</html>");
-        descLabel.setFont(descLabel.getFont().deriveFont(Font.PLAIN));
-        remote.add(descLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
-
-        final JLabel portLabel = new JLabel("<html>" + tr("JOSM will always listen at <b>port 8111</b> on localhost. "
-                + "<br>This port is not configurable because it is referenced by external applications talking to JOSM.") + "</html>");
-        portLabel.setFont(portLabel.getFont().deriveFont(Font.PLAIN));
-        remote.add(portLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
-
-        remote.add(enableRemoteControl = new JCheckBox(tr("Enable remote control"), RemoteControl.PROP_REMOTECONTROL_ENABLED.get()), GBC.eol());
-
-        final JPanel wrapper = new JPanel();
-        wrapper.setLayout(new GridBagLayout());
-        wrapper.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray)));
-
-        remote.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 5));
-
-        wrapper.add(new JLabel(tr("Permitted actions:")), GBC.eol());
-        int INDENT = 15;
-        for (JCheckBox p : prefs.values()) {
-            wrapper.add(p, GBC.eol().insets(INDENT, 5, 0, 0).fill(GBC.HORIZONTAL));
-        }
-
-        wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5));
-        wrapper.add(loadInNewLayer, GBC.eol().fill(GBC.HORIZONTAL));
-        wrapper.add(alwaysAskUserConfirm, GBC.eol().fill(GBC.HORIZONTAL));
-
-        remote.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
-
-        loadInNewLayer.setSelected(Main.pref.getBoolean(RequestHandler.loadInNewLayerKey, RequestHandler.loadInNewLayerDefault));
-        alwaysAskUserConfirm.setSelected(Main.pref.getBoolean(RequestHandler.globalConfirmationKey, RequestHandler.globalConfirmationDefault));
-
-        ActionListener remoteControlEnabled = new ActionListener() {
-
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                GuiHelper.setEnabledRec(wrapper, enableRemoteControl.isSelected());
-                // 'setEnabled(false)' does not work for JLabel with html text, so do it manually
-                // FIXME: use QuadStateCheckBox to make checkboxes unset when disabled
-            }
-        };
-        enableRemoteControl.addActionListener(remoteControlEnabled);
-        remoteControlEnabled.actionPerformed(null);
-        createPreferenceTabWithScrollPane(gui, remote);
-    }
-
-    @Override
-    public boolean ok() {
-        boolean enabled = enableRemoteControl.isSelected();
-        boolean changed = RemoteControl.PROP_REMOTECONTROL_ENABLED.put(enabled);
-        if (enabled) {
-            for (Entry<PermissionPrefWithDefault, JCheckBox> p : prefs.entrySet()) {
-                Main.pref.put(p.getKey().pref, p.getValue().isSelected());
-            }
-            Main.pref.put(RequestHandler.loadInNewLayerKey, loadInNewLayer.isSelected());
-            Main.pref.put(RequestHandler.globalConfirmationKey, alwaysAskUserConfirm.isSelected());
-        }
-        if (changed) {
-            if (enabled) {
-                RemoteControl.start();
-            } else {
-                RemoteControl.stop();
-            }
-        }
-        return false;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java	(revision 6528)
+++ 	(revision )
@@ -1,122 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.preferences;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.beans.PropertyChangeListener;
-
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-
-import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.preferences.server.OsmApiUrlInputPanel;
-import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
-
-/**
- * Connection preferences, including authentication and proxy sub-preferences.
- */
-public final class ServerAccessPreference extends DefaultTabPreferenceSetting {
-
-    /**
-     * Factory used to create a new {@code ServerAccessPreference}.
-     */
-    public static class Factory implements PreferenceSettingFactory {
-        @Override
-        public PreferenceSetting createPreferenceSetting() {
-            return new ServerAccessPreference();
-        }
-    }
-
-    private ServerAccessPreference() {
-        super("connection", tr("Connection Settings"), tr("Connection Settings for the OSM server."), false, new JTabbedPane());
-    }
-
-    /** indicates whether to use the default OSM URL or not */
-    private OsmApiUrlInputPanel pnlApiUrlPreferences;
-
-    /**
-     * Embeds a vertically scrollable panel in a {@link JScrollPane}
-     * @param panel the panel
-     * @return the scroll pane
-     */
-    public static JScrollPane wrapVerticallyScrollablePanel(VerticallyScrollablePanel panel) {
-        JScrollPane sp = new JScrollPane(panel);
-        sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
-        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
-        return sp;
-    }
-
-    /**
-     * Builds the tabbed pane with the server preferences
-     *
-     * @return panel with server preferences tabs
-     */
-    protected JPanel buildTabbedServerPreferences() {
-        JPanel pnl = new JPanel(new BorderLayout());
-        pnl.add(getTabPane(), BorderLayout.CENTER);
-        return pnl;
-    }
-
-    /**
-     * Builds the panel for entering the server access preferences
-     *
-     * @return preferences panel for server settings
-     */
-    protected JPanel buildContentPanel() {
-        JPanel pnl = new JPanel(new GridBagLayout());
-        GridBagConstraints gc = new GridBagConstraints();
-
-        // the checkbox for the default UL
-        gc.fill = GridBagConstraints.HORIZONTAL;
-        gc.anchor = GridBagConstraints.NORTHWEST;
-        gc.weightx = 1.0;
-        gc.insets = new Insets(0,0,0,0);
-        pnl.add(pnlApiUrlPreferences = new OsmApiUrlInputPanel(), gc);
-
-        // the remaining access properties
-        gc.gridy = 1;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.weightx = 1.0;
-        gc.weighty = 1.0;
-        gc.insets = new Insets(10,0,3,3);
-        pnl.add(buildTabbedServerPreferences(), gc);
-
-        HelpUtil.setHelpContext(pnl, HelpUtil.ht("/Preferences/Connection"));
-        return pnl;
-    }
-
-    /**
-     * Adds a listener that will be notified of API URL change.
-     * @param listener the listener
-     * @since 6523
-     */
-    public final void addApiUrlChangeListener(PropertyChangeListener listener) {
-        pnlApiUrlPreferences.addPropertyChangeListener(listener);
-    }
-
-    @Override
-    public void addGui(PreferenceTabbedPane gui) {
-        GridBagConstraints gc = new GridBagConstraints();
-        gc.fill = GridBagConstraints.BOTH;
-        gc.weightx = 1.0;
-        gc.weighty = 1.0;
-        gc.anchor = GridBagConstraints.NORTHWEST;
-        gui.createPreferenceTab(this).add(buildContentPanel(), gc);
-
-        pnlApiUrlPreferences.initFromPreferences();
-    }
-
-    /**
-     * Saves the values to the preferences
-     */
-    @Override
-    public boolean ok() {
-        pnlApiUrlPreferences.saveToPreferences();
-        return false;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/ValidatorPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ValidatorPreference.java	(revision 6528)
+++ 	(revision )
@@ -1,148 +1,0 @@
-// License: GPL. See LICENSE file for details.
-package org.openstreetmap.josm.gui.preferences;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Collection;
-
-import javax.swing.BorderFactory;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.validation.OsmValidator;
-import org.openstreetmap.josm.data.validation.Test;
-import org.openstreetmap.josm.tools.GBC;
-
-/**
- * Preference settings for the validator
- *
- * @author frsantos
- */
-public final class ValidatorPreference extends DefaultTabPreferenceSetting {
-
-    public static class Factory implements PreferenceSettingFactory {
-        @Override
-        public PreferenceSetting createPreferenceSetting() {
-            return new ValidatorPreference();
-        }
-    }
-
-    private ValidatorPreference() {
-        super("validator", tr("Data validator"),
-                tr("An OSM data validator that checks for common errors made by users and editor programs."));
-    }
-
-    /** The preferences prefix */
-    public static final String PREFIX = "validator";
-
-    /** The preferences key for error layer */
-    public static final String PREF_LAYER = PREFIX + ".layer";
-
-    /** The preferences key for enabled tests */
-    public static final String PREF_TESTS = PREFIX + ".tests";
-
-    /** The preferences key for enabled tests */
-    public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
-
-    /** The preferences key for enabled tests before upload*/
-    public static final String PREF_TESTS_BEFORE_UPLOAD = PREFIX + ".testsBeforeUpload";
-
-    /** The preferences key for ignored severity other on upload */
-    public static final String PREF_OTHER_UPLOAD = PREFIX + ".otherUpload";
-
-    /** The preferences key for ignored severity other */
-    public static final String PREF_OTHER = PREFIX + ".other";
-
-    /**
-     * The preferences key for enabling the permanent filtering
-     * of the displayed errors in the tree regarding the current selection
-     */
-    public static final String PREF_FILTER_BY_SELECTION = PREFIX + ".selectionFilter";
-
-    private JCheckBox prefUseIgnore;
-    private JCheckBox prefUseLayer;
-    private JCheckBox prefOtherUpload;
-    private JCheckBox prefOther;
-
-    /** The list of all tests */
-    private Collection<Test> allTests;
-
-    @Override
-    public void addGui(PreferenceTabbedPane gui)
-    {
-        JPanel testPanel = new JPanel(new GridBagLayout());
-        testPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
-
-        prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(PREF_USE_IGNORE, true));
-        prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
-        testPanel.add(prefUseIgnore, GBC.eol());
-
-        prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(PREF_LAYER, true));
-        prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
-        testPanel.add(prefUseLayer, GBC.eol());
-
-        prefOther = new JCheckBox(tr("Show informational level."), Main.pref.getBoolean(PREF_OTHER, false));
-        prefOther.setToolTipText(tr("Show the informational tests."));
-        testPanel.add(prefOther, GBC.eol());
-
-        prefOtherUpload = new JCheckBox(tr("Show informational level on upload."), Main.pref.getBoolean(PREF_OTHER_UPLOAD, false));
-        prefOtherUpload.setToolTipText(tr("Show the informational tests in the upload check windows."));
-        testPanel.add(prefOtherUpload, GBC.eol());
-
-        ActionListener otherUploadEnabled = new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                prefOtherUpload.setEnabled(prefOther.isSelected());
-            }
-        };
-        prefOther.addActionListener(otherUploadEnabled);
-        otherUploadEnabled.actionPerformed(null);
-
-        GBC a = GBC.eol().insets(-5,0,0,0);
-        a.anchor = GBC.EAST;
-        testPanel.add( new JLabel(tr("On demand")), GBC.std() );
-        testPanel.add( new JLabel(tr("On upload")), a );
-
-        allTests = OsmValidator.getTests();
-        for (Test test: allTests) {
-            test.addGui(testPanel);
-        }
-
-        createPreferenceTabWithScrollPane(gui, testPanel);
-    }
-
-    @Override
-    public boolean ok() {
-        StringBuilder tests = new StringBuilder();
-        StringBuilder testsBeforeUpload = new StringBuilder();
-
-        for (Test test : allTests) {
-            test.ok();
-            String name = test.getClass().getSimpleName();
-            tests.append(',').append(name).append('=').append(test.enabled);
-            testsBeforeUpload.append(',').append(name).append('=').append(test.testBeforeUpload);
-        }
-
-        if (tests.length() > 0) {
-            tests = tests.deleteCharAt(0);
-        }
-        if (testsBeforeUpload.length() > 0) {
-            testsBeforeUpload = testsBeforeUpload.deleteCharAt(0);
-        }
-
-        OsmValidator.initializeTests(allTests);
-
-        Main.pref.put(PREF_TESTS, tests.toString());
-        Main.pref.put(PREF_TESTS_BEFORE_UPLOAD, testsBeforeUpload.toString());
-        Main.pref.put(PREF_USE_IGNORE, prefUseIgnore.isSelected());
-        Main.pref.put(PREF_OTHER, prefOther.isSelected());
-        Main.pref.put(PREF_OTHER_UPLOAD, prefOtherUpload.isSelected());
-        Main.pref.put(PREF_LAYER, prefUseLayer.isSelected());
-        return false;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 6529)
@@ -50,4 +50,7 @@
 public final class AdvancedPreference extends DefaultTabPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code AdvancedPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/audio/AudioPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/audio/AudioPreference.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/audio/AudioPreference.java	(revision 6529)
@@ -0,0 +1,152 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.audio;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.tools.GBC;
+
+/*
+ * marker.audiosampleminsecs
+ * marker.audiosampleminmetres
+ * marker.buttonlabels
+ * markers.namedtrackpoints
+ * audio.forwardbackamount
+ * audio.leadin
+ * audio.menuinvisible
+ * marker.audiotraceVisible
+ * audio.toolbar ??
+ */
+
+public final class AudioPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code AudioPreference}.
+     */
+    public static class Factory implements PreferenceSettingFactory {
+        @Override
+        public PreferenceSetting createPreferenceSetting() {
+            return new AudioPreference();
+        }
+    }
+
+    private AudioPreference() {
+        super("audio", tr("Audio Settings"), tr("Settings for the audio player and audio markers."));
+    }
+
+    private JCheckBox audioMenuVisible = new JCheckBox(tr("Display the Audio menu."));
+    private JCheckBox markerButtonLabels = new JCheckBox(tr("Label audio (and image and web) markers."));
+    private JCheckBox markerAudioTraceVisible = new JCheckBox(tr("Display live audio trace."));
+
+    // various methods of making markers on import audio
+    private JCheckBox audioMarkersFromExplicitWaypoints = new JCheckBox(tr("Explicit waypoints with valid timestamps."));
+    private JCheckBox audioMarkersFromUntimedWaypoints = new JCheckBox(tr("Explicit waypoints with time estimated from track position."));
+    private JCheckBox audioMarkersFromNamedTrackpoints = new JCheckBox(tr("Named trackpoints."));
+    private JCheckBox audioMarkersFromWavTimestamps = new JCheckBox(tr("Modified times (time stamps) of audio files."));
+    private JCheckBox audioMarkersFromStart = new JCheckBox(tr("Start of track (will always do this if no other markers available)."));
+
+    private JosmTextField audioLeadIn = new JosmTextField(8);
+    private JosmTextField audioForwardBackAmount = new JosmTextField(8);
+    private JosmTextField audioFastForwardMultiplier = new JosmTextField(8);
+    private JosmTextField audioCalibration = new JosmTextField(8);
+
+    @Override
+    public void addGui(PreferenceTabbedPane gui) {
+        JPanel audio = new JPanel(new GridBagLayout());
+
+        // audioMenuVisible
+        audioMenuVisible.setSelected(! Main.pref.getBoolean("audio.menuinvisible"));
+        audioMenuVisible.setToolTipText(tr("Show or hide the audio menu entry on the main menu bar."));
+        audio.add(audioMenuVisible, GBC.eol().insets(0,0,0,0));
+
+        // audioTraceVisible
+        markerAudioTraceVisible.setSelected(Main.pref.getBoolean("marker.traceaudio", true));
+        markerAudioTraceVisible.setToolTipText(tr("Display a moving icon representing the point on the synchronized track where the audio currently playing was recorded."));
+        audio.add(markerAudioTraceVisible, GBC.eol().insets(0,0,0,0));
+
+        // buttonLabels
+        markerButtonLabels.setSelected(Main.pref.getBoolean("marker.buttonlabels", true));
+        markerButtonLabels.setToolTipText(tr("Put text labels against audio (and image and web) markers as well as their button icons."));
+        audio.add(markerButtonLabels, GBC.eol().insets(0,0,0,0));
+
+        audio.add(new JLabel(tr("When importing audio, make markers from...")), GBC.eol());
+
+        // audioMarkersFromExplicitWaypoints
+        audioMarkersFromExplicitWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromexplicitwaypoints", true));
+        audioMarkersFromExplicitWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer."));
+        audio.add(audioMarkersFromExplicitWaypoints, GBC.eol().insets(10,0,0,0));
+
+        // audioMarkersFromUntimedWaypoints
+        audioMarkersFromUntimedWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromuntimedwaypoints", true));
+        audioMarkersFromUntimedWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer."));
+        audio.add(audioMarkersFromUntimedWaypoints, GBC.eol().insets(10,0,0,0));
+
+        // audioMarkersFromNamedTrackpoints
+        audioMarkersFromNamedTrackpoints.setSelected(Main.pref.getBoolean("marker.audiofromnamedtrackpoints", false));
+        audioMarkersFromNamedTrackpoints.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions."));
+        audio.add(audioMarkersFromNamedTrackpoints, GBC.eol().insets(10,0,0,0));
+
+        // audioMarkersFromWavTimestamps
+        audioMarkersFromWavTimestamps.setSelected(Main.pref.getBoolean("marker.audiofromwavtimestamps", false));
+        audioMarkersFromWavTimestamps.setToolTipText(tr("Create audio markers at the position on the track corresponding to the modified time of each audio WAV file imported."));
+        audio.add(audioMarkersFromWavTimestamps, GBC.eol().insets(10,0,0,0));
+
+        // audioMarkersFromStart
+        audioMarkersFromStart.setSelected(Main.pref.getBoolean("marker.audiofromstart"));
+        audioMarkersFromStart.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions."));
+        audio.add(audioMarkersFromStart, GBC.eol().insets(10,0,0,0));
+
+        audioForwardBackAmount.setText(Main.pref.get("audio.forwardbackamount", "10.0"));
+        audioForwardBackAmount.setToolTipText(tr("The number of seconds to jump forward or back when the relevant button is pressed"));
+        audio.add(new JLabel(tr("Forward/back time (seconds)")), GBC.std());
+        audio.add(audioForwardBackAmount, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+
+        audioFastForwardMultiplier.setText(Main.pref.get("audio.fastfwdmultiplier", "1.3"));
+        audioFastForwardMultiplier.setToolTipText(tr("The amount by which the speed is multiplied for fast forwarding"));
+        audio.add(new JLabel(tr("Fast forward multiplier")), GBC.std());
+        audio.add(audioFastForwardMultiplier, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+
+        audioLeadIn.setText(Main.pref.get("audio.leadin", "1.0"));
+        audioLeadIn.setToolTipText(tr("Playback starts this number of seconds before (or after, if negative) the audio track position requested"));
+        audio.add(new JLabel(tr("Lead-in time (seconds)")), GBC.std());
+        audio.add(audioLeadIn, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+
+        audioCalibration.setText(Main.pref.get("audio.calibration", "1.0"));
+        audioCalibration.setToolTipText(tr("The ratio of voice recorder elapsed time to true elapsed time"));
+        audio.add(new JLabel(tr("Voice recorder calibration")), GBC.std());
+        audio.add(audioCalibration, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+
+        audio.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
+
+        createPreferenceTabWithScrollPane(gui, audio);
+    }
+
+    @Override
+    public boolean ok() {
+        Main.pref.put("audio.menuinvisible", ! audioMenuVisible.isSelected());
+        Main.pref.put("marker.traceaudio", markerAudioTraceVisible.isSelected());
+        Main.pref.put("marker.buttonlabels", markerButtonLabels.isSelected());
+        Main.pref.put("marker.audiofromexplicitwaypoints", audioMarkersFromExplicitWaypoints.isSelected());
+        Main.pref.put("marker.audiofromuntimedwaypoints", audioMarkersFromUntimedWaypoints.isSelected());
+        Main.pref.put("marker.audiofromnamedtrackpoints", audioMarkersFromNamedTrackpoints.isSelected());
+        Main.pref.put("marker.audiofromwavtimestamps", audioMarkersFromWavTimestamps.isSelected());
+        Main.pref.put("marker.audiofromstart", audioMarkersFromStart.isSelected());
+        Main.pref.put("audio.forwardbackamount", audioForwardBackAmount.getText());
+        Main.pref.put("audio.fastfwdmultiplier", audioFastForwardMultiplier.getText());
+        Main.pref.put("audio.leadin", audioLeadIn.getText());
+        Main.pref.put("audio.calibration", audioCalibration.getText());
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/ColorPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/ColorPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/ColorPreference.java	(revision 6529)
@@ -52,4 +52,7 @@
 public class ColorPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code ColorPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/DisplayPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/DisplayPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/DisplayPreference.java	(revision 6529)
@@ -13,4 +13,8 @@
 
 public final class DisplayPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code DisplayPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/DrawingPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/DrawingPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/DrawingPreference.java	(revision 6529)
@@ -26,4 +26,7 @@
 public class DrawingPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code DrawingPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java	(revision 6529)
@@ -31,4 +31,7 @@
 public class LafPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code LafPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/LanguagePreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/LanguagePreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/LanguagePreference.java	(revision 6529)
@@ -29,4 +29,8 @@
 
 public class LanguagePreference implements SubPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code LanguagePreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 6529)
@@ -68,4 +68,8 @@
 
 public final class ImageryPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code ImageryPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/BackupPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/BackupPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/BackupPreference.java	(revision 6529)
@@ -29,4 +29,7 @@
 public class BackupPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code BackupPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 6529)
@@ -47,4 +47,7 @@
     }
 
+    /**
+     * Factory used to create a new {@code MapPaintPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPreference.java	(revision 6529)
@@ -13,4 +13,8 @@
 
 public final class MapPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code MapPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java	(revision 6529)
@@ -48,4 +48,7 @@
 public final class TaggingPresetPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code TaggingPresetPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/preferences/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/package-info.java	(revision 6529)
@@ -0,0 +1,7 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides generic classes for handling JOSM preferences.
+ * Functional classes for the different components are located in sub-packages.
+ */
+package org.openstreetmap.josm.gui.preferences;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java	(revision 6529)
@@ -0,0 +1,556 @@
+//License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.plugin;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Version;
+import org.openstreetmap.josm.gui.HelpAwareOptionPane;
+import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
+import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.PreferencePanel;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
+import org.openstreetmap.josm.plugins.PluginDownloadTask;
+import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask;
+import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+public final class PluginPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code PluginPreference}.
+     */
+    public static class Factory implements PreferenceSettingFactory {
+        @Override
+        public PreferenceSetting createPreferenceSetting() {
+            return new PluginPreference();
+        }
+    }
+
+    private PluginPreference() {
+        super("plugin", tr("Plugins"), tr("Configure available plugins."), false, new JTabbedPane());
+    }
+
+    public static String buildDownloadSummary(PluginDownloadTask task) {
+        Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
+        Collection<PluginInformation> failed = task.getFailedPlugins();
+        StringBuilder sb = new StringBuilder();
+        if (! downloaded.isEmpty()) {
+            sb.append(trn(
+                    "The following plugin has been downloaded <strong>successfully</strong>:",
+                    "The following {0} plugins have been downloaded <strong>successfully</strong>:",
+                    downloaded.size(),
+                    downloaded.size()
+                    ));
+            sb.append("<ul>");
+            for(PluginInformation pi: downloaded) {
+                sb.append("<li>").append(pi.name).append(" (").append(pi.version).append(")").append("</li>");
+            }
+            sb.append("</ul>");
+        }
+        if (! failed.isEmpty()) {
+            sb.append(trn(
+                    "Downloading the following plugin has <strong>failed</strong>:",
+                    "Downloading the following {0} plugins has <strong>failed</strong>:",
+                    failed.size(),
+                    failed.size()
+                    ));
+            sb.append("<ul>");
+            for(PluginInformation pi: failed) {
+                sb.append("<li>").append(pi.name).append("</li>");
+            }
+            sb.append("</ul>");
+        }
+        return sb.toString();
+    }
+
+    private JosmTextField tfFilter;
+    private PluginListPanel pnlPluginPreferences;
+    private PluginPreferencesModel model;
+    private JScrollPane spPluginPreferences;
+    private PluginUpdatePolicyPanel pnlPluginUpdatePolicy;
+
+    /**
+     * is set to true if this preference pane has been selected
+     * by the user
+     */
+    private boolean pluginPreferencesActivated = false;
+
+    protected JPanel buildSearchFieldPanel() {
+        JPanel pnl  = new JPanel(new GridBagLayout());
+        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        GridBagConstraints gc = new GridBagConstraints();
+
+        gc.anchor = GridBagConstraints.NORTHWEST;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 0.0;
+        gc.insets = new Insets(0,0,0,3);
+        pnl.add(new JLabel(tr("Search:")), gc);
+
+        gc.gridx = 1;
+        gc.weightx = 1.0;
+        pnl.add(tfFilter = new JosmTextField(), gc);
+        tfFilter.setToolTipText(tr("Enter a search expression"));
+        SelectAllOnFocusGainedDecorator.decorate(tfFilter);
+        tfFilter.getDocument().addDocumentListener(new SearchFieldAdapter());
+        return pnl;
+    }
+
+    protected JPanel buildActionPanel() {
+        JPanel pnl = new JPanel(new GridLayout(1,3));
+
+        pnl.add(new JButton(new DownloadAvailablePluginsAction()));
+        pnl.add(new JButton(new UpdateSelectedPluginsAction()));
+        pnl.add(new JButton(new ConfigureSitesAction()));
+        return pnl;
+    }
+
+    protected JPanel buildPluginListPanel() {
+        JPanel pnl = new JPanel(new BorderLayout());
+        pnl.add(buildSearchFieldPanel(), BorderLayout.NORTH);
+        model  = new PluginPreferencesModel();
+        spPluginPreferences = new JScrollPane(pnlPluginPreferences = new PluginListPanel(model));
+        spPluginPreferences.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        spPluginPreferences.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        spPluginPreferences.getVerticalScrollBar().addComponentListener(
+                new ComponentAdapter(){
+                    @Override
+                    public void componentShown(ComponentEvent e) {
+                        spPluginPreferences.setBorder(UIManager.getBorder("ScrollPane.border"));
+                    }
+                    @Override
+                    public void componentHidden(ComponentEvent e) {
+                        spPluginPreferences.setBorder(null);
+                    }
+                }
+                );
+
+        pnl.add(spPluginPreferences, BorderLayout.CENTER);
+        pnl.add(buildActionPanel(), BorderLayout.SOUTH);
+        return pnl;
+    }
+
+    protected JTabbedPane buildContentPane() {
+        JTabbedPane pane = getTabPane();
+        pane.addTab(tr("Plugins"), buildPluginListPanel());
+        pane.addTab(tr("Plugin update policy"), pnlPluginUpdatePolicy = new PluginUpdatePolicyPanel());
+        return pane;
+    }
+
+    @Override
+    public void addGui(final PreferenceTabbedPane gui) {
+        GridBagConstraints gc = new GridBagConstraints();
+        gc.weightx = 1.0;
+        gc.weighty = 1.0;
+        gc.anchor = GridBagConstraints.NORTHWEST;
+        gc.fill = GridBagConstraints.BOTH;
+        PreferencePanel plugins = gui.createPreferenceTab(this);
+        plugins.add(buildContentPane(), gc);
+        readLocalPluginInformation();
+        pluginPreferencesActivated = true;
+    }
+
+    private void configureSites() {
+        ButtonSpec[] options = new ButtonSpec[] {
+                new ButtonSpec(
+                        tr("OK"),
+                        ImageProvider.get("ok"),
+                        tr("Accept the new plugin sites and close the dialog"),
+                        null /* no special help topic */
+                        ),
+                        new ButtonSpec(
+                                tr("Cancel"),
+                                ImageProvider.get("cancel"),
+                                tr("Close the dialog"),
+                                null /* no special help topic */
+                                )
+        };
+        PluginConfigurationSitesPanel pnl = new PluginConfigurationSitesPanel();
+
+        int answer = HelpAwareOptionPane.showOptionDialog(
+                pnlPluginPreferences,
+                pnl,
+                tr("Configure Plugin Sites"),
+                JOptionPane.QUESTION_MESSAGE,
+                null,
+                options,
+                options[0],
+                null /* no help topic */
+                );
+        if (answer != 0 /* OK */)
+            return;
+        List<String> sites = pnl.getUpdateSites();
+        Main.pref.setPluginSites(sites);
+    }
+
+    /**
+     * Replies the list of plugins waiting for update or download
+     *
+     * @return the list of plugins waiting for update or download
+     */
+    public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() {
+        return model != null ? model.getPluginsScheduledForUpdateOrDownload() : null;
+    }
+
+    @Override
+    public boolean ok() {
+        if (! pluginPreferencesActivated)
+            return false;
+        pnlPluginUpdatePolicy.rememberInPreferences();
+        if (model.isActivePluginsChanged()) {
+            LinkedList<String> l = new LinkedList<String>(model.getSelectedPluginNames());
+            Collections.sort(l);
+            Main.pref.putCollection("plugins", l);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Reads locally available information about plugins from the local file system.
+     * Scans cached plugin lists from plugin download sites and locally available
+     * plugin jar files.
+     *
+     */
+    public void readLocalPluginInformation() {
+        final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask();
+        Runnable r = new Runnable() {
+            @Override
+            public void run() {
+                if (task.isCanceled()) return;
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        model.setAvailablePlugins(task.getAvailablePlugins());
+                        pnlPluginPreferences.refreshView();
+                    }
+                });
+            }
+        };
+        Main.worker.submit(task);
+        Main.worker.submit(r);
+    }
+
+    /**
+     * The action for downloading the list of available plugins
+     *
+     */
+    class DownloadAvailablePluginsAction extends AbstractAction {
+
+        public DownloadAvailablePluginsAction() {
+            putValue(NAME,tr("Download list"));
+            putValue(SHORT_DESCRIPTION, tr("Download the list of available plugins"));
+            putValue(SMALL_ICON, ImageProvider.get("download"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
+            Runnable continuation = new Runnable() {
+                @Override
+                public void run() {
+                    if (task.isCanceled()) return;
+                    SwingUtilities.invokeLater(new Runnable() {
+                        @Override
+                        public void run() {
+                            model.updateAvailablePlugins(task.getAvailablePlugins());
+                            pnlPluginPreferences.refreshView();
+                            Main.pref.putInteger("pluginmanager.version", Version.getInstance().getVersion()); // fix #7030
+                        }
+                    });
+                }
+            };
+            Main.worker.submit(task);
+            Main.worker.submit(continuation);
+        }
+    }
+
+    /**
+     * The action for downloading the list of available plugins
+     *
+     */
+    class UpdateSelectedPluginsAction extends AbstractAction {
+        public UpdateSelectedPluginsAction() {
+            putValue(NAME,tr("Update plugins"));
+            putValue(SHORT_DESCRIPTION, tr("Update the selected plugins"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
+        }
+
+        protected void notifyDownloadResults(PluginDownloadTask task) {
+            final Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
+            final Collection<PluginInformation> failed = task.getFailedPlugins();
+            final StringBuilder sb = new StringBuilder();
+            sb.append("<html>");
+            sb.append(buildDownloadSummary(task));
+            if (!downloaded.isEmpty()) {
+                sb.append(tr("Please restart JOSM to activate the downloaded plugins."));
+            }
+            sb.append("</html>");
+            GuiHelper.runInEDTAndWait(new Runnable() {
+                @Override
+                public void run() {
+                    HelpAwareOptionPane.showOptionDialog(
+                            pnlPluginPreferences,
+                            sb.toString(),
+                            tr("Update plugins"),
+                            !failed.isEmpty() ? JOptionPane.WARNING_MESSAGE : JOptionPane.INFORMATION_MESSAGE,
+                                    HelpUtil.ht("/Preferences/Plugins")
+                            );
+                }
+            });
+        }
+
+        protected void alertNothingToUpdate() {
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    @Override
+                    public void run() {
+                        HelpAwareOptionPane.showOptionDialog(
+                                pnlPluginPreferences,
+                                tr("All installed plugins are up to date. JOSM does not have to download newer versions."),
+                                tr("Plugins up to date"),
+                                JOptionPane.INFORMATION_MESSAGE,
+                                null // FIXME: provide help context
+                                );
+                    }
+                });
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            final List<PluginInformation> toUpdate = model.getSelectedPlugins();
+            // the async task for downloading plugins
+            final PluginDownloadTask pluginDownloadTask = new PluginDownloadTask(
+                    pnlPluginPreferences,
+                    toUpdate,
+                    tr("Update plugins")
+                    );
+            // the async task for downloading plugin information
+            final ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
+
+            // to be run asynchronously after the plugin download
+            //
+            final Runnable pluginDownloadContinuation = new Runnable() {
+                @Override
+                public void run() {
+                    if (pluginDownloadTask.isCanceled())
+                        return;
+                    notifyDownloadResults(pluginDownloadTask);
+                    model.refreshLocalPluginVersion(pluginDownloadTask.getDownloadedPlugins());
+                    model.clearPendingPlugins(pluginDownloadTask.getDownloadedPlugins());
+                    GuiHelper.runInEDT(new Runnable() {
+                        @Override
+                        public void run() {
+                            pnlPluginPreferences.refreshView();                        }
+                    });
+                }
+            };
+
+            // to be run asynchronously after the plugin list download
+            //
+            final Runnable pluginInfoDownloadContinuation = new Runnable() {
+                @Override
+                public void run() {
+                    if (pluginInfoDownloadTask.isCanceled())
+                        return;
+                    model.updateAvailablePlugins(pluginInfoDownloadTask.getAvailablePlugins());
+                    // select plugins which actually have to be updated
+                    //
+                    Iterator<PluginInformation> it = toUpdate.iterator();
+                    while(it.hasNext()) {
+                        PluginInformation pi = it.next();
+                        if (!pi.isUpdateRequired()) {
+                            it.remove();
+                        }
+                    }
+                    if (toUpdate.isEmpty()) {
+                        alertNothingToUpdate();
+                        return;
+                    }
+                    pluginDownloadTask.setPluginsToDownload(toUpdate);
+                    Main.worker.submit(pluginDownloadTask);
+                    Main.worker.submit(pluginDownloadContinuation);
+                }
+            };
+
+            Main.worker.submit(pluginInfoDownloadTask);
+            Main.worker.submit(pluginInfoDownloadContinuation);
+        }
+    }
+
+
+    /**
+     * The action for configuring the plugin download sites
+     *
+     */
+    class ConfigureSitesAction extends AbstractAction {
+        public ConfigureSitesAction() {
+            putValue(NAME,tr("Configure sites..."));
+            putValue(SHORT_DESCRIPTION, tr("Configure the list of sites where plugins are downloaded from"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "settings"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            configureSites();
+        }
+    }
+
+    /**
+     * Applies the current filter condition in the filter text field to the
+     * model
+     */
+    class SearchFieldAdapter implements DocumentListener {
+        public void filter() {
+            String expr = tfFilter.getText().trim();
+            if (expr.isEmpty()) {
+                expr = null;
+            }
+            model.filterDisplayedPlugins(expr);
+            pnlPluginPreferences.refreshView();
+        }
+
+        @Override
+        public void changedUpdate(DocumentEvent arg0) {
+            filter();
+        }
+
+        @Override
+        public void insertUpdate(DocumentEvent arg0) {
+            filter();
+        }
+
+        @Override
+        public void removeUpdate(DocumentEvent arg0) {
+            filter();
+        }
+    }
+
+    static private class PluginConfigurationSitesPanel extends JPanel {
+
+        private DefaultListModel model;
+
+        protected void build() {
+            setLayout(new GridBagLayout());
+            add(new JLabel(tr("Add JOSM Plugin description URL.")), GBC.eol());
+            model = new DefaultListModel();
+            for (String s : Main.pref.getPluginSites()) {
+                model.addElement(s);
+            }
+            final JList list = new JList(model);
+            add(new JScrollPane(list), GBC.std().fill());
+            JPanel buttons = new JPanel(new GridBagLayout());
+            buttons.add(new JButton(new AbstractAction(tr("Add")){
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    String s = JOptionPane.showInputDialog(
+                            JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
+                            tr("Add JOSM Plugin description URL."),
+                            tr("Enter URL"),
+                            JOptionPane.QUESTION_MESSAGE
+                            );
+                    if (s != null) {
+                        model.addElement(s);
+                    }
+                }
+            }), GBC.eol().fill(GBC.HORIZONTAL));
+            buttons.add(new JButton(new AbstractAction(tr("Edit")){
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    if (list.getSelectedValue() == null) {
+                        JOptionPane.showMessageDialog(
+                                JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
+                                tr("Please select an entry."),
+                                tr("Warning"),
+                                JOptionPane.WARNING_MESSAGE
+                                );
+                        return;
+                    }
+                    String s = (String)JOptionPane.showInputDialog(
+                            Main.parent,
+                            tr("Edit JOSM Plugin description URL."),
+                            tr("JOSM Plugin description URL"),
+                            JOptionPane.QUESTION_MESSAGE,
+                            null,
+                            null,
+                            list.getSelectedValue()
+                            );
+                    if (s != null) {
+                        model.setElementAt(s, list.getSelectedIndex());
+                    }
+                }
+            }), GBC.eol().fill(GBC.HORIZONTAL));
+            buttons.add(new JButton(new AbstractAction(tr("Delete")){
+                @Override
+                public void actionPerformed(ActionEvent event) {
+                    if (list.getSelectedValue() == null) {
+                        JOptionPane.showMessageDialog(
+                                JOptionPane.getFrameForComponent(PluginConfigurationSitesPanel.this),
+                                tr("Please select an entry."),
+                                tr("Warning"),
+                                JOptionPane.WARNING_MESSAGE
+                                );
+                        return;
+                    }
+                    model.removeElement(list.getSelectedValue());
+                }
+            }), GBC.eol().fill(GBC.HORIZONTAL));
+            add(buttons, GBC.eol());
+        }
+
+        public PluginConfigurationSitesPanel() {
+            build();
+        }
+
+        public List<String> getUpdateSites() {
+            if (model.getSize() == 0) return Collections.emptyList();
+            List<String> ret = new ArrayList<String>(model.getSize());
+            for (int i=0; i< model.getSize();i++){
+                ret.add((String)model.get(i));
+            }
+            return ret;
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/plugin/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/plugin/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/plugin/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling plugin preferences.
+ */
+package org.openstreetmap.josm.gui.preferences.plugin;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 6529)
@@ -56,4 +56,7 @@
 public class ProjectionPreference implements SubPreferenceSetting {
 
+    /**
+     * Factory used to create a new {@code ProjectionPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
@@ -91,6 +94,5 @@
          * see http://www.epsg-registry.org/
          */
-        mercator = registerProjectionChoice(tr("Mercator"), "core:mercator",
-                3857);
+        mercator = registerProjectionChoice(tr("Mercator"), "core:mercator", 3857);
 
         /**
Index: trunk/src/org/openstreetmap/josm/gui/preferences/projection/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/projection/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/projection/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling projection preferences.
+ */
+package org.openstreetmap.josm.gui.preferences.projection;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java	(revision 6529)
@@ -0,0 +1,138 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.remotecontrol;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
+import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
+import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * Preference settings for Remote Control.
+ *
+ * @author Frederik Ramm
+ */
+public final class RemoteControlPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to build a new instance of this preference setting
+     */
+    public static class Factory implements PreferenceSettingFactory {
+
+        @Override
+        public PreferenceSetting createPreferenceSetting() {
+            return new RemoteControlPreference();
+        }
+    }
+
+    private RemoteControlPreference() {
+        super("remotecontrol", tr("Remote Control"), tr("Settings for the remote control feature."));
+        for (PermissionPrefWithDefault p : PermissionPrefWithDefault.getPermissionPrefs()) {
+            JCheckBox cb = new JCheckBox(p.preferenceText);
+            cb.setSelected(p.isAllowed());
+            prefs.put(p, cb);
+        }
+    }
+    private final Map<PermissionPrefWithDefault, JCheckBox> prefs =
+            new LinkedHashMap<PermissionPrefWithDefault, JCheckBox>();
+    private JCheckBox enableRemoteControl;
+    private JCheckBox loadInNewLayer = new JCheckBox(tr("Download objects to new layer"));
+    private JCheckBox alwaysAskUserConfirm = new JCheckBox(tr("Confirm all Remote Control actions manually"));
+
+    @Override
+    public void addGui(final PreferenceTabbedPane gui) {
+
+        JPanel remote = new JPanel(new GridBagLayout());
+
+        final JLabel descLabel = new JLabel("<html>"
+                + tr("Allows JOSM to be controlled from other applications, e.g. from a web browser.")
+                + "</html>");
+        descLabel.setFont(descLabel.getFont().deriveFont(Font.PLAIN));
+        remote.add(descLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
+
+        final JLabel portLabel = new JLabel("<html>" + tr("JOSM will always listen at <b>port 8111</b> on localhost. "
+                + "<br>This port is not configurable because it is referenced by external applications talking to JOSM.") + "</html>");
+        portLabel.setFont(portLabel.getFont().deriveFont(Font.PLAIN));
+        remote.add(portLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
+
+        remote.add(enableRemoteControl = new JCheckBox(tr("Enable remote control"), RemoteControl.PROP_REMOTECONTROL_ENABLED.get()), GBC.eol());
+
+        final JPanel wrapper = new JPanel();
+        wrapper.setLayout(new GridBagLayout());
+        wrapper.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray)));
+
+        remote.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 5));
+
+        wrapper.add(new JLabel(tr("Permitted actions:")), GBC.eol());
+        int INDENT = 15;
+        for (JCheckBox p : prefs.values()) {
+            wrapper.add(p, GBC.eol().insets(INDENT, 5, 0, 0).fill(GBC.HORIZONTAL));
+        }
+
+        wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5));
+        wrapper.add(loadInNewLayer, GBC.eol().fill(GBC.HORIZONTAL));
+        wrapper.add(alwaysAskUserConfirm, GBC.eol().fill(GBC.HORIZONTAL));
+
+        remote.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
+
+        loadInNewLayer.setSelected(Main.pref.getBoolean(RequestHandler.loadInNewLayerKey, RequestHandler.loadInNewLayerDefault));
+        alwaysAskUserConfirm.setSelected(Main.pref.getBoolean(RequestHandler.globalConfirmationKey, RequestHandler.globalConfirmationDefault));
+
+        ActionListener remoteControlEnabled = new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                GuiHelper.setEnabledRec(wrapper, enableRemoteControl.isSelected());
+                // 'setEnabled(false)' does not work for JLabel with html text, so do it manually
+                // FIXME: use QuadStateCheckBox to make checkboxes unset when disabled
+            }
+        };
+        enableRemoteControl.addActionListener(remoteControlEnabled);
+        remoteControlEnabled.actionPerformed(null);
+        createPreferenceTabWithScrollPane(gui, remote);
+    }
+
+    @Override
+    public boolean ok() {
+        boolean enabled = enableRemoteControl.isSelected();
+        boolean changed = RemoteControl.PROP_REMOTECONTROL_ENABLED.put(enabled);
+        if (enabled) {
+            for (Entry<PermissionPrefWithDefault, JCheckBox> p : prefs.entrySet()) {
+                Main.pref.put(p.getKey().pref, p.getValue().isSelected());
+            }
+            Main.pref.put(RequestHandler.loadInNewLayerKey, loadInNewLayer.isSelected());
+            Main.pref.put(RequestHandler.globalConfirmationKey, alwaysAskUserConfirm.isSelected());
+        }
+        if (changed) {
+            if (enabled) {
+                RemoteControl.start();
+            } else {
+                RemoteControl.stop();
+            }
+        }
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling Remote Control preferences.
+ */
+package org.openstreetmap.josm.gui.preferences.remotecontrol;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 6529)
@@ -219,8 +219,16 @@
     }
 
+    /**
+     * Determines if the test has been canceled.
+     * @return {@code true} if canceled, {@code false} otherwise
+     */
     public boolean isCanceled() {
         return canceled;
     }
 
+    /**
+     * Determines if the test has succeeded.
+     * @return {@code true} if success, {@code false} otherwise
+     */
     public boolean isSuccess() {
         return success;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreference.java	(revision 6529)
@@ -7,5 +7,4 @@
 import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
-import org.openstreetmap.josm.gui.preferences.ServerAccessPreference;
 import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java	(revision 6529)
@@ -84,8 +84,14 @@
     }
 
+    /**
+     * Constructs a new {@code BasicAuthenticationPreferencesPanel}.
+     */
     public BasicAuthenticationPreferencesPanel() {
         build();
     }
 
+    /**
+     * Inits contents from preferences.
+     */
     public void initFromPreferences() {
         CredentialsAgent cm = CredentialsManager.getInstance();
@@ -110,4 +116,7 @@
     }
 
+    /**
+     * Saves contents to preferences.
+     */
     public void saveToPreferences() {
         CredentialsAgent cm = CredentialsManager.getInstance();
@@ -125,4 +134,7 @@
     }
 
+    /**
+     * Clears the password field.
+     */
     public void clearPassword() {
         tfOsmPassword.setText("");
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAccessTokenHolder.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAccessTokenHolder.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAccessTokenHolder.java	(revision 6529)
@@ -11,8 +11,14 @@
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
-
+/**
+ * Class holding OAuth access token key and secret.
+ */
 public class OAuthAccessTokenHolder {
     private  static OAuthAccessTokenHolder instance;
 
+    /**
+     * Replies the unique instance.
+     * @return The unique instance of {@code OAuthAccessTokenHolder}
+     */
     public static OAuthAccessTokenHolder getInstance() {
         if (instance == null) {
@@ -87,4 +93,8 @@
     }
 
+    /**
+     * Replies the access token.
+     * @return the access token, can be {@code null}
+     */
     public OAuthToken getAccessToken() {
         if (!containsAccessToken())
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 6529)
@@ -30,10 +30,17 @@
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-
+
+/**
+ * Component allowing input os OSM API URL.
+ */
 public class OsmApiUrlInputPanel extends JPanel {
+    
+    /**
+     * OSM API URL property key.
+     */
     static public final String API_URL_PROP = OsmApiUrlInputPanel.class.getName() + ".apiUrl";
 
@@ -225,4 +232,8 @@
     }
 
+    /**
+     * Enables or disables the API URL input.
+     * @param enabled {@code true} to enable input, {@code false} otherwise
+     */
     public void setApiUrlInputEnabled(boolean enabled) {
         lblApiUrl.setEnabled(enabled);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreference.java	(revision 6529)
@@ -10,5 +10,4 @@
 import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
-import org.openstreetmap.josm.gui.preferences.ServerAccessPreference;
 import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java	(revision 6529)
@@ -36,10 +36,20 @@
 import org.openstreetmap.josm.tools.GBC;
 
+/**
+ * Component allowing input of proxy settings.
+ */
 public class ProxyPreferencesPanel extends VerticallyScrollablePanel {
 
+    /**
+     * The proxy policy is how JOSM will use proxy information.
+     */
     public enum ProxyPolicy {
+        /** No proxy: JOSM will access Internet resources directly */
         NO_PROXY("no-proxy"),
+        /** Use system settings: JOSM will use system proxy settings */
         USE_SYSTEM_SETTINGS("use-system-settings"),
+        /** Use HTTP proxy: JOSM will use the given HTTP proxy, configured manually */
         USE_HTTP_PROXY("use-http-proxy"),
+        /** Use HTTP proxy: JOSM will use the given SOCKS proxy */
         USE_SOCKS_PROXY("use-socks-proxy");
 
@@ -49,8 +59,17 @@
         }
 
+        /**
+         * Replies the policy name, to be stored in proxy preferences.
+         * @return the policy unique name
+         */
         public String getName() {
             return policyName;
         }
 
+        /**
+         * Retrieves a proxy policy from its name found in preferences.
+         * @param policyName The policy name
+         * @return The proxy policy matching the given name, or {@code null}
+         */
         static public ProxyPolicy fromName(String policyName) {
             if (policyName == null) return null;
@@ -64,10 +83,17 @@
     }
 
+    /** Property key for proxy policy */
     public static final String PROXY_POLICY = "proxy.policy";
+    /** Property key for HTTP proxy host */
     public static final String PROXY_HTTP_HOST = "proxy.http.host";
+    /** Property key for HTTP proxy port */
     public static final String PROXY_HTTP_PORT = "proxy.http.port";
+    /** Property key for SOCKS proxy host */
     public static final String PROXY_SOCKS_HOST = "proxy.socks.host";
+    /** Property key for SOCKS proxy port */
     public static final String PROXY_SOCKS_PORT = "proxy.socks.port";
+    /** Property key for proxy username */
     public static final String PROXY_USER = "proxy.user";
+    /** Property key for proxy password */
     public static final String PROXY_PASS = "proxy.pass";
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/ServerAccessPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/ServerAccessPreference.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/ServerAccessPreference.java	(revision 6529)
@@ -0,0 +1,125 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.preferences.server;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+
+import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
+
+/**
+ * Connection preferences, including authentication and proxy sub-preferences.
+ */
+public final class ServerAccessPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code ServerAccessPreference}.
+     */
+    public static class Factory implements PreferenceSettingFactory {
+        @Override
+        public PreferenceSetting createPreferenceSetting() {
+            return new ServerAccessPreference();
+        }
+    }
+
+    private ServerAccessPreference() {
+        super("connection", tr("Connection Settings"), tr("Connection Settings for the OSM server."), false, new JTabbedPane());
+    }
+
+    /** indicates whether to use the default OSM URL or not */
+    private OsmApiUrlInputPanel pnlApiUrlPreferences;
+
+    /**
+     * Embeds a vertically scrollable panel in a {@link JScrollPane}
+     * @param panel the panel
+     * @return the scroll pane
+     */
+    public static JScrollPane wrapVerticallyScrollablePanel(VerticallyScrollablePanel panel) {
+        JScrollPane sp = new JScrollPane(panel);
+        sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        return sp;
+    }
+
+    /**
+     * Builds the tabbed pane with the server preferences
+     *
+     * @return panel with server preferences tabs
+     */
+    protected JPanel buildTabbedServerPreferences() {
+        JPanel pnl = new JPanel(new BorderLayout());
+        pnl.add(getTabPane(), BorderLayout.CENTER);
+        return pnl;
+    }
+
+    /**
+     * Builds the panel for entering the server access preferences
+     *
+     * @return preferences panel for server settings
+     */
+    protected JPanel buildContentPanel() {
+        JPanel pnl = new JPanel(new GridBagLayout());
+        GridBagConstraints gc = new GridBagConstraints();
+
+        // the checkbox for the default UL
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.anchor = GridBagConstraints.NORTHWEST;
+        gc.weightx = 1.0;
+        gc.insets = new Insets(0,0,0,0);
+        pnl.add(pnlApiUrlPreferences = new OsmApiUrlInputPanel(), gc);
+
+        // the remaining access properties
+        gc.gridy = 1;
+        gc.fill = GridBagConstraints.BOTH;
+        gc.weightx = 1.0;
+        gc.weighty = 1.0;
+        gc.insets = new Insets(10,0,3,3);
+        pnl.add(buildTabbedServerPreferences(), gc);
+
+        HelpUtil.setHelpContext(pnl, HelpUtil.ht("/Preferences/Connection"));
+        return pnl;
+    }
+
+    /**
+     * Adds a listener that will be notified of API URL change.
+     * @param listener the listener
+     * @since 6523
+     */
+    public final void addApiUrlChangeListener(PropertyChangeListener listener) {
+        pnlApiUrlPreferences.addPropertyChangeListener(listener);
+    }
+
+    @Override
+    public void addGui(PreferenceTabbedPane gui) {
+        GridBagConstraints gc = new GridBagConstraints();
+        gc.fill = GridBagConstraints.BOTH;
+        gc.weightx = 1.0;
+        gc.weighty = 1.0;
+        gc.anchor = GridBagConstraints.NORTHWEST;
+        gui.createPreferenceTab(this).add(buildContentPanel(), gc);
+
+        pnlApiUrlPreferences.initFromPreferences();
+    }
+
+    /**
+     * Saves the values to the preferences
+     */
+    @Override
+    public boolean ok() {
+        pnlApiUrlPreferences.saveToPreferences();
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/UserNameValidator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/UserNameValidator.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/UserNameValidator.java	(revision 6529)
@@ -8,6 +8,13 @@
 import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
 
+/**
+ * Validator for OSM username.
+ */
 public class UserNameValidator extends AbstractTextComponentValidator {
 
+    /**
+     * Constructs a new {@code UserNameValidator}.
+     * @param tc the text component used to enter username
+     */
     public UserNameValidator(JTextComponent tc) {
         super(tc);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling connection preferences, including server authentication and proxy settings.
+ */
+package org.openstreetmap.josm.gui.preferences.server;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/PrefJPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/PrefJPanel.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/PrefJPanel.java	(revision 6529)
@@ -51,5 +51,4 @@
 /**
  * This is the keyboard preferences content.
- * If someone wants to merge it with ShortcutPreference.java, feel free.
  */
 public class PrefJPanel extends JPanel {
@@ -61,6 +60,5 @@
     // on the physical keyboard. What language pack is installed in JOSM is completely
     // independent from the keyboard's labelling. But the operation system's locale
-    // usually matches the keyboard. This even works with my English Windows and my German
-    // keyboard.
+    // usually matches the keyboard. This even works with my English Windows and my German keyboard.
     private static String SHIFT = KeyEvent.getKeyModifiersText(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.SHIFT_DOWN_MASK).getModifiers());
     private static String CTRL  = KeyEvent.getKeyModifiersText(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK).getModifiers());
@@ -106,14 +104,44 @@
 
     /** Creates new form prefJPanel */
-    public PrefJPanel(AbstractTableModel model) {
-        this.model = model;
+    public PrefJPanel() {
+        this.model = new ScListModel();
         initComponents();
     }
 
     /**
-     * Show only shortcuts with descriptions coontaing given substring
+     * Show only shortcuts with descriptions containing given substring
+     * @param substring The substring used to filter
      */
     public void filter(String substring) {
         filterField.setText(substring);
+    }
+    
+    private static class ScListModel extends AbstractTableModel {
+        private String[] columnNames = new String[]{tr("Action"), tr("Shortcut")};
+        private List<Shortcut> data;
+
+        public ScListModel() {
+            data = Shortcut.listAll();
+        }
+        @Override
+        public int getColumnCount() {
+            return columnNames.length;
+        }
+        @Override
+        public int getRowCount() {
+            return data.size();
+        }
+        @Override
+        public String getColumnName(int col) {
+            return columnNames[col];
+        }
+        @Override
+        public Object getValueAt(int row, int col) {
+            return (col==0)?  data.get(row).getLongText() : data.get(row);
+        }
+        @Override
+        public boolean isCellEditable(int row, int col) {
+            return false;
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/ShortcutPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/ShortcutPreference.java	(revision 6528)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/ShortcutPreference.java	(revision 6529)
@@ -4,8 +4,5 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.util.List;
-
 import javax.swing.JPanel;
-import javax.swing.table.AbstractTableModel;
 
 import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
@@ -16,8 +13,14 @@
 import org.openstreetmap.josm.tools.Shortcut;
 
+/**
+ * Keyboard shortcut preferences.
+ */
 public final class ShortcutPreference extends DefaultTabPreferenceSetting {
 
     private String defaultFilter;
 
+    /**
+     * Factory used to create a new {@code ShortcutPreference}.
+     */
     public static class Factory implements PreferenceSettingFactory {
         @Override
@@ -28,10 +31,4 @@
 
     private ShortcutPreference() {
-        // icon source: http://www.iconfinder.net/index.php?q=key&page=icondetails&iconid=8553&size=128&q=key&s12=on&s16=on&s22=on&s32=on&s48=on&s64=on&s128=on
-        // icon licence: GPL
-        // icon designer: Paolino, http://www.paolinoland.it/
-        // icon original filename: keyboard.png
-        // icon original size: 128x128
-        // modifications: icon was cropped, then resized
         super("shortcuts", tr("Keyboard Shortcuts"), tr("Changing keyboard shortcuts manually."));
     }
@@ -41,7 +38,9 @@
         JPanel p = gui.createPreferenceTab(this);
 
-        PrefJPanel prefpanel = new PrefJPanel(new ScListModel());
+        PrefJPanel prefpanel = new PrefJPanel();
         p.add(prefpanel, GBC.eol().fill(GBC.BOTH));
-        if (defaultFilter!=null) prefpanel.filter(defaultFilter);
+        if (defaultFilter != null) {
+            prefpanel.filter(defaultFilter);
+        }
     }
 
@@ -51,36 +50,11 @@
     }
 
+    /**
+     * Sets the default filter used to show only shortcuts with descriptions containing given substring.
+     * @param substring The substring used to filter
+     * @see PrefJPanel#filter(String)
+     */
     public void setDefaultFilter(String substring) {
         defaultFilter = substring;
     }
-
-    // Maybe move this to prefPanel? There's no need for it to be here.
-    private static class ScListModel extends AbstractTableModel {
-        private String[] columnNames = new String[]{tr("Action"), tr("Shortcut")};
-        private List<Shortcut> data;
-
-        public ScListModel() {
-            data = Shortcut.listAll();
-        }
-        @Override
-        public int getColumnCount() {
-            return columnNames.length;
-        }
-        @Override
-        public int getRowCount() {
-            return data.size();
-        }
-        @Override
-        public String getColumnName(int col) {
-            return columnNames[col];
-        }
-        @Override
-        public Object getValueAt(int row, int col) {
-            return (col==0)?  data.get(row).getLongText() : data.get(row);
-        }
-        @Override
-        public boolean isCellEditable(int row, int col) {
-            return false;
-        }
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/shortcut/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling shortcut preferences.
+ */
+package org.openstreetmap.josm.gui.preferences.shortcut;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java	(revision 6529)
@@ -0,0 +1,155 @@
+// License: GPL. See LICENSE file for details.
+package org.openstreetmap.josm.gui.preferences.validator;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Collection;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.validation.OsmValidator;
+import org.openstreetmap.josm.data.validation.Test;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * Preference settings for the validator
+ *
+ * @author frsantos
+ */
+public final class ValidatorPreference extends DefaultTabPreferenceSetting {
+
+    /**
+     * Factory used to create a new {@code ValidatorPreference}.
+     */
+    public static class Factory implements PreferenceSettingFactory {
+        @Override
+        public PreferenceSetting createPreferenceSetting() {
+            return new ValidatorPreference();
+        }
+    }
+
+    private ValidatorPreference() {
+        super("validator", tr("Data validator"),
+                tr("An OSM data validator that checks for common errors made by users and editor programs."));
+    }
+
+    /** The preferences prefix */
+    public static final String PREFIX = "validator";
+
+    /** The preferences key for error layer */
+    public static final String PREF_LAYER = PREFIX + ".layer";
+
+    /** The preferences key for enabled tests */
+    public static final String PREF_TESTS = PREFIX + ".tests";
+
+    /** The preferences key for enabled tests */
+    public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
+
+    /** The preferences key for enabled tests before upload*/
+    public static final String PREF_TESTS_BEFORE_UPLOAD = PREFIX + ".testsBeforeUpload";
+
+    /** The preferences key for ignored severity other on upload */
+    public static final String PREF_OTHER_UPLOAD = PREFIX + ".otherUpload";
+
+    /** The preferences key for ignored severity other */
+    public static final String PREF_OTHER = PREFIX + ".other";
+
+    /**
+     * The preferences key for enabling the permanent filtering
+     * of the displayed errors in the tree regarding the current selection
+     */
+    public static final String PREF_FILTER_BY_SELECTION = PREFIX + ".selectionFilter";
+
+    private JCheckBox prefUseIgnore;
+    private JCheckBox prefUseLayer;
+    private JCheckBox prefOtherUpload;
+    private JCheckBox prefOther;
+
+    /** The list of all tests */
+    private Collection<Test> allTests;
+
+    @Override
+    public void addGui(PreferenceTabbedPane gui)
+    {
+        JPanel testPanel = new JPanel(new GridBagLayout());
+        testPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+        prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(PREF_USE_IGNORE, true));
+        prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
+        testPanel.add(prefUseIgnore, GBC.eol());
+
+        prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(PREF_LAYER, true));
+        prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
+        testPanel.add(prefUseLayer, GBC.eol());
+
+        prefOther = new JCheckBox(tr("Show informational level."), Main.pref.getBoolean(PREF_OTHER, false));
+        prefOther.setToolTipText(tr("Show the informational tests."));
+        testPanel.add(prefOther, GBC.eol());
+
+        prefOtherUpload = new JCheckBox(tr("Show informational level on upload."), Main.pref.getBoolean(PREF_OTHER_UPLOAD, false));
+        prefOtherUpload.setToolTipText(tr("Show the informational tests in the upload check windows."));
+        testPanel.add(prefOtherUpload, GBC.eol());
+
+        ActionListener otherUploadEnabled = new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                prefOtherUpload.setEnabled(prefOther.isSelected());
+            }
+        };
+        prefOther.addActionListener(otherUploadEnabled);
+        otherUploadEnabled.actionPerformed(null);
+
+        GBC a = GBC.eol().insets(-5,0,0,0);
+        a.anchor = GBC.EAST;
+        testPanel.add( new JLabel(tr("On demand")), GBC.std() );
+        testPanel.add( new JLabel(tr("On upload")), a );
+
+        allTests = OsmValidator.getTests();
+        for (Test test: allTests) {
+            test.addGui(testPanel);
+        }
+
+        createPreferenceTabWithScrollPane(gui, testPanel);
+    }
+
+    @Override
+    public boolean ok() {
+        StringBuilder tests = new StringBuilder();
+        StringBuilder testsBeforeUpload = new StringBuilder();
+
+        for (Test test : allTests) {
+            test.ok();
+            String name = test.getClass().getSimpleName();
+            tests.append(',').append(name).append('=').append(test.enabled);
+            testsBeforeUpload.append(',').append(name).append('=').append(test.testBeforeUpload);
+        }
+
+        if (tests.length() > 0) {
+            tests = tests.deleteCharAt(0);
+        }
+        if (testsBeforeUpload.length() > 0) {
+            testsBeforeUpload = testsBeforeUpload.deleteCharAt(0);
+        }
+
+        OsmValidator.initializeTests(allTests);
+
+        Main.pref.put(PREF_TESTS, tests.toString());
+        Main.pref.put(PREF_TESTS_BEFORE_UPLOAD, testsBeforeUpload.toString());
+        Main.pref.put(PREF_USE_IGNORE, prefUseIgnore.isSelected());
+        Main.pref.put(PREF_OTHER, prefOther.isSelected());
+        Main.pref.put(PREF_OTHER_UPLOAD, prefOtherUpload.isSelected());
+        Main.pref.put(PREF_LAYER, prefUseLayer.isSelected());
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/preferences/validator/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/validator/package-info.java	(revision 6529)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/validator/package-info.java	(revision 6529)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides classes for handling validator preferences.
+ */
+package org.openstreetmap.josm.gui.preferences.validator;
