Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 6992)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.data.ServerSidePreferences;
 import org.openstreetmap.josm.data.UndoRedoHandler;
+import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.data.coor.CoordinateFormat;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -72,5 +73,4 @@
 import org.openstreetmap.josm.gui.MapFrameListener;
 import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.NavigatableComponent.ViewportData;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.help.HelpUtil;
Index: trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java	(revision 6992)
@@ -19,6 +19,6 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
-import org.openstreetmap.josm.gui.NavigatableComponent.ViewportData;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.layer.Layer;
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 6992)
@@ -25,4 +25,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
@@ -36,5 +37,4 @@
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.NavigatableComponent;
-import org.openstreetmap.josm.gui.NavigatableComponent.SystemOfMeasurement;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
@@ -429,10 +429,10 @@
             double snapDistance;
             SystemOfMeasurement som = NavigatableComponent.getSystemOfMeasurement();
-            if (som.equals(NavigatableComponent.CHINESE_SOM)) {
-                snapDistance = snapDistanceChinese * NavigatableComponent.CHINESE_SOM.aValue;
-            } else if (som.equals(NavigatableComponent.IMPERIAL_SOM)) {
-                snapDistance = snapDistanceImperial * NavigatableComponent.IMPERIAL_SOM.aValue;
-            } else if (som.equals(NavigatableComponent.NAUTICAL_MILE_SOM)) {
-                snapDistance = snapDistanceNautical * NavigatableComponent.NAUTICAL_MILE_SOM.aValue;
+            if (som.equals(SystemOfMeasurement.CHINESE)) {
+                snapDistance = snapDistanceChinese * SystemOfMeasurement.CHINESE.aValue;
+            } else if (som.equals(SystemOfMeasurement.IMPERIAL)) {
+                snapDistance = snapDistanceImperial * SystemOfMeasurement.IMPERIAL.aValue;
+            } else if (som.equals(SystemOfMeasurement.NAUTICAL_MILE)) {
+                snapDistance = snapDistanceNautical * SystemOfMeasurement.NAUTICAL_MILE.aValue;
             } else {
                 snapDistance = snapDistanceMetric; // Metric system by default
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 6992)
@@ -48,5 +48,4 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.SelectionManager;
 import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
@@ -248,5 +247,5 @@
      */
     private boolean giveUserFeedback(MouseEvent e, int modifiers) {
-        Collection<OsmPrimitive> c = MapView.asColl(
+        Collection<OsmPrimitive> c = asColl(
                 mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true));
 
@@ -431,5 +430,5 @@
             //  if nothing was selected, select primitive under cursor for scaling or rotating
             if (getCurrentDataSet().getSelected().isEmpty()) {
-                getCurrentDataSet().setSelected(MapView.asColl(nearestPrimitive));
+                getCurrentDataSet().setSelected(asColl(nearestPrimitive));
             }
 
@@ -446,5 +445,5 @@
             }
             OsmPrimitive toSelect = cycleManager.cycleSetup(nearestPrimitive, e.getPoint());
-            selectPrims(NavigatableComponent.asColl(toSelect), false, false);
+            selectPrims(asColl(toSelect), false, false);
             useLastMoveCommandIfPossible();
             // Schedule a timer to update status line "initialMoveDelay+1" ms in the future
@@ -522,5 +521,5 @@
                 needsRepaint = true;
             }
-            mv.setNewCursor(getCursor(MapView.asColl(p)), this);
+            mv.setNewCursor(getCursor(asColl(p)), this);
             // also update the stored mouse event, so we can display the correct cursor
             // when dragging a node onto another one and then press CTRL to merge
@@ -953,5 +952,5 @@
                 if (!(alt || multipleMatchesParameter)) {
                     // no real cycling, just one element in cycle list
-                    cycleList = MapView.asColl(osm);
+                    cycleList = asColl(osm);
 
                     if (waitForMouseUpParameter) {
@@ -1060,5 +1059,5 @@
             }
             // return one-element collection with one element to be selected (or added  to selection)
-            return MapView.asColl(nxt);
+            return asColl(nxt);
         }
     }
@@ -1162,3 +1161,12 @@
         }
     }
+
+    /**
+     * @return o as collection of o's type.
+     */
+    protected static <T> Collection<T> asColl(T o) {
+        if (o == null)
+            return Collections.emptySet();
+        return Collections.singleton(o);
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/SystemOfMeasurement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/SystemOfMeasurement.java	(revision 6992)
+++ trunk/src/org/openstreetmap/josm/data/SystemOfMeasurement.java	(revision 6992)
@@ -0,0 +1,177 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data;
+
+import static org.openstreetmap.josm.tools.I18n.marktr;
+
+import java.text.NumberFormat;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+
+/**
+ * A system of units used to express length and area measurements.
+ * @since 3406 (creation)
+ * @since 6992 (extraction in this package) 
+ */
+public class SystemOfMeasurement {
+
+    /**
+     * Metric system (international standard).
+     * @since 3406
+     */
+    public static final SystemOfMeasurement METRIC = new SystemOfMeasurement(1, "m", 1000, "km", 10000, "ha");
+
+    /**
+     * Chinese system.
+     * @since 3406
+     */
+    public static final SystemOfMeasurement CHINESE = new SystemOfMeasurement(1.0/3.0, "\u5e02\u5c3a" /* chi */, 500, "\u5e02\u91cc" /* li */);
+
+    /**
+     * Imperial system (British Commonwealth and former British Empire).
+     * @since 3406
+     */
+    public static final SystemOfMeasurement IMPERIAL = new SystemOfMeasurement(0.3048, "ft", 1609.344, "mi", 4046.86, "ac");
+
+    /**
+     * Nautical mile system (navigation, polar exploration).
+     * @since 5549
+     */
+    public static final SystemOfMeasurement NAUTICAL_MILE = new SystemOfMeasurement(185.2, "kbl", 1852, "NM");
+    
+    /**
+     * Known systems of measurement.
+     * @since 3406
+     */
+    public static final Map<String, SystemOfMeasurement> ALL_SYSTEMS;
+    static {
+        ALL_SYSTEMS = new LinkedHashMap<String, SystemOfMeasurement>();
+        ALL_SYSTEMS.put(marktr("Metric"), METRIC);
+        ALL_SYSTEMS.put(marktr("Chinese"), CHINESE);
+        ALL_SYSTEMS.put(marktr("Imperial"), IMPERIAL);
+        ALL_SYSTEMS.put(marktr("Nautical Mile"), NAUTICAL_MILE);
+    }
+    
+    /** First value, in meters, used to translate unit according to above formula. */
+    public final double aValue;
+    /** Second value, in meters, used to translate unit according to above formula. */
+    public final double bValue;
+    /** First unit used to format text. */
+    public final String aName;
+    /** Second unit used to format text. */
+    public final String bName;
+    /** Specific optional area value, in squared meters, between {@code aValue*aValue} and {@code bValue*bValue}. Set to {@code -1} if not used.
+     *  @since 5870 */
+    public final double areaCustomValue;
+    /** Specific optional area unit. Set to {@code null} if not used.
+     *  @since 5870 */
+    public final String areaCustomName;
+
+    /**
+     * System of measurement. Currently covers only length (and area) units.
+     *
+     * If a quantity x is given in m (x_m) and in unit a (x_a) then it translates as
+     * x_a == x_m / aValue
+     *
+     * @param aValue First value, in meters, used to translate unit according to above formula.
+     * @param aName First unit used to format text.
+     * @param bValue Second value, in meters, used to translate unit according to above formula.
+     * @param bName Second unit used to format text.
+     */
+    public SystemOfMeasurement(double aValue, String aName, double bValue, String bName) {
+        this(aValue, aName, bValue, bName, -1, null);
+    }
+
+    /**
+     * System of measurement. Currently covers only length (and area) units.
+     *
+     * If a quantity x is given in m (x_m) and in unit a (x_a) then it translates as
+     * x_a == x_m / aValue
+     *
+     * @param aValue First value, in meters, used to translate unit according to above formula.
+     * @param aName First unit used to format text.
+     * @param bValue Second value, in meters, used to translate unit according to above formula.
+     * @param bName Second unit used to format text.
+     * @param areaCustomValue Specific optional area value, in squared meters, between {@code aValue*aValue} and {@code bValue*bValue}.
+     *                        Set to {@code -1} if not used.
+     * @param areaCustomName Specific optional area unit. Set to {@code null} if not used.
+     *
+     * @since 5870
+     */
+    public SystemOfMeasurement(double aValue, String aName, double bValue, String bName, double areaCustomValue, String areaCustomName) {
+        this.aValue = aValue;
+        this.aName = aName;
+        this.bValue = bValue;
+        this.bName = bName;
+        this.areaCustomValue = areaCustomValue;
+        this.areaCustomName = areaCustomName;
+    }
+
+    /**
+     * Returns the text describing the given distance in this system of measurement.
+     * @param dist The distance in metres
+     * @return The text describing the given distance in this system of measurement.
+     */
+    public String getDistText(double dist) {
+        return getDistText(dist, null, 0.01);
+    }
+
+    /**
+     * Returns the text describing the given distance in this system of measurement.
+     * @param dist The distance in metres
+     * @param format A {@link NumberFormat} to format the area value
+     * @param threshold Values lower than this {@code threshold} are displayed as {@code "< [threshold]"}
+     * @return The text describing the given distance in this system of measurement.
+     * @since 6422
+     */
+    public String getDistText(final double dist, final NumberFormat format, final double threshold) {
+        double a = dist / aValue;
+        if (!Main.pref.getBoolean("system_of_measurement.use_only_lower_unit", false) && a > bValue / aValue)
+            return formatText(dist / bValue, bName, format);
+        else if (a < threshold)
+            return "< " + formatText(threshold, aName, format);
+        else
+            return formatText(a, aName, format);
+    }
+
+    /**
+     * Returns the text describing the given area in this system of measurement.
+     * @param area The area in square metres
+     * @return The text describing the given area in this system of measurement.
+     * @since 5560
+     */
+    public String getAreaText(double area) {
+        return getAreaText(area, null, 0.01);
+    }
+
+    /**
+     * Returns the text describing the given area in this system of measurement.
+     * @param area The area in square metres
+     * @param format A {@link NumberFormat} to format the area value
+     * @param threshold Values lower than this {@code threshold} are displayed as {@code "< [threshold]"}
+     * @return The text describing the given area in this system of measurement.
+     * @since 6422
+     */
+    public String getAreaText(final double area, final NumberFormat format, final double threshold) {
+        double a = area / (aValue*aValue);
+        boolean lowerOnly = Main.pref.getBoolean("system_of_measurement.use_only_lower_unit", false);
+        boolean customAreaOnly = Main.pref.getBoolean("system_of_measurement.use_only_custom_area_unit", false);
+        if ((!lowerOnly && areaCustomValue > 0 && a > areaCustomValue / (aValue*aValue) && a < (bValue*bValue) / (aValue*aValue)) || customAreaOnly)
+            return formatText(area / areaCustomValue, areaCustomName, format);
+        else if (!lowerOnly && a >= (bValue*bValue) / (aValue*aValue))
+            return formatText(area / (bValue * bValue), bName + "\u00b2", format);
+        else if (a < threshold)
+            return "< " + formatText(threshold, aName + "\u00b2", format);
+        else
+            return formatText(a, aName + "\u00b2", format);
+    }
+
+    private static String formatText(double v, String unit, NumberFormat format) {
+        if (format != null) {
+            return format.format(v) + " " + unit;
+        }
+        return String.format(Locale.US, "%." + (v<9.999999 ? 2 : 1) + "f %s", v, unit);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/data/ViewportData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/ViewportData.java	(revision 6992)
+++ trunk/src/org/openstreetmap/josm/data/ViewportData.java	(revision 6992)
@@ -0,0 +1,40 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data;
+
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+/**
+ * Simple data class that keeps map center and scale in one object.
+ * @since 5670 (creation)
+ * @since 6992 (extraction in this package) 
+ */
+public class ViewportData {
+    private EastNorth center;
+    private Double scale;
+
+    /**
+     * Constructs a new {@code ViewportData}.
+     * @param center Projected coordinates of the map center
+     * @param scale Scale factor in east-/north-units per pixel
+     */
+    public ViewportData(EastNorth center, Double scale) {
+        this.center = center;
+        this.scale = scale;
+    }
+
+    /**
+     * Return the projected coordinates of the map center
+     * @return the center
+     */
+    public EastNorth getCenter() {
+        return center;
+    }
+
+    /**
+     * Return the scale factor in east-/north-units per pixel.
+     * @return the scale
+     */
+    public Double getScale() {
+        return scale;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/data/imagery/WmsCache.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/WmsCache.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/data/imagery/WmsCache.java	(revision 6992)
@@ -1,5 +1,4 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.imagery;
-
 
 import java.awt.Graphics2D;
@@ -35,4 +34,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.ProjectionBounds;
+import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -42,8 +42,5 @@
 import org.openstreetmap.josm.data.preferences.StringProperty;
 import org.openstreetmap.josm.data.projection.Projection;
-import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.tools.Utils;
-
-
 
 public class WmsCache {
@@ -454,5 +451,5 @@
         int precisionLon = Math.max(0, -(int)Math.ceil(Math.log10(deltaLon)) + 1);
 
-        String zoom = NavigatableComponent.METRIC_SOM.getDistText(ll1.greatCircleDistance(ll2));
+        String zoom = SystemOfMeasurement.METRIC.getDistText(ll1.greatCircleDistance(ll2));
         String extension;
         if ("image/jpeg".equals(mimeType) || "image/jpg".equals(mimeType)) {
Index: trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 6992)
@@ -53,8 +53,8 @@
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
 import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.NavigatableComponent.ViewportData;
 import org.openstreetmap.josm.gui.dialogs.ChangesetDialog;
 import org.openstreetmap.josm.gui.dialogs.CommandStackDialog;
Index: trunk/src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 6992)
@@ -50,4 +50,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
@@ -732,5 +733,5 @@
 
         public MapStatusPopupMenu() {
-            for (final String key : new TreeSet<String>(NavigatableComponent.SYSTEMS_OF_MEASUREMENT.keySet())) {
+            for (final String key : new TreeSet<String>(SystemOfMeasurement.ALL_SYSTEMS.keySet())) {
                 JCheckBoxMenuItem item = new JCheckBoxMenuItem(new AbstractAction(key) {
                     @Override
@@ -829,5 +830,5 @@
         if (Main.pref.getBoolean("statusbar.change-system-of-measurement-on-click", true)) {
             distText.addMouseListener(new MouseAdapter() {
-                private final List<String> soms = new ArrayList<String>(new TreeSet<String>(NavigatableComponent.SYSTEMS_OF_MEASUREMENT.keySet()));
+                private final List<String> soms = new ArrayList<String>(new TreeSet<String>(SystemOfMeasurement.ALL_SYSTEMS.keySet()));
     
                 @Override
Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 6992)
@@ -40,4 +40,5 @@
 import org.openstreetmap.josm.actions.mapmode.MapMode;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
Index: trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 6992)
@@ -1,6 +1,4 @@
 // License: GPL. See LICENSE file for details.
 package org.openstreetmap.josm.gui;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
 
 import java.awt.Cursor;
@@ -11,5 +9,4 @@
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
-import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -17,8 +14,6 @@
 import java.util.Date;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -33,4 +28,5 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.ProjectionBounds;
+import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.coor.CachedLatLon;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -54,8 +50,9 @@
 
 /**
- * An component that can be navigated by a mapmover. Used as map view and for the
+ * A component that can be navigated by a {@link MapMover}. Used as map view and for the
  * zoomer in the download dialog.
  *
  * @author imi
+ * @since 41
  */
 public class NavigatableComponent extends JComponent implements Helpful {
@@ -65,4 +62,7 @@
      */
     public interface ZoomChangeListener {
+        /**
+         * Method called when the zoom area has changed.
+         */
         void zoomChanged();
     }
@@ -81,33 +81,4 @@
     }
 
-    /**
-     * Simple data class that keeps map center and scale in one object.
-     */
-    public static class ViewportData {
-        private EastNorth center;
-        private Double scale;
-
-        public ViewportData(EastNorth center, Double scale) {
-            this.center = center;
-            this.scale = scale;
-        }
-
-        /**
-         * Return the projected coordinates of the map center
-         * @return the center
-         */
-        public EastNorth getCenter() {
-            return center;
-        }
-
-        /**
-         * Return the scale factor in east-/north-units per pixel.
-         * @return the scale
-         */
-        public Double getScale() {
-            return scale;
-        }
-    }
-
     public static final IntegerProperty PROP_SNAP_DISTANCE = new IntegerProperty("mappaint.node.snap-distance", 10);
 
@@ -146,7 +117,4 @@
     }
 
-    /**
-     * the SoM listeners
-     */
     private static final CopyOnWriteArrayList<SoMChangeListener> somChangeListeners = new CopyOnWriteArrayList<SoMChangeListener>();
 
@@ -185,4 +153,5 @@
      */
     private double scale = Main.getProjection().getDefaultZoomInPPD();
+
     /**
      * Center n/e coordinate of the desired screen center.
@@ -233,11 +202,9 @@
     }
 
-    public String getDist100PixelText()
-    {
+    public String getDist100PixelText() {
         return getDistText(getDist100Pixel());
     }
 
-    public double getDist100Pixel()
-    {
+    public double getDist100Pixel() {
         int w = getWidth()/2;
         int h = getHeight()/2;
@@ -263,6 +230,5 @@
      * @param y Y-Pixelposition to get coordinate from
      *
-     * @return Geographic coordinates from a specific pixel coordination
-     *      on the screen.
+     * @return Geographic coordinates from a specific pixel coordination on the screen.
      */
     public EastNorth getEastNorth(int x, int y) {
@@ -549,6 +515,6 @@
 
     private class ZoomData {
-        LatLon center;
-        double scale;
+        final LatLon center;
+        final double scale;
 
         public ZoomData(EastNorth center, double scale) {
@@ -731,6 +697,6 @@
      *        give the nearest node that is tagged.
      */
-    public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate, boolean use_selected) {
-        return getNearestNode(p, predicate, use_selected, null);
+    public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate, boolean useSelected) {
+        return getNearestNode(p, predicate, useSelected, null);
     }
 
@@ -811,4 +777,7 @@
     /**
      * Convenience method to {@link #getNearestNode(Point, Predicate, boolean)}.
+     * @param p the screen point
+     * @param predicate this parameter imposes a condition on the returned object, e.g.
+     *        give the nearest node that is tagged.
      *
      * @return The nearest node to point p.
@@ -940,7 +909,7 @@
      * @param p the point for which to search the nearest segment.
      * @param predicate the returned object has to fulfill certain properties.
-     * @param use_selected whether selected way segments should be preferred.
-     */
-    public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate, boolean use_selected) {
+     * @param useSelected whether selected way segments should be preferred.
+     */
+    public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate, boolean useSelected) {
         WaySegment wayseg = null, ntsel = null;
 
@@ -959,5 +928,5 @@
         }
 
-        return (ntsel != null && use_selected) ? ntsel : wayseg;
+        return (ntsel != null && useSelected) ? ntsel : wayseg;
     }
 
@@ -1017,4 +986,6 @@
     /**
      * Convenience method to {@link #getNearestWaySegment(Point, Predicate, boolean)}.
+     * @param p the point for which to search the nearest segment.
+     * @param predicate the returned object has to fulfill certain properties.
      *
      * @return The nearest way segment to point p.
@@ -1177,5 +1148,4 @@
      *      that is chosen by the algorithm described.
      * @see #getNearestNode(Point, Predicate)
-     * @see #getNearestNodesImpl(Point, Predicate)
      * @see #getNearestWay(Point, Predicate)
      *
@@ -1223,13 +1193,4 @@
     }
 
-    /**
-     * @return o as collection of o's type.
-     */
-    public static <T> Collection<T> asColl(T o) {
-        if (o == null)
-            return Collections.emptySet();
-        return Collections.singleton(o);
-    }
-
     public static double perDist(Point2D pt, Point2D a, Point2D b) {
         if (pt != null && a != null && b != null) {
@@ -1360,4 +1321,5 @@
     /**
      * Return a ID which is unique as long as viewport dimensions are the same
+     * @return A unique ID, as long as viewport dimensions are the same
      */
     public int getViewID() {
@@ -1375,7 +1337,7 @@
      */
     public static SystemOfMeasurement getSystemOfMeasurement() {
-        SystemOfMeasurement som = SYSTEMS_OF_MEASUREMENT.get(ProjectionPreference.PROP_SYSTEM_OF_MEASUREMENT.get());
+        SystemOfMeasurement som = SystemOfMeasurement.ALL_SYSTEMS.get(ProjectionPreference.PROP_SYSTEM_OF_MEASUREMENT.get());
         if (som == null)
-            return METRIC_SOM;
+            return SystemOfMeasurement.METRIC;
         return som;
     }
@@ -1383,10 +1345,10 @@
     /**
      * Sets the current system of measurement.
-     * @param somKey The system of measurement key. Must be defined in {@link NavigatableComponent#SYSTEMS_OF_MEASUREMENT}.
+     * @param somKey The system of measurement key. Must be defined in {@link SystemOfMeasurement#ALL_SYSTEMS}.
      * @since 6056
      * @throws IllegalArgumentException if {@code somKey} is not known
      */
     public static void setSystemOfMeasurement(String somKey) {
-        if (!SYSTEMS_OF_MEASUREMENT.containsKey(somKey)) {
+        if (!SystemOfMeasurement.ALL_SYSTEMS.containsKey(somKey)) {
             throw new IllegalArgumentException("Invalid system of measurement: "+somKey);
         }
@@ -1397,172 +1359,7 @@
     }
 
-    /**
-     * A system of units used to express length and area measurements.
-     * @since 3406
-     */
-    public static class SystemOfMeasurement {
-
-        /** First value, in meters, used to translate unit according to above formula. */
-        public final double aValue;
-        /** Second value, in meters, used to translate unit according to above formula. */
-        public final double bValue;
-        /** First unit used to format text. */
-        public final String aName;
-        /** Second unit used to format text. */
-        public final String bName;
-        /** Specific optional area value, in squared meters, between {@code aValue*aValue} and {@code bValue*bValue}. Set to {@code -1} if not used.
-         *  @since 5870 */
-        public final double areaCustomValue;
-        /** Specific optional area unit. Set to {@code null} if not used.
-         *  @since 5870 */
-        public final String areaCustomName;
-
-        /**
-         * System of measurement. Currently covers only length (and area) units.
-         *
-         * If a quantity x is given in m (x_m) and in unit a (x_a) then it translates as
-         * x_a == x_m / aValue
-         *
-         * @param aValue First value, in meters, used to translate unit according to above formula.
-         * @param aName First unit used to format text.
-         * @param bValue Second value, in meters, used to translate unit according to above formula.
-         * @param bName Second unit used to format text.
-         */
-        public SystemOfMeasurement(double aValue, String aName, double bValue, String bName) {
-            this(aValue, aName, bValue, bName, -1, null);
-        }
-
-        /**
-         * System of measurement. Currently covers only length (and area) units.
-         *
-         * If a quantity x is given in m (x_m) and in unit a (x_a) then it translates as
-         * x_a == x_m / aValue
-         *
-         * @param aValue First value, in meters, used to translate unit according to above formula.
-         * @param aName First unit used to format text.
-         * @param bValue Second value, in meters, used to translate unit according to above formula.
-         * @param bName Second unit used to format text.
-         * @param areaCustomValue Specific optional area value, in squared meters, between {@code aValue*aValue} and {@code bValue*bValue}.
-         *                        Set to {@code -1} if not used.
-         * @param areaCustomName Specific optional area unit. Set to {@code null} if not used.
-         *
-         * @since 5870
-         */
-        public SystemOfMeasurement(double aValue, String aName, double bValue, String bName, double areaCustomValue, String areaCustomName) {
-            this.aValue = aValue;
-            this.aName = aName;
-            this.bValue = bValue;
-            this.bName = bName;
-            this.areaCustomValue = areaCustomValue;
-            this.areaCustomName = areaCustomName;
-        }
-
-        /**
-         * Returns the text describing the given distance in this system of measurement.
-         * @param dist The distance in metres
-         * @return The text describing the given distance in this system of measurement.
-         */
-        public String getDistText(double dist) {
-            return getDistText(dist, null, 0.01);
-        }
-
-        /**
-         * Returns the text describing the given distance in this system of measurement.
-         * @param dist The distance in metres
-         * @param format A {@link NumberFormat} to format the area value
-         * @param threshold Values lower than this {@code threshold} are displayed as {@code "< [threshold]"}
-         * @return The text describing the given distance in this system of measurement.
-         * @since 6422
-         */
-        public String getDistText(final double dist, final NumberFormat format, final double threshold) {
-            double a = dist / aValue;
-            if (!Main.pref.getBoolean("system_of_measurement.use_only_lower_unit", false) && a > bValue / aValue)
-                return formatText(dist / bValue, bName, format);
-            else if (a < threshold)
-                return "< " + formatText(threshold, aName, format);
-            else
-                return formatText(a, aName, format);
-        }
-
-        /**
-         * Returns the text describing the given area in this system of measurement.
-         * @param area The area in square metres
-         * @return The text describing the given area in this system of measurement.
-         * @since 5560
-         */
-        public String getAreaText(double area) {
-            return getAreaText(area, null, 0.01);
-        }
-
-        /**
-         * Returns the text describing the given area in this system of measurement.
-         * @param area The area in square metres
-         * @param format A {@link NumberFormat} to format the area value
-         * @param threshold Values lower than this {@code threshold} are displayed as {@code "< [threshold]"}
-         * @return The text describing the given area in this system of measurement.
-         * @since 6422
-         */
-        public String getAreaText(final double area, final NumberFormat format, final double threshold) {
-            double a = area / (aValue*aValue);
-            boolean lowerOnly = Main.pref.getBoolean("system_of_measurement.use_only_lower_unit", false);
-            boolean customAreaOnly = Main.pref.getBoolean("system_of_measurement.use_only_custom_area_unit", false);
-            if ((!lowerOnly && areaCustomValue > 0 && a > areaCustomValue / (aValue*aValue) && a < (bValue*bValue) / (aValue*aValue)) || customAreaOnly)
-                return formatText(area / areaCustomValue, areaCustomName, format);
-            else if (!lowerOnly && a >= (bValue*bValue) / (aValue*aValue))
-                return formatText(area / (bValue * bValue), bName + "\u00b2", format);
-            else if (a < threshold)
-                return "< " + formatText(threshold, aName + "\u00b2", format);
-            else
-                return formatText(a, aName + "\u00b2", format);
-        }
-
-        private static String formatText(double v, String unit, NumberFormat format) {
-            if (format != null) {
-                return format.format(v) + " " + unit;
-            }
-            return String.format(Locale.US, "%." + (v<9.999999 ? 2 : 1) + "f %s", v, unit);
-        }
-    }
-
-    /**
-     * Metric system (international standard).
-     * @since 3406
-     */
-    public static final SystemOfMeasurement METRIC_SOM = new SystemOfMeasurement(1, "m", 1000, "km", 10000, "ha");
-
-    /**
-     * Chinese system.
-     * @since 3406
-     */
-    public static final SystemOfMeasurement CHINESE_SOM = new SystemOfMeasurement(1.0/3.0, "\u5e02\u5c3a" /* chi */, 500, "\u5e02\u91cc" /* li */);
-
-    /**
-     * Imperial system (British Commonwealth and former British Empire).
-     * @since 3406
-     */
-    public static final SystemOfMeasurement IMPERIAL_SOM = new SystemOfMeasurement(0.3048, "ft", 1609.344, "mi", 4046.86, "ac");
-
-    /**
-     * Nautical mile system (navigation, polar exploration).
-     * @since 5549
-     */
-    public static final SystemOfMeasurement NAUTICAL_MILE_SOM = new SystemOfMeasurement(185.2, "kbl", 1852, "NM");
-
-    /**
-     * Known systems of measurement.
-     * @since 3406
-     */
-    public static final Map<String, SystemOfMeasurement> SYSTEMS_OF_MEASUREMENT;
-    static {
-        SYSTEMS_OF_MEASUREMENT = new LinkedHashMap<String, SystemOfMeasurement>();
-        SYSTEMS_OF_MEASUREMENT.put(marktr("Metric"), METRIC_SOM);
-        SYSTEMS_OF_MEASUREMENT.put(marktr("Chinese"), CHINESE_SOM);
-        SYSTEMS_OF_MEASUREMENT.put(marktr("Imperial"), IMPERIAL_SOM);
-        SYSTEMS_OF_MEASUREMENT.put(marktr("Nautical Mile"), NAUTICAL_MILE_SOM);
-    }
-
     private static class CursorInfo {
-        public Cursor cursor;
-        public Object object;
+        final Cursor cursor;
+        final Object object;
         public CursorInfo(Cursor c, Object o) {
             cursor = c;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java	(revision 6992)
@@ -24,4 +24,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.coor.CoordinateFormat;
 import org.openstreetmap.josm.data.preferences.CollectionProperty;
@@ -246,5 +247,5 @@
     private static final CollectionProperty PROP_SUB_PROJECTION = new CollectionProperty("projection.sub", null);
     public static final StringProperty PROP_SYSTEM_OF_MEASUREMENT = new StringProperty("system_of_measurement", "Metric");
-    private static final String[] unitsValues = (new ArrayList<String>(NavigatableComponent.SYSTEMS_OF_MEASUREMENT.keySet())).toArray(new String[0]);
+    private static final String[] unitsValues = (new ArrayList<String>(SystemOfMeasurement.ALL_SYSTEMS.keySet())).toArray(new String[0]);
     private static final String[] unitsValuesTr = new String[unitsValues.length];
     static {
Index: trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 6991)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 6992)
@@ -33,4 +33,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.ViewportData;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -38,5 +39,4 @@
 import org.openstreetmap.josm.data.projection.Projections;
 import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.NavigatableComponent.ViewportData;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
