Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColorMap.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColorMap.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColorMap.java	(revision 32315)
@@ -16,176 +16,176 @@
  */
 public class ColorMap {
-	private List<ColorMapEntry> colorList;
-	private String name;
-	private static HashMap<String, ColorMap> colorMaps;
+    private List<ColorMapEntry> colorList;
+    private String name;
+    private static HashMap<String, ColorMap> colorMaps;
 
-	static {
-		colorMaps = new HashMap<>();
-	}
+    static {
+        colorMaps = new HashMap<>();
+    }
 
-	// Private ctor to enforce use of create
-	private ColorMap() {
-	}
+    // Private ctor to enforce use of create
+    private ColorMap() {
+    }
 
-	public String getName() {
-		return name;
-	}
+    public String getName() {
+        return name;
+    }
 
-	public void setName(String name) {
-		this.name = name;
-	}
+    public void setName(String name) {
+        this.name = name;
+    }
 
-	/**
-	 * Gets the color according to the given elevation value.
-	 *
-	 * @param elevation the elevation
-	 * @return the color
-	 */
-	public Color getColor(int elevation) {
-		// empty color map?
-		if (colorList == null || colorList.size() == 0) {
-			return Color.white;
-		}
+    /**
+     * Gets the color according to the given elevation value.
+     *
+     * @param elevation the elevation
+     * @return the color
+     */
+    public Color getColor(int elevation) {
+        // empty color map?
+        if (colorList == null || colorList.size() == 0) {
+            return Color.white;
+        }
 
-		// out of range?
-		if (elevation < colorList.get(0).ele) {
-			return colorList.get(0).getColor();
-		}
+        // out of range?
+        if (elevation < colorList.get(0).ele) {
+            return colorList.get(0).getColor();
+        }
 
-		int last = colorList.size() - 1;
-		if (elevation > colorList.get(last).ele) {
-			return colorList.get(last).getColor();
-		}
+        int last = colorList.size() - 1;
+        if (elevation > colorList.get(last).ele) {
+            return colorList.get(last).getColor();
+        }
 
-		// find elevation section
-		for (int i = 0; i < last; i++) {
-			ColorMapEntry e1 = colorList.get(i);
-			ColorMapEntry e2 = colorList.get(i + 1);
+        // find elevation section
+        for (int i = 0; i < last; i++) {
+            ColorMapEntry e1 = colorList.get(i);
+            ColorMapEntry e2 = colorList.get(i + 1);
 
-			// elevation within range?
-			if (e1.getEle() <= elevation && e2.getEle() >= elevation) {
+            // elevation within range?
+            if (e1.getEle() <= elevation && e2.getEle() >= elevation) {
 
-				// interpolate color between both
-				double val = (elevation - e1.getEle()) / (double)(e2.getEle() - e1.getEle());
-				return interpolate(e1.getColor(), e2.getColor(), val);
-			}
-		}
+                // interpolate color between both
+                double val = (elevation - e1.getEle()) / (double)(e2.getEle() - e1.getEle());
+                return interpolate(e1.getColor(), e2.getColor(), val);
+            }
+        }
 
-		// here we should never end!
-		throw new RuntimeException("Inconsistent color map - found no entry for elevation " + elevation);
-	}
+        // here we should never end!
+        throw new RuntimeException("Inconsistent color map - found no entry for elevation " + elevation);
+    }
 
 
-	/**
-	 * Gets the color map with the given name.
-	 *
-	 * @param name the name
-	 * @return the map or <code>null</code>, if no such map exists
-	 */
-	public static ColorMap getMap(String name) {
-		if (colorMaps.containsKey(name)) {
-			return colorMaps.get(name);
-		}
-		return null;
-	}
+    /**
+     * Gets the color map with the given name.
+     *
+     * @param name the name
+     * @return the map or <code>null</code>, if no such map exists
+     */
+    public static ColorMap getMap(String name) {
+        if (colorMaps.containsKey(name)) {
+            return colorMaps.get(name);
+        }
+        return null;
+    }
 
-	/**
-	 * Gets the number of available color maps.
-	 *
-	 * @return the int
-	 */
-	public static int size() {
-		return colorMaps != null ? colorMaps.size() : 0;
-	}
+    /**
+     * Gets the number of available color maps.
+     *
+     * @return the int
+     */
+    public static int size() {
+        return colorMaps != null ? colorMaps.size() : 0;
+    }
 
 
-	/**
-	 * Gets the available color map names.
-	 *
-	 * @param name the name
-	 * @return the map or <code>null</code>, if no such map exists
-	 */
-	public static String[] getNames() {
-		return colorMaps.keySet().toArray(new String[size()]);
-	}
+    /**
+     * Gets the available color map names.
+     *
+     * @param name the name
+     * @return the map or <code>null</code>, if no such map exists
+     */
+    public static String[] getNames() {
+        return colorMaps.keySet().toArray(new String[size()]);
+    }
 
-	private static void registerColorMap(ColorMap newMap) {
-		CheckParameterUtil.ensureParameterNotNull(newMap);
-		colorMaps.put(newMap.getName(), newMap);
-	}
+    private static void registerColorMap(ColorMap newMap) {
+        CheckParameterUtil.ensureParameterNotNull(newMap);
+        colorMaps.put(newMap.getName(), newMap);
+    }
 
-	public static void unregisterColorMap(String name) {
-		if (colorMaps.containsKey(name)) {
-			colorMaps.remove(name);
-		}
-	}
+    public static void unregisterColorMap(String name) {
+        if (colorMaps.containsKey(name)) {
+            colorMaps.remove(name);
+        }
+    }
 
-	public static Color interpolate(java.awt.Color c1, java.awt.Color c2, double ratio) {
-		double r1 = 1 -ratio;
-		// clip
-		if (r1 < 0) r1 = 0d;
-		if (r1 > 1) r1 = 1d;
-		double r2 = 1 - r1;
+    public static Color interpolate(java.awt.Color c1, java.awt.Color c2, double ratio) {
+        double r1 = 1 -ratio;
+        // clip
+        if (r1 < 0) r1 = 0d;
+        if (r1 > 1) r1 = 1d;
+        double r2 = 1 - r1;
 
-		int r = (int) Math.round((r1 * c1.getRed()) + (r2 * c2.getRed()));
-		int g = (int) Math.round((r1 * c1.getGreen()) + (r2 * c2.getGreen()));
-		int b = (int) Math.round((r1 * c1.getBlue()) + (r2 * c2.getBlue()));
-		return new Color(r, g, b);
-	}
+        int r = (int) Math.round((r1 * c1.getRed()) + (r2 * c2.getRed()));
+        int g = (int) Math.round((r1 * c1.getGreen()) + (r2 * c2.getGreen()));
+        int b = (int) Math.round((r1 * c1.getBlue()) + (r2 * c2.getBlue()));
+        return new Color(r, g, b);
+    }
 
-	/**
-	 * Creates a color map using the given colors/elevation values.
-	 * Both arrays must have same length.
-	 *
-	 * @param name the name of the color map
-	 * @param colors the array containing the colors
-	 * @param ele the elevation values
-	 * @return the color map
-	 */
-	public static ColorMap create(String name, Color[] colors, int[] ele) {
-		CheckParameterUtil.ensureParameterNotNull(colors);
-		CheckParameterUtil.ensureParameterNotNull(ele);
+    /**
+     * Creates a color map using the given colors/elevation values.
+     * Both arrays must have same length.
+     *
+     * @param name the name of the color map
+     * @param colors the array containing the colors
+     * @param ele the elevation values
+     * @return the color map
+     */
+    public static ColorMap create(String name, Color[] colors, int[] ele) {
+        CheckParameterUtil.ensureParameterNotNull(colors);
+        CheckParameterUtil.ensureParameterNotNull(ele);
 
-		if (colors.length != ele.length) {
-			throw new IllegalArgumentException("Arrays colors and ele must have same length: " + colors.length + " vs " + ele.length);
-		}
+        if (colors.length != ele.length) {
+            throw new IllegalArgumentException("Arrays colors and ele must have same length: " + colors.length + " vs " + ele.length);
+        }
 
-		ColorMap map = new ColorMap();
-		map.colorList = new ArrayList<>();
-		map.name = name;
-		for (int i = 0; i < ele.length; i++) {
-			map.colorList.add(map.new ColorMapEntry(colors[i], ele[i]));
-		}
+        ColorMap map = new ColorMap();
+        map.colorList = new ArrayList<>();
+        map.name = name;
+        for (int i = 0; i < ele.length; i++) {
+            map.colorList.add(map.new ColorMapEntry(colors[i], ele[i]));
+        }
 
-		// sort by elevation
-		Collections.sort(map.colorList);
+        // sort by elevation
+        Collections.sort(map.colorList);
 
-		registerColorMap(map);
-		return map;
-	}
+        registerColorMap(map);
+        return map;
+    }
 
 
-	class ColorMapEntry implements Comparable<ColorMapEntry> {
-		private final int ele; // limit
-		private final Color color;
+    class ColorMapEntry implements Comparable<ColorMapEntry> {
+        private final int ele; // limit
+        private final Color color;
 
-		public ColorMapEntry(Color color, int ele) {
-			super();
-			this.color = color;
-			this.ele = ele;
-		}
+        public ColorMapEntry(Color color, int ele) {
+            super();
+            this.color = color;
+            this.ele = ele;
+        }
 
-		public int getEle() {
-			return ele;
-		}
+        public int getEle() {
+            return ele;
+        }
 
-		public Color getColor() {
-			return color;
-		}
+        public Color getColor() {
+            return color;
+        }
 
-		@Override
-		public int compareTo(ColorMapEntry o) {
-			return this.ele - o.ele;
-		}
-	}
+        @Override
+        public int compareTo(ColorMapEntry o) {
+            return this.ele - o.ele;
+        }
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 32315)
@@ -19,282 +19,282 @@
  */
 public class ElevationHelper {
-	public static double METER_TO_FEET = 3.280948;
-
-	/* Countries which use the imperial system instead of the metric system. */
-	private static String IMPERIAL_SYSTEM_COUNTRIES[] = {
-		"en_US",     /* USA */
-		"en_CA",    /* Canada */
-		"en_AU",    /* Australia */
-		"en_NZ",    /* New Zealand */
-		//        "de_DE",    /* for testing only */
-		"en_ZA"    /* South Africa */
-	};
-
-	/** The 'no elevation' data magic. */
-	public static double NO_ELEVATION = Double.NaN;
-
-	/**
-	 * The name of the elevation height of a way point.
-	 */
-	public static final String HEIGHT_ATTRIBUTE = "ele";
-
-	private static UnitMode unitMode = UnitMode.NotSelected;
-
-	private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None;
-
-	/** The HGT reader instance. */
-	private static HgtReader hgt = new HgtReader();
-
-	/**
-	 * Gets the current mode of GEOID correction.
-	 * @return
-	 */
-	public static GeoidCorrectionKind getGeoidKind() {
-		return geoidKind;
-	}
-
-	public static void setGeoidKind(GeoidCorrectionKind geoidKind) {
-		ElevationHelper.geoidKind = geoidKind;
-	}
-
-	/**
-	 * Gets the current unit mode (metric or imperial).
-	 * @return
-	 */
-	public static UnitMode getUnitMode() {
-		//TODO: Use this until /JOSM/src/org/openstreetmap/josm/gui/NavigatableComponent.java
-		// has a an appropriate method
-
-		// unit mode already determined?
-		if (unitMode != UnitMode.NotSelected) {
-			return unitMode;
-		}
-
-		// Set default
-		unitMode = UnitMode.Metric;
-
-		// Check if user could prefer imperial system
-		Locale l = Locale.getDefault();
-		for (int i = 0; i < IMPERIAL_SYSTEM_COUNTRIES.length; i++) {
-			String ctry = l.toString();
-			if (IMPERIAL_SYSTEM_COUNTRIES[i].equals(ctry)) {
-				unitMode = UnitMode.Imperial;
-			}
-		}
-
-		return unitMode;
-	}
-
-	/**
-	 * Gets the unit string for elevation ("m" or "ft").
-	 * @return
-	 */
-	public static String getUnit() {
-		switch (getUnitMode()) {
-		case Metric:
-			return "m";
-		case Imperial:
-			return "ft";
-		default:
-			throw new RuntimeException("Invalid or unsupported unit mode: " + unitMode);
-		}
-	}
-
-	/**
-	 * Checks if given value is a valid elevation value.
-	 *
-	 * @param ele the ele
-	 * @return true, if is valid elevation
-	 */
-	public static boolean isValidElevation(double ele) {
-		return !Double.isNaN(ele);
-	}
-
-	/**
-	 * Gets the elevation (Z coordinate) of a GPX way point in meter or feet (for
-	 * US, UK, ZA, AU, NZ and CA).
-	 *
-	 * @param wpt
-	 *            The way point instance.
-	 * @return The x coordinate or <code>NO_ELEVATION</code>, if the given way point is null or contains
-	 *         not height attribute.
-	 */
-	public static double getElevation(WayPoint wpt) {
-		if (wpt == null) return NO_ELEVATION;
-
-		// try to get elevation from HGT file
-		double eleInt = getSrtmElevation(wpt.getCoor());
-		if (isValidElevation(eleInt)) {
-			return convert(eleInt);
-		}
-
-		// no HGT, check for elevation data in GPX
-		if (!wpt.attr.containsKey(HEIGHT_ATTRIBUTE)) {
-			// GPX has no elevation data :-(
-			return NO_ELEVATION;
-		}
-
-		// Parse elevation from GPX data
-		String height = wpt.getString(ElevationHelper.HEIGHT_ATTRIBUTE);
-		try {
-			double z = Double.parseDouble(height);
-
-			return convert(z);
-		} catch (NumberFormatException e) {
-			System.err.println(String.format(
-					"Cannot parse double from '%s': %s", height, e
-					.getMessage()));
-			return NO_ELEVATION;
-		}
-	}
-
-
-	private static double getElevation(LatLon ll) {
-		double ele = getSrtmElevation(ll);
-		//System.out.println("Get elevation " + ll + " => " + ele);
-		return convert(ele);
-	}
-
-	/**
-	 * Converts the value to feet, if required.
-	 *
-	 * @param ele the elevation to convert
-	 * @return the double
-	 */
-	private static double convert(double ele) {
-		if (isValidElevation(ele)) {
-			if (getUnitMode() == UnitMode.Imperial) {
-				// translate to feet
-				return meter2Feet(ele);
-			} else {
-				// keep 'as is'
-				return ele;
-			}
-		}
-		return NO_ELEVATION;
-	}
-
-	/**
-	 * Computes the slope <b>in percent</b> between two way points. E. g. an elevation gain of 12m
-	 * within a distance of 100m is equal to a slope of 12%.
-	 *
-	 * @param w1 the first way point
-	 * @param w2 the second way point
-	 * @return the slope in percent
-	 */
-	public static double computeSlope(LatLon w1, LatLon w2) {
-		// same coordinates? -> return 0, if yes
-		if (w1.equals(w2)) return 0;
-
-		// get distance in meters and divide it by 100 in advance
-		double distInMeter = convert(w1.greatCircleDistance(w2) / 100.0);
-
-		// get elevation (difference) - is converted automatically to feet
-		int ele1 = (int) ElevationHelper.getElevation(w1);
-		int ele2 = (int) ElevationHelper.getElevation(w2);
-		int dH = ele2 - ele1;
-
-		// Slope in percent is define as elevation gain/loss in meters related to a distance of 100m
-		return dH / distInMeter;
-	}
-
-	/**
-	 * Converts meter into feet
-	 *
-	 * @param meter the meter
-	 * @return the double
-	 */
-	public static double meter2Feet(double meter) {
-		return meter * METER_TO_FEET;
-	}
-
-	/**
-	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
-	 * @param elevation
-	 * @return
-	 */
-	public static String getElevationText(int elevation) {
-		return String.format("%d %s", elevation, getUnit());
-	}
-
-	/**
-	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
-	 * @param elevation
-	 * @return
-	 */
-	public static String getElevationText(double elevation) {
-		return String.format("%d %s", (int)Math.round(elevation), getUnit());
-	}
-
-	/**
-	 * Gets the elevation string for a given way point, e. g "300m" or "800ft".
-	 *
-	 * @param wpt the way point
-	 * @return the elevation text
-	 */
-	public static String getElevationText(WayPoint wpt) {
-		if (wpt == null) return "-";
-
-		int elevation = (int)Math.round(ElevationHelper.getElevation(wpt));
-		return String.format("%d %s", elevation, getUnit());
-	}
-
-	/**
-	 * Get the time string for a given way point.
-	 * @param wpt
-	 * @return
-	 */
-	public static String getTimeText(WayPoint wpt) {
-		if (wpt == null) return null;
-
-		int hour = ElevationHelper.getHourOfWayPoint(wpt);
-		int min = ElevationHelper.getMinuteOfWayPoint(wpt);
-		return String.format("%02d:%02d", hour, min);
-	}
-
-	/**
-	 * Gets the SRTM elevation (Z coordinate) of the given coordinate.
-	 *
-	 * @param ll
-	 *            The coordinate.
-	 * @return The z coordinate or {@link Double#NaN}, if elevation value could not be obtained
-	 *         not height attribute.
-	 */
-	public static double getSrtmElevation(LatLon ll) {
-		if (ll != null) {
-			// Try to read data from SRTM file
-			// TODO: Option to switch this off
-			double eleHgt = hgt.getElevationFromHgt(ll);
-
-			//System.out.println("Get elevation from HGT " + ll + " => " + eleHgt);
-			if (isValidElevation(eleHgt)) {
-				return eleHgt;
-			}
-		}
-		return NO_ELEVATION;
-	}
-
-	/**
-	 * Checks given area for SRTM data.
-	 *
-	 * @param bounds the bounds/area to check
-	 * @return true, if SRTM data are present; otherwise false
-	 */
-	public static boolean hasSrtmData(Bounds bounds) {
-		if (bounds == null) return false;
-
-		LatLon tl = bounds.getMin();
-		LatLon br = bounds.getMax();
-
-		return     isValidElevation(getSrtmElevation(tl)) &&
-				isValidElevation(getSrtmElevation(br));
-	}
-
-	/*
-	 * Gets the geoid height for the given way point. See also {@link
-	 * GeoidData}.
-	 */
-	public static byte getGeoidCorrection(WayPoint wpt) {
-		/*
+    public static double METER_TO_FEET = 3.280948;
+
+    /* Countries which use the imperial system instead of the metric system. */
+    private static String IMPERIAL_SYSTEM_COUNTRIES[] = {
+        "en_US",     /* USA */
+        "en_CA",    /* Canada */
+        "en_AU",    /* Australia */
+        "en_NZ",    /* New Zealand */
+        //        "de_DE",    /* for testing only */
+        "en_ZA"    /* South Africa */
+    };
+
+    /** The 'no elevation' data magic. */
+    public static double NO_ELEVATION = Double.NaN;
+
+    /**
+     * The name of the elevation height of a way point.
+     */
+    public static final String HEIGHT_ATTRIBUTE = "ele";
+
+    private static UnitMode unitMode = UnitMode.NotSelected;
+
+    private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None;
+
+    /** The HGT reader instance. */
+    private static HgtReader hgt = new HgtReader();
+
+    /**
+     * Gets the current mode of GEOID correction.
+     * @return
+     */
+    public static GeoidCorrectionKind getGeoidKind() {
+        return geoidKind;
+    }
+
+    public static void setGeoidKind(GeoidCorrectionKind geoidKind) {
+        ElevationHelper.geoidKind = geoidKind;
+    }
+
+    /**
+     * Gets the current unit mode (metric or imperial).
+     * @return
+     */
+    public static UnitMode getUnitMode() {
+        //TODO: Use this until /JOSM/src/org/openstreetmap/josm/gui/NavigatableComponent.java
+        // has a an appropriate method
+
+        // unit mode already determined?
+        if (unitMode != UnitMode.NotSelected) {
+            return unitMode;
+        }
+
+        // Set default
+        unitMode = UnitMode.Metric;
+
+        // Check if user could prefer imperial system
+        Locale l = Locale.getDefault();
+        for (int i = 0; i < IMPERIAL_SYSTEM_COUNTRIES.length; i++) {
+            String ctry = l.toString();
+            if (IMPERIAL_SYSTEM_COUNTRIES[i].equals(ctry)) {
+                unitMode = UnitMode.Imperial;
+            }
+        }
+
+        return unitMode;
+    }
+
+    /**
+     * Gets the unit string for elevation ("m" or "ft").
+     * @return
+     */
+    public static String getUnit() {
+        switch (getUnitMode()) {
+        case Metric:
+            return "m";
+        case Imperial:
+            return "ft";
+        default:
+            throw new RuntimeException("Invalid or unsupported unit mode: " + unitMode);
+        }
+    }
+
+    /**
+     * Checks if given value is a valid elevation value.
+     *
+     * @param ele the ele
+     * @return true, if is valid elevation
+     */
+    public static boolean isValidElevation(double ele) {
+        return !Double.isNaN(ele);
+    }
+
+    /**
+     * Gets the elevation (Z coordinate) of a GPX way point in meter or feet (for
+     * US, UK, ZA, AU, NZ and CA).
+     *
+     * @param wpt
+     *            The way point instance.
+     * @return The x coordinate or <code>NO_ELEVATION</code>, if the given way point is null or contains
+     *         not height attribute.
+     */
+    public static double getElevation(WayPoint wpt) {
+        if (wpt == null) return NO_ELEVATION;
+
+        // try to get elevation from HGT file
+        double eleInt = getSrtmElevation(wpt.getCoor());
+        if (isValidElevation(eleInt)) {
+            return convert(eleInt);
+        }
+
+        // no HGT, check for elevation data in GPX
+        if (!wpt.attr.containsKey(HEIGHT_ATTRIBUTE)) {
+            // GPX has no elevation data :-(
+            return NO_ELEVATION;
+        }
+
+        // Parse elevation from GPX data
+        String height = wpt.getString(ElevationHelper.HEIGHT_ATTRIBUTE);
+        try {
+            double z = Double.parseDouble(height);
+
+            return convert(z);
+        } catch (NumberFormatException e) {
+            System.err.println(String.format(
+                    "Cannot parse double from '%s': %s", height, e
+                    .getMessage()));
+            return NO_ELEVATION;
+        }
+    }
+
+
+    private static double getElevation(LatLon ll) {
+        double ele = getSrtmElevation(ll);
+        //System.out.println("Get elevation " + ll + " => " + ele);
+        return convert(ele);
+    }
+
+    /**
+     * Converts the value to feet, if required.
+     *
+     * @param ele the elevation to convert
+     * @return the double
+     */
+    private static double convert(double ele) {
+        if (isValidElevation(ele)) {
+            if (getUnitMode() == UnitMode.Imperial) {
+                // translate to feet
+                return meter2Feet(ele);
+            } else {
+                // keep 'as is'
+                return ele;
+            }
+        }
+        return NO_ELEVATION;
+    }
+
+    /**
+     * Computes the slope <b>in percent</b> between two way points. E. g. an elevation gain of 12m
+     * within a distance of 100m is equal to a slope of 12%.
+     *
+     * @param w1 the first way point
+     * @param w2 the second way point
+     * @return the slope in percent
+     */
+    public static double computeSlope(LatLon w1, LatLon w2) {
+        // same coordinates? -> return 0, if yes
+        if (w1.equals(w2)) return 0;
+
+        // get distance in meters and divide it by 100 in advance
+        double distInMeter = convert(w1.greatCircleDistance(w2) / 100.0);
+
+        // get elevation (difference) - is converted automatically to feet
+        int ele1 = (int) ElevationHelper.getElevation(w1);
+        int ele2 = (int) ElevationHelper.getElevation(w2);
+        int dH = ele2 - ele1;
+
+        // Slope in percent is define as elevation gain/loss in meters related to a distance of 100m
+        return dH / distInMeter;
+    }
+
+    /**
+     * Converts meter into feet
+     *
+     * @param meter the meter
+     * @return the double
+     */
+    public static double meter2Feet(double meter) {
+        return meter * METER_TO_FEET;
+    }
+
+    /**
+     * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
+     * @param elevation
+     * @return
+     */
+    public static String getElevationText(int elevation) {
+        return String.format("%d %s", elevation, getUnit());
+    }
+
+    /**
+     * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
+     * @param elevation
+     * @return
+     */
+    public static String getElevationText(double elevation) {
+        return String.format("%d %s", (int)Math.round(elevation), getUnit());
+    }
+
+    /**
+     * Gets the elevation string for a given way point, e. g "300m" or "800ft".
+     *
+     * @param wpt the way point
+     * @return the elevation text
+     */
+    public static String getElevationText(WayPoint wpt) {
+        if (wpt == null) return "-";
+
+        int elevation = (int)Math.round(ElevationHelper.getElevation(wpt));
+        return String.format("%d %s", elevation, getUnit());
+    }
+
+    /**
+     * Get the time string for a given way point.
+     * @param wpt
+     * @return
+     */
+    public static String getTimeText(WayPoint wpt) {
+        if (wpt == null) return null;
+
+        int hour = ElevationHelper.getHourOfWayPoint(wpt);
+        int min = ElevationHelper.getMinuteOfWayPoint(wpt);
+        return String.format("%02d:%02d", hour, min);
+    }
+
+    /**
+     * Gets the SRTM elevation (Z coordinate) of the given coordinate.
+     *
+     * @param ll
+     *            The coordinate.
+     * @return The z coordinate or {@link Double#NaN}, if elevation value could not be obtained
+     *         not height attribute.
+     */
+    public static double getSrtmElevation(LatLon ll) {
+        if (ll != null) {
+            // Try to read data from SRTM file
+            // TODO: Option to switch this off
+            double eleHgt = hgt.getElevationFromHgt(ll);
+
+            //System.out.println("Get elevation from HGT " + ll + " => " + eleHgt);
+            if (isValidElevation(eleHgt)) {
+                return eleHgt;
+            }
+        }
+        return NO_ELEVATION;
+    }
+
+    /**
+     * Checks given area for SRTM data.
+     *
+     * @param bounds the bounds/area to check
+     * @return true, if SRTM data are present; otherwise false
+     */
+    public static boolean hasSrtmData(Bounds bounds) {
+        if (bounds == null) return false;
+
+        LatLon tl = bounds.getMin();
+        LatLon br = bounds.getMax();
+
+        return     isValidElevation(getSrtmElevation(tl)) &&
+                isValidElevation(getSrtmElevation(br));
+    }
+
+    /*
+     * Gets the geoid height for the given way point. See also {@link
+     * GeoidData}.
+     */
+    public static byte getGeoidCorrection(WayPoint wpt) {
+        /*
         int lat = (int)Math.round(wpt.getCoor().lat());
         int lon = (int)Math.round(wpt.getCoor().lon());
@@ -303,66 +303,66 @@
         System.out.println(
                 String.format("Geoid(%d, %d) = %d", lat, lon, geoid));
-		 */
-		return 0;
-	}
-
-	/**
-	 * Reduces a given list of way points to the specified target size.
-	 *
-	 * @param origList
-	 *            The original list containing the way points.
-	 * @param targetSize
-	 *            The desired target size of the list. The resulting list may
-	 *            contain fewer items, so targetSize should be considered as
-	 *            maximum.
-	 * @return A list containing the reduced list.
-	 */
-	public static List<WayPoint> downsampleWayPoints(List<WayPoint> origList,
-			int targetSize) {
-		if (origList == null)
-			return null;
-		if (targetSize <= 0)
-			throw new IllegalArgumentException(
-					"targetSize must be greater than zero");
-
-		int origSize = origList.size();
-		if (origSize <= targetSize) {
-			return origList;
-		}
-
-		int delta = (int) Math.max(Math.ceil(origSize / targetSize), 2);
-
-		List<WayPoint> res = new ArrayList<>(targetSize);
-		for (int i = 0; i < origSize; i += delta) {
-			res.add(origList.get(i));
-		}
-
-		return res;
-	}
-
-	/**
-	 * Gets the hour value of a way point in 24h format.
-	 * @param wpt
-	 * @return
-	 */
-	public static int getHourOfWayPoint(WayPoint wpt) {
-		if (wpt == null) return -1;
-
-		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-		calendar.setTime(wpt.getTime());   // assigns calendar to given date
-		return calendar.get(Calendar.HOUR_OF_DAY);
-	}
-
-	/**
-	 * Gets the minute value of a way point in 24h format.
-	 * @param wpt
-	 * @return
-	 */
-	public static int getMinuteOfWayPoint(WayPoint wpt) {
-		if (wpt == null) return -1;
-
-		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-		calendar.setTime(wpt.getTime());   // assigns calendar to given date
-		return calendar.get(Calendar.MINUTE);
-	}
+         */
+        return 0;
+    }
+
+    /**
+     * Reduces a given list of way points to the specified target size.
+     *
+     * @param origList
+     *            The original list containing the way points.
+     * @param targetSize
+     *            The desired target size of the list. The resulting list may
+     *            contain fewer items, so targetSize should be considered as
+     *            maximum.
+     * @return A list containing the reduced list.
+     */
+    public static List<WayPoint> downsampleWayPoints(List<WayPoint> origList,
+            int targetSize) {
+        if (origList == null)
+            return null;
+        if (targetSize <= 0)
+            throw new IllegalArgumentException(
+                    "targetSize must be greater than zero");
+
+        int origSize = origList.size();
+        if (origSize <= targetSize) {
+            return origList;
+        }
+
+        int delta = (int) Math.max(Math.ceil(origSize / targetSize), 2);
+
+        List<WayPoint> res = new ArrayList<>(targetSize);
+        for (int i = 0; i < origSize; i += delta) {
+            res.add(origList.get(i));
+        }
+
+        return res;
+    }
+
+    /**
+     * Gets the hour value of a way point in 24h format.
+     * @param wpt
+     * @return
+     */
+    public static int getHourOfWayPoint(WayPoint wpt) {
+        if (wpt == null) return -1;
+
+        Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
+        calendar.setTime(wpt.getTime());   // assigns calendar to given date
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    /**
+     * Gets the minute value of a way point in 24h format.
+     * @param wpt
+     * @return
+     */
+    public static int getMinuteOfWayPoint(WayPoint wpt) {
+        if (wpt == null) return -1;
+
+        Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
+        calendar.setTime(wpt.getTime());   // assigns calendar to given date
+        return calendar.get(Calendar.MINUTE);
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 32315)
@@ -23,104 +23,104 @@
 public class ElevationProfilePlugin extends Plugin {
 
-	private static ElevationProfileLayer currentLayer;
+    private static ElevationProfileLayer currentLayer;
 
-	/**
-	 * Initializes the plugin.
-	 * @param info Context information about the plugin.
-	 */
-	public ElevationProfilePlugin(PluginInformation info) {
-		super(info);
+    /**
+     * Initializes the plugin.
+     * @param info Context information about the plugin.
+     */
+    public ElevationProfilePlugin(PluginInformation info) {
+        super(info);
 
-		createColorMaps();
+        createColorMaps();
 
-		// TODO: Disable this view as long as it is not stable
-		MainMenu.add(Main.main.menu.imagerySubMenu, new AddElevationLayerAction(), false, 0);
-	}
+        // TODO: Disable this view as long as it is not stable
+        MainMenu.add(Main.main.menu.imagerySubMenu, new AddElevationLayerAction(), false, 0);
+    }
 
-	/**
-	 * Called after Main.mapFrame is initialized. (After the first data is loaded).
-	 * You can use this callback to tweak the newFrame to your needs, as example install
-	 * an alternative Painter.
-	 */
-	@Override
-	public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-		super.mapFrameInitialized(oldFrame, newFrame);
+    /**
+     * Called after Main.mapFrame is initialized. (After the first data is loaded).
+     * You can use this callback to tweak the newFrame to your needs, as example install
+     * an alternative Painter.
+     */
+    @Override
+    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+        super.mapFrameInitialized(oldFrame, newFrame);
 
-		if (newFrame != null) {
-			ElevationMapMode eleMode = new ElevationMapMode("Elevation profile", newFrame);
-			newFrame.addMapMode(new IconToggleButton(eleMode));
-			ElevationProfileDialog eleProfileDlg = new ElevationProfileDialog();
-			eleProfileDlg.addModelListener(eleMode);
-			eleProfileDlg.setProfileLayer(getCurrentLayer());
-			newFrame.addToggleDialog(eleProfileDlg);
-		}
-	}
+        if (newFrame != null) {
+            ElevationMapMode eleMode = new ElevationMapMode("Elevation profile", newFrame);
+            newFrame.addMapMode(new IconToggleButton(eleMode));
+            ElevationProfileDialog eleProfileDlg = new ElevationProfileDialog();
+            eleProfileDlg.addModelListener(eleMode);
+            eleProfileDlg.setProfileLayer(getCurrentLayer());
+            newFrame.addToggleDialog(eleProfileDlg);
+        }
+    }
 
-	/**
-	 * Gets the elevation profile layer which decorates the current layer
-	 * with some markers.
-	 * @return
-	 */
-	public static ElevationProfileLayer getCurrentLayer(){
-		if(currentLayer == null){
-			currentLayer = new ElevationProfileLayer(tr("Elevation Profile"));
-			Main.main.addLayer(currentLayer);
-		}
-		return currentLayer;
-	}
+    /**
+     * Gets the elevation profile layer which decorates the current layer
+     * with some markers.
+     * @return
+     */
+    public static ElevationProfileLayer getCurrentLayer(){
+        if(currentLayer == null){
+            currentLayer = new ElevationProfileLayer(tr("Elevation Profile"));
+            Main.main.addLayer(currentLayer);
+        }
+        return currentLayer;
+    }
 
-	private void createColorMaps() {
-		// Data taken from http://proceedings.esri.com/library/userconf/proc98/proceed/to850/pap842/p842.htm
-		ColorMap.create("Physical_US",
-				new Color[]{
-						new Color(18,129,242),
-						new Color(113,153,89),
-						new Color(117,170,101),
-						new Color(149,190,113),
-						new Color(178,214,117),
-						new Color(202,226,149),
-						new Color(222,238,161),
-						new Color(242,238,161),
-						new Color(238,222,153),
-						new Color(242,206,133),
-						new Color(234,182,129),
-						new Color(218,157,121),
-						new Color(194,141,125),
-						new Color(214,157,145),
-						new Color(226,174,165),
-						new Color(222,186,182),
-						new Color(238,198,210),
-						new Color(255,206,226),
-						new Color(250,218,234),
-						new Color(255,222,230),
-						new Color(255,230,242),
-						new Color(255,242,255)
-		},
-				// elevation in meters - the page above uses feet, so these values differs slightly
-				new int[]{
-						-3000,
-						0,
-						150,
-						300,
-						450,
-						600,
-						750,
-						900,
-						1050,
-						1200,
-						1350,
-						1500,
-						1650,
-						1800,
-						1950,
-						2100,
-						2250,
-						2400,
-						2550,
-						2700,
-						2750,
-						3000
-		}
-				);
-	}
+    private void createColorMaps() {
+        // Data taken from http://proceedings.esri.com/library/userconf/proc98/proceed/to850/pap842/p842.htm
+        ColorMap.create("Physical_US",
+                new Color[]{
+                        new Color(18,129,242),
+                        new Color(113,153,89),
+                        new Color(117,170,101),
+                        new Color(149,190,113),
+                        new Color(178,214,117),
+                        new Color(202,226,149),
+                        new Color(222,238,161),
+                        new Color(242,238,161),
+                        new Color(238,222,153),
+                        new Color(242,206,133),
+                        new Color(234,182,129),
+                        new Color(218,157,121),
+                        new Color(194,141,125),
+                        new Color(214,157,145),
+                        new Color(226,174,165),
+                        new Color(222,186,182),
+                        new Color(238,198,210),
+                        new Color(255,206,226),
+                        new Color(250,218,234),
+                        new Color(255,222,230),
+                        new Color(255,230,242),
+                        new Color(255,242,255)
+        },
+                // elevation in meters - the page above uses feet, so these values differs slightly
+                new int[]{
+                        -3000,
+                        0,
+                        150,
+                        300,
+                        450,
+                        600,
+                        750,
+                        900,
+                        1050,
+                        1200,
+                        1350,
+                        1500,
+                        1650,
+                        1800,
+                        1950,
+                        2100,
+                        2250,
+                        2400,
+                        2550,
+                        2700,
+                        2750,
+                        3000
+        }
+                );
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 32315)
@@ -22,152 +22,152 @@
  */
 public class HgtReader {
-	private static final int SECONDS_PER_MINUTE = 60;
+    private static final int SECONDS_PER_MINUTE = 60;
 
-	public static final String HGT_EXT = ".hgt";
+    public static final String HGT_EXT = ".hgt";
 
-	// alter these values for different SRTM resolutions
-	public static final int HGT_RES = 3; // resolution in arc seconds
-	public static final int HGT_ROW_LENGTH = 1201; // number of elevation values per line
-	public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file
+    // alter these values for different SRTM resolutions
+    public static final int HGT_RES = 3; // resolution in arc seconds
+    public static final int HGT_ROW_LENGTH = 1201; // number of elevation values per line
+    public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file
 
-	private final HashMap<String, ShortBuffer> cache = new HashMap<>();
+    private final HashMap<String, ShortBuffer> cache = new HashMap<>();
 
-	public double getElevationFromHgt(LatLon coor) {
-		try {
-			String file = getHgtFileName(coor);
-			// given area in cache?
-			if (!cache.containsKey(file)) {
+    public double getElevationFromHgt(LatLon coor) {
+        try {
+            String file = getHgtFileName(coor);
+            // given area in cache?
+            if (!cache.containsKey(file)) {
 
-				// fill initial cache value. If no file is found, then
-				// we use it as a marker to indicate 'file has been searched
-				// but is not there'
-				cache.put(file, null);
-				// Try all resource directories
-				for (String location : Main.pref.getAllPossiblePreferenceDirs()) {
-					String fullPath = new File(location + File.separator + "elevation", file).getPath();
-					File f = new File(fullPath);
-					if (f.exists()) {
-						// found something: read HGT file...
-						ShortBuffer data = readHgtFile(fullPath);
-						// ... and store result in cache
-						cache.put(file, data);
-						break;
-					}
-				}
-			}
+                // fill initial cache value. If no file is found, then
+                // we use it as a marker to indicate 'file has been searched
+                // but is not there'
+                cache.put(file, null);
+                // Try all resource directories
+                for (String location : Main.pref.getAllPossiblePreferenceDirs()) {
+                    String fullPath = new File(location + File.separator + "elevation", file).getPath();
+                    File f = new File(fullPath);
+                    if (f.exists()) {
+                        // found something: read HGT file...
+                        ShortBuffer data = readHgtFile(fullPath);
+                        // ... and store result in cache
+                        cache.put(file, data);
+                        break;
+                    }
+                }
+            }
 
-			// read elevation value
-			return readElevation(coor);
-		} catch (FileNotFoundException e) {
-			System.err.println("Get elevation from HGT " + coor + " failed: => " + e.getMessage());
-			// no problem... file not there
-			return ElevationHelper.NO_ELEVATION;
-		} catch (Exception ioe) {
-			// oops...
-			ioe.printStackTrace(System.err);
-			// fallback
-			return ElevationHelper.NO_ELEVATION;
-		}
-	}
+            // read elevation value
+            return readElevation(coor);
+        } catch (FileNotFoundException e) {
+            System.err.println("Get elevation from HGT " + coor + " failed: => " + e.getMessage());
+            // no problem... file not there
+            return ElevationHelper.NO_ELEVATION;
+        } catch (Exception ioe) {
+            // oops...
+            ioe.printStackTrace(System.err);
+            // fallback
+            return ElevationHelper.NO_ELEVATION;
+        }
+    }
 
-	@SuppressWarnings("resource")
-	private ShortBuffer readHgtFile(String file) throws Exception {
-		CheckParameterUtil.ensureParameterNotNull(file);
+    @SuppressWarnings("resource")
+    private ShortBuffer readHgtFile(String file) throws Exception {
+        CheckParameterUtil.ensureParameterNotNull(file);
 
-		FileChannel fc = null;
-		ShortBuffer sb = null;
-		try {
-			// Eclipse complains here about resource leak on 'fc' - even with 'finally' clause???
-			fc = new FileInputStream(file).getChannel();
-			// choose the right endianness
+        FileChannel fc = null;
+        ShortBuffer sb = null;
+        try {
+            // Eclipse complains here about resource leak on 'fc' - even with 'finally' clause???
+            fc = new FileInputStream(file).getChannel();
+            // choose the right endianness
 
-			ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
-			while (bb.remaining() > 0) fc.read(bb);
+            ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
+            while (bb.remaining() > 0) fc.read(bb);
 
-			bb.flip();
-			//sb = bb.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
-			sb = bb.order(ByteOrder.BIG_ENDIAN).asShortBuffer();
-		} finally {
-			if (fc != null) fc.close();
-		}
+            bb.flip();
+            //sb = bb.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
+            sb = bb.order(ByteOrder.BIG_ENDIAN).asShortBuffer();
+        } finally {
+            if (fc != null) fc.close();
+        }
 
-		return sb;
-	}
+        return sb;
+    }
 
-	/**
-	 * Reads the elevation value for the given coordinate.
-	 *
-	 * See also <a href="http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file">stackexchange.com</a>
-	 * @param coor the coordinate to get the elevation data for
-	 * @return the elevation value or <code>Double.NaN</code>, if no value is present
-	 */
-	public double readElevation(LatLon coor) {
-		String tag = getHgtFileName(coor);
+    /**
+     * Reads the elevation value for the given coordinate.
+     *
+     * See also <a href="http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file">stackexchange.com</a>
+     * @param coor the coordinate to get the elevation data for
+     * @return the elevation value or <code>Double.NaN</code>, if no value is present
+     */
+    public double readElevation(LatLon coor) {
+        String tag = getHgtFileName(coor);
 
-		ShortBuffer sb = cache.get(tag);
+        ShortBuffer sb = cache.get(tag);
 
-		if (sb == null) {
-			return ElevationHelper.NO_ELEVATION;
-		}
+        if (sb == null) {
+            return ElevationHelper.NO_ELEVATION;
+        }
 
-		// see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file
-		double fLat = frac(coor.lat()) * SECONDS_PER_MINUTE;
-		double fLon = frac(coor.lon()) * SECONDS_PER_MINUTE;
+        // see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file
+        double fLat = frac(coor.lat()) * SECONDS_PER_MINUTE;
+        double fLon = frac(coor.lon()) * SECONDS_PER_MINUTE;
 
-		// compute offset within HGT file
-		int row = (int)Math.round(fLat * SECONDS_PER_MINUTE / HGT_RES);
-		int col = (int)Math.round(fLon * SECONDS_PER_MINUTE / HGT_RES);
+        // compute offset within HGT file
+        int row = (int)Math.round(fLat * SECONDS_PER_MINUTE / HGT_RES);
+        int col = (int)Math.round(fLon * SECONDS_PER_MINUTE / HGT_RES);
 
-		row = HGT_ROW_LENGTH - row;
-		int cell = (HGT_ROW_LENGTH*  (row - 1)) + col;
+        row = HGT_ROW_LENGTH - row;
+        int cell = (HGT_ROW_LENGTH*  (row - 1)) + col;
 
-		//System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit());
+        //System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit());
 
-		// valid position in buffer?
-		if (cell < sb.limit()) {
-			short ele = sb.get(cell);
-			//System.out.println("==> Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + " = " + ele);
-			// check for data voids
-			if (ele == HGT_VOID) {
-				return ElevationHelper.NO_ELEVATION;
-			} else {
-				return ele;
-			}
-		} else {
-			return ElevationHelper.NO_ELEVATION;
-		}
-	}
+        // valid position in buffer?
+        if (cell < sb.limit()) {
+            short ele = sb.get(cell);
+            //System.out.println("==> Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + " = " + ele);
+            // check for data voids
+            if (ele == HGT_VOID) {
+                return ElevationHelper.NO_ELEVATION;
+            } else {
+                return ele;
+            }
+        } else {
+            return ElevationHelper.NO_ELEVATION;
+        }
+    }
 
-	/**
-	 * Gets the associated HGT file name for the given way point. Usually the
-	 * format is <tt>[N|S]nn[W|E]mmm.hgt</tt> where <i>nn</i> is the integral latitude
-	 * without decimals and <i>mmm</i> is the longitude.
-	 *
-	 * @param latLon the coordinate to get the filename for
-	 * @return the file name of the HGT file
-	 */
-	public String getHgtFileName(LatLon latLon) {
-		int lat = (int) latLon.lat();
-		int lon = (int) latLon.lon();
+    /**
+     * Gets the associated HGT file name for the given way point. Usually the
+     * format is <tt>[N|S]nn[W|E]mmm.hgt</tt> where <i>nn</i> is the integral latitude
+     * without decimals and <i>mmm</i> is the longitude.
+     *
+     * @param latLon the coordinate to get the filename for
+     * @return the file name of the HGT file
+     */
+    public String getHgtFileName(LatLon latLon) {
+        int lat = (int) latLon.lat();
+        int lon = (int) latLon.lon();
 
-		String latPref = "N";
-		if (lat < 0) latPref = "S";
+        String latPref = "N";
+        if (lat < 0) latPref = "S";
 
-		String lonPref = "E";
-		if (lon < 0) {
-			lonPref = "W";
-		}
+        String lonPref = "E";
+        if (lon < 0) {
+            lonPref = "W";
+        }
 
-		return String.format("%s%02d%s%03d%s", latPref, lat, lonPref, lon, HGT_EXT);
-	}
+        return String.format("%s%02d%s%03d%s", latPref, lat, lonPref, lon, HGT_EXT);
+    }
 
-	public static double frac(double d) {
-		long iPart;
-		double fPart;
+    public static double frac(double d) {
+        long iPart;
+        double fPart;
 
-		// Get user input
-		iPart = (long) d;
-		fPart = d - iPart;
-		return fPart;
-	}
+        // Get user input
+        iPart = (long) d;
+        fPart = d - iPart;
+        return fPart;
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 32315)
@@ -13,20 +13,20 @@
 public class AddElevationLayerAction extends JosmAction {
 
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = -745642875640041385L;
-	private Layer currentLayer;
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -745642875640041385L;
+    private Layer currentLayer;
 
-	public AddElevationLayerAction() {
-		super(tr("Elevation Grid Layer (experimental!)"), "elevation", tr("Shows elevation grid layer"), null, true);
-	}
+    public AddElevationLayerAction() {
+        super(tr("Elevation Grid Layer (experimental!)"), "elevation", tr("Shows elevation grid layer"), null, true);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		if (currentLayer == null) {
-			currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name
-			Main.main.addLayer(currentLayer);
-		}
-	}
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        if (currentLayer == null) {
+            currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name
+            Main.main.addLayer(currentLayer);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java	(revision 32315)
@@ -24,222 +24,222 @@
  */
 public class ElevationModel implements IGpxVisitor, IElevationModel {
-	// private int sliceSize;
-	private int trackCounter;
-	private final GpxData gpxData;
-	private final String name;
-	private final WayPointMap profiles = new WayPointMap();
-	private final List<IElevationModelListener> listeners = new ArrayList<>();
-	private final List<WayPoint> buffer = new ArrayList<>();
-	private int currentProfileIndex = 0;
-	private ElevationProfile curProfile = null;
-
-	/**
-	 * Instantiates a new elevation model.
-	 */
-	public ElevationModel() {
-		this("", null);
-	}
-
-	/**
-	 * Instantiates a new elevation model.
-	 *
-	 * @param name the name of the model
-	 * @param data the GPX data
-	 */
-	public ElevationModel(String name, GpxData data) {
-		gpxData = data;
-		this.name = name;
-		GpxIterator.visit(data, this);
-	}
-
-	/**
-	 * Gets the GPX data instance used by this model.
-	 *
-	 * @return
-	 */
-	public GpxData getGpxData() {
-		return gpxData;
-	}
-
-	/**
-	 * @return the tracks
-	 */
-	protected WayPointMap getTracks() {
-		return profiles;
-	}
-
-	/**
-	 * Fires the 'model changed' event to all listeners.
-	 */
-	protected void fireModelChanged() {
-		for (IElevationModelListener listener : listeners) {
-			if (profiles != null && profiles.size() > 0)
-				listener.elevationProfileChanged(getCurrentProfile());
-		}
-	}
-
-	@Override
-	public void addModelListener(IElevationModelListener listener) {
-		this.listeners.add(listener);
-	}
-
-	@Override
-	public void removeModelListener(IElevationModelListener listener) {
-		this.listeners.remove(listener);
-	}
-
-	@Override
-	public void removeAllListeners() {
-		this.listeners.clear();
-	}
-
-	@Override
-	public List<IElevationProfile> getProfiles() {
-		return profiles;
-	}
-
-	@Override
-	public IElevationProfile getCurrentProfile() {
-		if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null;
-
-		return profiles.get(currentProfileIndex);
-	}
-
-	@Override
-	public void setCurrentProfile(IElevationProfile newProfile) {
-		CheckParameterUtil.ensureParameterNotNull(newProfile);
-
-		if (!profiles.contains(newProfile)) {
-			profiles.add(newProfile);
-		}
-
-		setCurrentProfile(profiles.indexOf(newProfile));
-	}
-
-	@Override
-	public void setCurrentProfile(int index) {
-		if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount());
-
-		currentProfileIndex = index;
-		fireModelChanged();
-	}
-
-	@Override
-	public int profileCount() {
-		return profiles != null ? profiles.size() : 0;
-	}
-
-	// Visitor stuff starts here...
-
-	@Override
-	public void beginWayPoints() {
-		// we ignore single way points (elevation profile is quite meaningless...)
-	}
-
-	@Override
-	public void endWayPoints() {
-		// we ignore single way points (elevation profile is quite meaningless...)
-	}
-
-	@Override
-	public void visitWayPoint(WayPoint wp) {
-		// we ignore single way points (elevation profile is quite meaningless...)
-	}
-
-
-	@Override
-	public void beginTrack(GpxTrack track) {
-		createProfile(track);
-	}
-
-	@Override
-	public void endTrack(GpxTrack track) {
-		if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
-
-		curProfile.setDistance(track.length());
-		commitProfile();
-	}
-
-	@Override
-	public void beginTrackSegment(GpxTrack track, GpxTrackSegment segment) {
-		// Nothing to do here for now
-	}
-
-	@Override
-	public void endTrackSegment(GpxTrack track, GpxTrackSegment segment) {
-		// Nothing to do here for now
-	}
-
-	@Override
-	public void visitTrackPoint(WayPoint wp, GpxTrack track,
-			GpxTrackSegment segment) {
-
-		processWayPoint(wp);
-	}
-
-	@Override
-	public void beginRoute(GpxRoute route) {
-		createProfile(route);
-	}
-
-	@Override
-	public void endRoute(GpxRoute route) {
-		if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
-		// a GpxRoute has no 'length' property
-		curProfile.setDistance(0);
-		commitProfile();
-	}
-
-	@Override
-	public void visitRoutePoint(WayPoint wp, GpxRoute route) {
-		processWayPoint(wp);
-	}
-
-	/**
-	 * Creates a new profile.
-	 *
-	 * @param trackOrRoute the track or route
-	 */
-	private void createProfile(IWithAttributes trackOrRoute) {
-		// check GPX data
-		String trackName = (String) trackOrRoute.get("name");
-
-		if (trackName == null) {
-			trackName = (String) trackOrRoute.get(GpxData.META_NAME);
-			if (trackName == null) {
-				// no name given, build artificial one
-				trackName = name + "." + trackCounter;
-			}
-		}
-
-		curProfile = new ElevationProfile(trackName);
-	}
-
-	/**
-	 * Adds a track or route to the internal track list.
-	 *
-	 * @param trackName the track name
-	 */
-	private void commitProfile() {
-		if (buffer.size() > 0) {
-			// assign way points to profile...
-			curProfile.setWayPoints(buffer);
-			// ... and add to profile list
-			profiles.add(curProfile);
-			buffer.clear();
-		}
-	}
-
-	/**
-	 * Adds the given way point to the current buffer.
-	 *
-	 * @param wp the wp
-	 */
-	private void processWayPoint(WayPoint wp) {
-		if (wp == null) {
-			throw new RuntimeException("WPT must not be null!");
-		}
-
-		buffer.add(wp);
-	}
+    // private int sliceSize;
+    private int trackCounter;
+    private final GpxData gpxData;
+    private final String name;
+    private final WayPointMap profiles = new WayPointMap();
+    private final List<IElevationModelListener> listeners = new ArrayList<>();
+    private final List<WayPoint> buffer = new ArrayList<>();
+    private int currentProfileIndex = 0;
+    private ElevationProfile curProfile = null;
+
+    /**
+     * Instantiates a new elevation model.
+     */
+    public ElevationModel() {
+        this("", null);
+    }
+
+    /**
+     * Instantiates a new elevation model.
+     *
+     * @param name the name of the model
+     * @param data the GPX data
+     */
+    public ElevationModel(String name, GpxData data) {
+        gpxData = data;
+        this.name = name;
+        GpxIterator.visit(data, this);
+    }
+
+    /**
+     * Gets the GPX data instance used by this model.
+     *
+     * @return
+     */
+    public GpxData getGpxData() {
+        return gpxData;
+    }
+
+    /**
+     * @return the tracks
+     */
+    protected WayPointMap getTracks() {
+        return profiles;
+    }
+
+    /**
+     * Fires the 'model changed' event to all listeners.
+     */
+    protected void fireModelChanged() {
+        for (IElevationModelListener listener : listeners) {
+            if (profiles != null && profiles.size() > 0)
+                listener.elevationProfileChanged(getCurrentProfile());
+        }
+    }
+
+    @Override
+    public void addModelListener(IElevationModelListener listener) {
+        this.listeners.add(listener);
+    }
+
+    @Override
+    public void removeModelListener(IElevationModelListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    @Override
+    public void removeAllListeners() {
+        this.listeners.clear();
+    }
+
+    @Override
+    public List<IElevationProfile> getProfiles() {
+        return profiles;
+    }
+
+    @Override
+    public IElevationProfile getCurrentProfile() {
+        if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null;
+
+        return profiles.get(currentProfileIndex);
+    }
+
+    @Override
+    public void setCurrentProfile(IElevationProfile newProfile) {
+        CheckParameterUtil.ensureParameterNotNull(newProfile);
+
+        if (!profiles.contains(newProfile)) {
+            profiles.add(newProfile);
+        }
+
+        setCurrentProfile(profiles.indexOf(newProfile));
+    }
+
+    @Override
+    public void setCurrentProfile(int index) {
+        if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount());
+
+        currentProfileIndex = index;
+        fireModelChanged();
+    }
+
+    @Override
+    public int profileCount() {
+        return profiles != null ? profiles.size() : 0;
+    }
+
+    // Visitor stuff starts here...
+
+    @Override
+    public void beginWayPoints() {
+        // we ignore single way points (elevation profile is quite meaningless...)
+    }
+
+    @Override
+    public void endWayPoints() {
+        // we ignore single way points (elevation profile is quite meaningless...)
+    }
+
+    @Override
+    public void visitWayPoint(WayPoint wp) {
+        // we ignore single way points (elevation profile is quite meaningless...)
+    }
+
+
+    @Override
+    public void beginTrack(GpxTrack track) {
+        createProfile(track);
+    }
+
+    @Override
+    public void endTrack(GpxTrack track) {
+        if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
+
+        curProfile.setDistance(track.length());
+        commitProfile();
+    }
+
+    @Override
+    public void beginTrackSegment(GpxTrack track, GpxTrackSegment segment) {
+        // Nothing to do here for now
+    }
+
+    @Override
+    public void endTrackSegment(GpxTrack track, GpxTrackSegment segment) {
+        // Nothing to do here for now
+    }
+
+    @Override
+    public void visitTrackPoint(WayPoint wp, GpxTrack track,
+            GpxTrackSegment segment) {
+
+        processWayPoint(wp);
+    }
+
+    @Override
+    public void beginRoute(GpxRoute route) {
+        createProfile(route);
+    }
+
+    @Override
+    public void endRoute(GpxRoute route) {
+        if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
+        // a GpxRoute has no 'length' property
+        curProfile.setDistance(0);
+        commitProfile();
+    }
+
+    @Override
+    public void visitRoutePoint(WayPoint wp, GpxRoute route) {
+        processWayPoint(wp);
+    }
+
+    /**
+     * Creates a new profile.
+     *
+     * @param trackOrRoute the track or route
+     */
+    private void createProfile(IWithAttributes trackOrRoute) {
+        // check GPX data
+        String trackName = (String) trackOrRoute.get("name");
+
+        if (trackName == null) {
+            trackName = (String) trackOrRoute.get(GpxData.META_NAME);
+            if (trackName == null) {
+                // no name given, build artificial one
+                trackName = name + "." + trackCounter;
+            }
+        }
+
+        curProfile = new ElevationProfile(trackName);
+    }
+
+    /**
+     * Adds a track or route to the internal track list.
+     *
+     * @param trackName the track name
+     */
+    private void commitProfile() {
+        if (buffer.size() > 0) {
+            // assign way points to profile...
+            curProfile.setWayPoints(buffer);
+            // ... and add to profile list
+            profiles.add(curProfile);
+            buffer.clear();
+        }
+    }
+
+    /**
+     * Adds the given way point to the current buffer.
+     *
+     * @param wp the wp
+     */
+    private void processWayPoint(WayPoint wp) {
+        if (wp == null) {
+            throw new RuntimeException("WPT must not be null!");
+        }
+
+        buffer.add(wp);
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 32315)
@@ -34,403 +34,403 @@
 public class ElevationProfile implements IElevationProfile,
 IGpxWaypointVisitor {
-	public static final int WAYPOINT_START = 0;
-	public static final int WAYPOINT_END = 1;
-	public static final int WAYPOINT_MIN = 2;
-	public static final int WAYPOINT_MAX = 3;
-
-	private String name;
-	private int minHeight;
-	private int maxHeight;
-	private int avrgHeight;
-	private double dist;
-	private Date start = new Date();
-	private Date end = new Date();
-	private final WayPoint[] importantWayPoints = new WayPoint[4];
-	private IElevationProfile parent;
-	private int sumEle; // temp var for average height
-	private List<WayPoint> wayPoints;
-	private int numWayPoints; // cached value
-	private int gain;
-	private int lastEle;
-	private Bounds bounds;
-
-	private static boolean ignoreZeroHeight = true;
-
-	/**
-	 * Creates a name elevation profile without any way points.
-	 *
-	 * @param name
-	 */
-	public ElevationProfile(String name) {
-		this(name, null, null, 0);
-	}
-
-	/**
-	 * Creates a name elevation profile with a given set of way points.
-	 *
-	 * @param name
-	 *            The name of the profile.
-	 * @param parent
-	 *            The (optional) parent profile.
-	 * @param wayPoints
-	 *            The list containing the way points of the profile.
-	 * @param sliceSize
-	 *            The requested target size of the profile.
-	 */
-	public ElevationProfile(String name, IElevationProfile parent,
-			List<WayPoint> wayPoints, int sliceSize) {
-		super();
-		this.name = name;
-		this.parent = parent;
-
-		setWayPoints(wayPoints);
-	}
-
-	/**
-	 * Checks if zero elevation should be ignored or not.
-	 *
-	 * @return true, if is ignore zero height
-	 */
-	public static boolean isIgnoreZeroHeight() {
-		return ignoreZeroHeight;
-	}
-
-	/**
-	 * Sets the ignore zero height.
-	 *
-	 * @param ignoreZeroHeight the new ignore zero height
-	 */
-	public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) {
-		ElevationProfile.ignoreZeroHeight = ignoreZeroHeight;
-	}
-
-	@Override
-	public void updateElevationData() {
-		updateValues();
-	}
-
-	/**
-	 * Revisits all way points and recomputes the characteristic values like
-	 * min/max elevation.
-	 */
-	protected void updateValues() {
-		if (wayPoints == null)
-			return;
-
-		int n = this.wayPoints.size();
-		if (n == 0)
-			return;
-
-		start = new Date();
-		end = new Date(0L);
-		this.minHeight = Integer.MAX_VALUE;
-		this.maxHeight = Integer.MIN_VALUE;
-		sumEle = 0;
-		gain = 0;
-		lastEle = 0;
-
-		for (WayPoint wayPoint : this.wayPoints) {
-			visitWayPoint(wayPoint);
-		}
-
-		if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) {
-			// file does not contain elevation data    at all
-			minHeight = 0;
-			maxHeight = 0;
-			setMinWayPoint(wayPoints.get(0));
-			setMaxWayPoint(wayPoints.get(n-1));
-		}
-
-		//if (start.after(end) || start.equals(end)) {
-		// GPX does not contain time stamps -> use sequential order
-		setStart(wayPoints.get(0));
-		setEnd(wayPoints.get(n-1));
-		//}
-
-		avrgHeight = sumEle / n;
-	}
-
-	/**
-	 * Gets the name of the profile.
-	 */
-	@Override
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Sets the name of the profile.
-	 * @param name The new name of the profile.
-	 */
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * Sets the way point with the lowest elevation.
-	 * @param wp The way point instance having the lowest elevation.
-	 */
-	protected void setMinWayPoint(WayPoint wp) {
-		importantWayPoints[WAYPOINT_MIN] = wp;
-		this.minHeight = (int) ElevationHelper.getElevation(wp);
-	}
-
-	/**
-	 * Sets the way point with the highest elevation.
-	 * @param wp The way point instance having the highest elevation.
-	 */
-	protected void setMaxWayPoint(WayPoint wp) {
-		importantWayPoints[WAYPOINT_MAX] = wp;
-		this.maxHeight = (int) ElevationHelper.getElevation(wp);
-	}
-
-	/**
-	 * Sets the average height.
-	 * @param avrgHeight
-	 */
-	protected void setAvrgHeight(int avrgHeight) {
-		this.avrgHeight = avrgHeight;
-	}
-
-	/**
-	 * Sets the very first way point.
-	 * @param wp
-	 */
-	protected void setStart(WayPoint wp) {
-		importantWayPoints[WAYPOINT_START] = wp;
-		this.start = wp.getTime();
-	}
-
-	/**
-	 * Sets the very last way point.
-	 * @param wp
-	 */
-	protected void setEnd(WayPoint wp) {
-		importantWayPoints[WAYPOINT_END] = wp;
-		this.end = wp.getTime();
-	}
-
-	public void setParent(IElevationProfile parent) {
-		this.parent = parent;
-	}
-
-	/**
-	 * Sets the way points of this profile.
-	 *
-	 * @param wayPoints
-	 */
-	public void setWayPoints(List<WayPoint> wayPoints) {
-		if (this.wayPoints != wayPoints) {
-			this.wayPoints = new ArrayList<>(wayPoints);
-			numWayPoints = wayPoints != null ? wayPoints.size() : 0;
-			updateValues();
-
-		}
-	}
-
-	/**
-	 * Checks if the given index is valid or not.
-	 *
-	 * @param index
-	 *            The index to check.
-	 * @return true, if the given index is valid; otherwise false.
-	 */
-	protected boolean checkIndex(int index) {
-		return index >= 0 && index < getNumberOfWayPoints();
-	}
-
-	@Override
-	public int elevationValueAt(int i) {
-		if (checkIndex(i)) {
-			return (int) ElevationHelper.getElevation(wayPoints.get(i));
-		} else {
-			throw new IndexOutOfBoundsException(String.format(
-					"Invalid index: %d, expected 0..%d", i,
-					getNumberOfWayPoints()));
-		}
-	}
-
-	@Override
-	public int getAverageHeight() {
-		return avrgHeight;
-	}
-
-	@Override
-	public List<IElevationProfile> getChildren() {
-		return null;
-	}
-
-	@Override
-	public Date getEnd() {
-		return end;
-	}
-
-	@Override
-	public int getMaxHeight() {
-		return maxHeight;
-	}
-
-	@Override
-	public int getMinHeight() {
-		return minHeight;
-	}
-
-	/**
-	 * Gets the difference between min and max elevation.
-	 *
-	 * @return
-	 */
-	@Override
-	public int getHeightDifference() {
-		return maxHeight - minHeight;
-	}
-
-	/**
-	 * Gets the elevation gain.
-	 *
-	 * @return
-	 */
-	@Override
-	public int getGain() {
-		return gain;
-	}
-
-	@Override
-	public double getDistance() {
-		return dist; // dist is in meters
-	}
-
-	/**
-	 * Sets the distance of the elevation profile.
-	 * @param dist
-	 */
-	protected void setDistance(double dist) {
-		this.dist = dist;
-	}
-
-	/**
-	 * Returns the time between start and end of the track.
-	 * @return
-	 */
-	@Override
-	public long getTimeDifference() {
-		WayPoint wp1 = getStartWayPoint();
-		WayPoint wp2 = getEndWayPoint();
-
-		if (wp1 != null && wp2 != null) {
-			long diff = wp2.getTime().getTime() - wp1.getTime().getTime();
-			return diff;
-		}
-
-		return 0L;
-	}
-
-	@Override
-	public IElevationProfile getParent() {
-		return parent;
-	}
-
-	@Override
-	public Date getStart() {
-		return start;
-	}
-
-	@Override
-	public WayPoint getEndWayPoint() {
-		return importantWayPoints[WAYPOINT_END];
-	}
-
-	@Override
-	public WayPoint getMaxWayPoint() {
-		return importantWayPoints[WAYPOINT_MAX];
-	}
-
-	@Override
-	public WayPoint getMinWayPoint() {
-		return importantWayPoints[WAYPOINT_MIN];
-	}
-
-	@Override
-	public WayPoint getStartWayPoint() {
-		return importantWayPoints[WAYPOINT_START];
-	}
-
-	@Override
-	public List<WayPoint> getWayPoints() {
-		return wayPoints;
-	}
-
-	@Override
-	public int getNumberOfWayPoints() {
-		return numWayPoints;// wayPoints != null ? wayPoints.size() : 0;
-	}
-
-	/**
-	 * Gets the coordinate bounds of this profile. See {@link Bounds} for details.
-	 *
-	 * @return the bounds of this elevation profile
-	 */
-	@Override
-	public Bounds getBounds() {
-		return bounds;
-	}
-
-	/**
-	 * Gets a flag indicating whether the associated way points contained
-	 * elevation data or not. This is the case if min and max height or both
-	 * zero.
-	 *
-	 * @return
-	 */
-	@Override
-	public boolean hasElevationData() {
-		return minHeight != maxHeight;
-	}
-
-	/**
-	 * Visits a way point in order to update statistical values about the given
-	 * way point list.
-	 */
-	@Override
-	public void visitWayPoint(WayPoint wp) {
-		if (wp.getTime().after(end)) {
-			setEnd(wp);
-		}
-
-		if (wp.getTime().before(start)) {
-			setStart(wp);
-		}
-
-		// update boundaries
-		if (bounds == null) {
-			bounds = new Bounds(wp.getCoor());
-		} else {
-			bounds.extend(wp.getCoor());
-		}
-
-		int ele = (int) ElevationHelper.getElevation(wp);
-
-		if (!isIgnoreZeroHeight() || ele > 0) {
-			if (ele > maxHeight) {
-				setMaxWayPoint(wp);
-			}
-			if (ele < minHeight) {
-				setMinWayPoint(wp);
-			}
-
-			if (ele > lastEle) {
-				gain += ele - lastEle;
-			}
-
-			sumEle += ele;
-			lastEle = ele;
-		}
-	}
-
-	@Override
-	public String toString() {
-		return name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
+    public static final int WAYPOINT_START = 0;
+    public static final int WAYPOINT_END = 1;
+    public static final int WAYPOINT_MIN = 2;
+    public static final int WAYPOINT_MAX = 3;
+
+    private String name;
+    private int minHeight;
+    private int maxHeight;
+    private int avrgHeight;
+    private double dist;
+    private Date start = new Date();
+    private Date end = new Date();
+    private final WayPoint[] importantWayPoints = new WayPoint[4];
+    private IElevationProfile parent;
+    private int sumEle; // temp var for average height
+    private List<WayPoint> wayPoints;
+    private int numWayPoints; // cached value
+    private int gain;
+    private int lastEle;
+    private Bounds bounds;
+
+    private static boolean ignoreZeroHeight = true;
+
+    /**
+     * Creates a name elevation profile without any way points.
+     *
+     * @param name
+     */
+    public ElevationProfile(String name) {
+        this(name, null, null, 0);
+    }
+
+    /**
+     * Creates a name elevation profile with a given set of way points.
+     *
+     * @param name
+     *            The name of the profile.
+     * @param parent
+     *            The (optional) parent profile.
+     * @param wayPoints
+     *            The list containing the way points of the profile.
+     * @param sliceSize
+     *            The requested target size of the profile.
+     */
+    public ElevationProfile(String name, IElevationProfile parent,
+            List<WayPoint> wayPoints, int sliceSize) {
+        super();
+        this.name = name;
+        this.parent = parent;
+
+        setWayPoints(wayPoints);
+    }
+
+    /**
+     * Checks if zero elevation should be ignored or not.
+     *
+     * @return true, if is ignore zero height
+     */
+    public static boolean isIgnoreZeroHeight() {
+        return ignoreZeroHeight;
+    }
+
+    /**
+     * Sets the ignore zero height.
+     *
+     * @param ignoreZeroHeight the new ignore zero height
+     */
+    public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) {
+        ElevationProfile.ignoreZeroHeight = ignoreZeroHeight;
+    }
+
+    @Override
+    public void updateElevationData() {
+        updateValues();
+    }
+
+    /**
+     * Revisits all way points and recomputes the characteristic values like
+     * min/max elevation.
+     */
+    protected void updateValues() {
+        if (wayPoints == null)
+            return;
+
+        int n = this.wayPoints.size();
+        if (n == 0)
+            return;
+
+        start = new Date();
+        end = new Date(0L);
+        this.minHeight = Integer.MAX_VALUE;
+        this.maxHeight = Integer.MIN_VALUE;
+        sumEle = 0;
+        gain = 0;
+        lastEle = 0;
+
+        for (WayPoint wayPoint : this.wayPoints) {
+            visitWayPoint(wayPoint);
+        }
+
+        if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) {
+            // file does not contain elevation data    at all
+            minHeight = 0;
+            maxHeight = 0;
+            setMinWayPoint(wayPoints.get(0));
+            setMaxWayPoint(wayPoints.get(n-1));
+        }
+
+        //if (start.after(end) || start.equals(end)) {
+        // GPX does not contain time stamps -> use sequential order
+        setStart(wayPoints.get(0));
+        setEnd(wayPoints.get(n-1));
+        //}
+
+        avrgHeight = sumEle / n;
+    }
+
+    /**
+     * Gets the name of the profile.
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of the profile.
+     * @param name The new name of the profile.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Sets the way point with the lowest elevation.
+     * @param wp The way point instance having the lowest elevation.
+     */
+    protected void setMinWayPoint(WayPoint wp) {
+        importantWayPoints[WAYPOINT_MIN] = wp;
+        this.minHeight = (int) ElevationHelper.getElevation(wp);
+    }
+
+    /**
+     * Sets the way point with the highest elevation.
+     * @param wp The way point instance having the highest elevation.
+     */
+    protected void setMaxWayPoint(WayPoint wp) {
+        importantWayPoints[WAYPOINT_MAX] = wp;
+        this.maxHeight = (int) ElevationHelper.getElevation(wp);
+    }
+
+    /**
+     * Sets the average height.
+     * @param avrgHeight
+     */
+    protected void setAvrgHeight(int avrgHeight) {
+        this.avrgHeight = avrgHeight;
+    }
+
+    /**
+     * Sets the very first way point.
+     * @param wp
+     */
+    protected void setStart(WayPoint wp) {
+        importantWayPoints[WAYPOINT_START] = wp;
+        this.start = wp.getTime();
+    }
+
+    /**
+     * Sets the very last way point.
+     * @param wp
+     */
+    protected void setEnd(WayPoint wp) {
+        importantWayPoints[WAYPOINT_END] = wp;
+        this.end = wp.getTime();
+    }
+
+    public void setParent(IElevationProfile parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Sets the way points of this profile.
+     *
+     * @param wayPoints
+     */
+    public void setWayPoints(List<WayPoint> wayPoints) {
+        if (this.wayPoints != wayPoints) {
+            this.wayPoints = new ArrayList<>(wayPoints);
+            numWayPoints = wayPoints != null ? wayPoints.size() : 0;
+            updateValues();
+
+        }
+    }
+
+    /**
+     * Checks if the given index is valid or not.
+     *
+     * @param index
+     *            The index to check.
+     * @return true, if the given index is valid; otherwise false.
+     */
+    protected boolean checkIndex(int index) {
+        return index >= 0 && index < getNumberOfWayPoints();
+    }
+
+    @Override
+    public int elevationValueAt(int i) {
+        if (checkIndex(i)) {
+            return (int) ElevationHelper.getElevation(wayPoints.get(i));
+        } else {
+            throw new IndexOutOfBoundsException(String.format(
+                    "Invalid index: %d, expected 0..%d", i,
+                    getNumberOfWayPoints()));
+        }
+    }
+
+    @Override
+    public int getAverageHeight() {
+        return avrgHeight;
+    }
+
+    @Override
+    public List<IElevationProfile> getChildren() {
+        return null;
+    }
+
+    @Override
+    public Date getEnd() {
+        return end;
+    }
+
+    @Override
+    public int getMaxHeight() {
+        return maxHeight;
+    }
+
+    @Override
+    public int getMinHeight() {
+        return minHeight;
+    }
+
+    /**
+     * Gets the difference between min and max elevation.
+     *
+     * @return
+     */
+    @Override
+    public int getHeightDifference() {
+        return maxHeight - minHeight;
+    }
+
+    /**
+     * Gets the elevation gain.
+     *
+     * @return
+     */
+    @Override
+    public int getGain() {
+        return gain;
+    }
+
+    @Override
+    public double getDistance() {
+        return dist; // dist is in meters
+    }
+
+    /**
+     * Sets the distance of the elevation profile.
+     * @param dist
+     */
+    protected void setDistance(double dist) {
+        this.dist = dist;
+    }
+
+    /**
+     * Returns the time between start and end of the track.
+     * @return
+     */
+    @Override
+    public long getTimeDifference() {
+        WayPoint wp1 = getStartWayPoint();
+        WayPoint wp2 = getEndWayPoint();
+
+        if (wp1 != null && wp2 != null) {
+            long diff = wp2.getTime().getTime() - wp1.getTime().getTime();
+            return diff;
+        }
+
+        return 0L;
+    }
+
+    @Override
+    public IElevationProfile getParent() {
+        return parent;
+    }
+
+    @Override
+    public Date getStart() {
+        return start;
+    }
+
+    @Override
+    public WayPoint getEndWayPoint() {
+        return importantWayPoints[WAYPOINT_END];
+    }
+
+    @Override
+    public WayPoint getMaxWayPoint() {
+        return importantWayPoints[WAYPOINT_MAX];
+    }
+
+    @Override
+    public WayPoint getMinWayPoint() {
+        return importantWayPoints[WAYPOINT_MIN];
+    }
+
+    @Override
+    public WayPoint getStartWayPoint() {
+        return importantWayPoints[WAYPOINT_START];
+    }
+
+    @Override
+    public List<WayPoint> getWayPoints() {
+        return wayPoints;
+    }
+
+    @Override
+    public int getNumberOfWayPoints() {
+        return numWayPoints;// wayPoints != null ? wayPoints.size() : 0;
+    }
+
+    /**
+     * Gets the coordinate bounds of this profile. See {@link Bounds} for details.
+     *
+     * @return the bounds of this elevation profile
+     */
+    @Override
+    public Bounds getBounds() {
+        return bounds;
+    }
+
+    /**
+     * Gets a flag indicating whether the associated way points contained
+     * elevation data or not. This is the case if min and max height or both
+     * zero.
+     *
+     * @return
+     */
+    @Override
+    public boolean hasElevationData() {
+        return minHeight != maxHeight;
+    }
+
+    /**
+     * Visits a way point in order to update statistical values about the given
+     * way point list.
+     */
+    @Override
+    public void visitWayPoint(WayPoint wp) {
+        if (wp.getTime().after(end)) {
+            setEnd(wp);
+        }
+
+        if (wp.getTime().before(start)) {
+            setStart(wp);
+        }
+
+        // update boundaries
+        if (bounds == null) {
+            bounds = new Bounds(wp.getCoor());
+        } else {
+            bounds.extend(wp.getCoor());
+        }
+
+        int ele = (int) ElevationHelper.getElevation(wp);
+
+        if (!isIgnoreZeroHeight() || ele > 0) {
+            if (ele > maxHeight) {
+                setMaxWayPoint(wp);
+            }
+            if (ele < minHeight) {
+                setMinWayPoint(wp);
+            }
+
+            if (ele > lastEle) {
+                gain += ele - lastEle;
+            }
+
+            sumEle += ele;
+            lastEle = ele;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
                 + ", minHeight=" + getMinHeight() + ", maxHeight="
                 + getMaxHeight() + "]";*/
-	}
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/EleVertex.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/EleVertex.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/EleVertex.java	(revision 32315)
@@ -10,59 +10,59 @@
 
 public class EleVertex {
-	private static final int NPOINTS = 3;
-	private static final double MIN_DIST = 90;
-
-	private double avrgEle = Double.NaN;
-	private double area = Double.NaN;
-	private final EleCoordinate[] points = new EleCoordinate[NPOINTS];
-
-	public EleVertex(EleCoordinate p1, EleCoordinate p2, EleCoordinate p3) {
-		points[0] = p1;
-		points[1] = p2;
-		points[2] = p3;
-
-		// compute elevation
-		double z = 0D;
-		boolean eleValid = true;
-		for (EleCoordinate point : points) {
-			if (ElevationHelper.isValidElevation(p1.getEle())) {
-				z += point.getEle();
-			} else {
-				eleValid = false;
-				break;
-			}
-		}
-
-		if (eleValid) {
-			avrgEle = z / NPOINTS;
-		} else {
-			avrgEle = ElevationHelper.NO_ELEVATION;
-		}
-
-		// compute the (approx.!) area of the vertex using heron's formula
-		double a = p1.greatCircleDistance(p2);
-		double b = p2.greatCircleDistance(p3);
-		double c = p1.greatCircleDistance(p3);
-
-		double s = (a + b + c) / 2D;
-		double sq = s * (s - a) * (s - b) * (s - c);
-		area = Math.sqrt(sq);
-	}
-
-	public List<EleVertex> divide() {
-		TriangleEdge[] edges = new TriangleEdge[NPOINTS];
-
-		int k = 0;
-		for (int i = 0; i < points.length; i++) {
-			EleCoordinate c1 = points[i];
-
-			for (int j = i + 1; j < points.length; j++) {
-				EleCoordinate c2 = points[j];
-
-				edges[k++] = new TriangleEdge(i, j, c1.greatCircleDistance(c2));
-			}
-		}
-
-		/*
+    private static final int NPOINTS = 3;
+    private static final double MIN_DIST = 90;
+
+    private double avrgEle = Double.NaN;
+    private double area = Double.NaN;
+    private final EleCoordinate[] points = new EleCoordinate[NPOINTS];
+
+    public EleVertex(EleCoordinate p1, EleCoordinate p2, EleCoordinate p3) {
+        points[0] = p1;
+        points[1] = p2;
+        points[2] = p3;
+
+        // compute elevation
+        double z = 0D;
+        boolean eleValid = true;
+        for (EleCoordinate point : points) {
+            if (ElevationHelper.isValidElevation(p1.getEle())) {
+                z += point.getEle();
+            } else {
+                eleValid = false;
+                break;
+            }
+        }
+
+        if (eleValid) {
+            avrgEle = z / NPOINTS;
+        } else {
+            avrgEle = ElevationHelper.NO_ELEVATION;
+        }
+
+        // compute the (approx.!) area of the vertex using heron's formula
+        double a = p1.greatCircleDistance(p2);
+        double b = p2.greatCircleDistance(p3);
+        double c = p1.greatCircleDistance(p3);
+
+        double s = (a + b + c) / 2D;
+        double sq = s * (s - a) * (s - b) * (s - c);
+        area = Math.sqrt(sq);
+    }
+
+    public List<EleVertex> divide() {
+        TriangleEdge[] edges = new TriangleEdge[NPOINTS];
+
+        int k = 0;
+        for (int i = 0; i < points.length; i++) {
+            EleCoordinate c1 = points[i];
+
+            for (int j = i + 1; j < points.length; j++) {
+                EleCoordinate c2 = points[j];
+
+                edges[k++] = new TriangleEdge(i, j, c1.greatCircleDistance(c2));
+            }
+        }
+
+        /*
     for (int i = 0; i < edges.length; i++) {
         TriangleEdge triangleEdge = edges[i];
@@ -70,36 +70,36 @@
     }*/
 
-		// sort by distance
-		Arrays.sort(edges);
-		// pick the longest edge
-		TriangleEdge longest = edges[0];
-
-
-		//System.out.println("Longest " + longest);
-		EleCoordinate pI = points[longest.getI()];
-		EleCoordinate pJ = points[longest.getJ()];
-		EleCoordinate pK = points[longest.getK()];
-		EleCoordinate newP = getMid(pI, pJ);
-		/*
+        // sort by distance
+        Arrays.sort(edges);
+        // pick the longest edge
+        TriangleEdge longest = edges[0];
+
+
+        //System.out.println("Longest " + longest);
+        EleCoordinate pI = points[longest.getI()];
+        EleCoordinate pJ = points[longest.getJ()];
+        EleCoordinate pK = points[longest.getK()];
+        EleCoordinate newP = getMid(pI, pJ);
+        /*
     System.out.println(pI);
     System.out.println(pJ);
     System.out.println(pK);
     System.out.println(newP);
-		 */
-		List<EleVertex> res = new ArrayList<>();
-		res.add(new EleVertex(pI, pK, newP));
-		res.add(new EleVertex(pJ, pK, newP));
-
-		return res;
-	}
-
-	/**
-	 * Checks if vertex requires further processing or is finished. Currently this
-	 * method returns <code>true</code>, if the average deviation is < 5m
-	 *
-	 * @return true, if is finished
-	 */
-	public boolean isFinished() {
-		/*double z = 0D;
+         */
+        List<EleVertex> res = new ArrayList<>();
+        res.add(new EleVertex(pI, pK, newP));
+        res.add(new EleVertex(pJ, pK, newP));
+
+        return res;
+    }
+
+    /**
+     * Checks if vertex requires further processing or is finished. Currently this
+     * method returns <code>true</code>, if the average deviation is < 5m
+     *
+     * @return true, if is finished
+     */
+    public boolean isFinished() {
+        /*double z = 0D;
         double avrgEle = getEle();
 
@@ -108,115 +108,115 @@
         }*/
 
-		// TODO: Check for proper limit
-		return /*z < 75 || */getArea() < (30 * 30); // = 3 * 25
-	}
-
-	/**
-	 * Gets the approximate area of this vertex in square meters.
-	 *
-	 * @return the area
-	 */
-	public double getArea() {
-		return area;
-	}
-
-	/**
-	 * Gets the (linear interpolated) mid point of c1 and c2.
-	 *
-	 * @param c1 the first coordinate
-	 * @param c2 the second coordinate
-	 * @return the mid point
-	 */
-	public EleCoordinate getMid(EleCoordinate c1, EleCoordinate c2) {
-		double x = (c1.getX() + c2.getX()) / 2.0;
-		double y = (c1.getY() + c2.getY()) / 2.0;
-
-		double z = (c1.getEle() + c2.getEle()) / 2.0;
-		if (c1.greatCircleDistance(c2) > MIN_DIST) {
-			double hgtZ = ElevationHelper.getSrtmElevation(new LatLon(y, x));
-
-			if (ElevationHelper.isValidElevation(hgtZ)) {
-				z = hgtZ;
-			}
-		}
-
-		return new EleCoordinate(y, x, z);
-	}
-
-	/**
-	 * Gets the coordinate for the given index.
-	 *
-	 * @param index the index between 0 and NPOINTS:
-	 * @return the elevation coordinate instance
-	 * @throws IllegalArgumentException, if index is invalid
-	 */
-	public EleCoordinate get(int index) {
-		if (index < 0 || index >= NPOINTS) throw new IllegalArgumentException("Invalid index: " + index);
-
-		return points[index];
-	}
-
-	/**
-	 * Gets the average elevation of this vertex.
-	 *
-	 * @return the ele
-	 */
-	public double getEle() {
-
-		return avrgEle;
-	}
-
-	@Override
-	public String toString() {
-		return "EleVertex [avrgEle=" + avrgEle + ", area=" + area + ", points="
-				+ Arrays.toString(points) + "]";
-	}
-
-
-
-
-	class TriangleEdge implements Comparable<TriangleEdge> {
-		private final int i;
-		private final int j;
-		private final double dist;
-
-		public TriangleEdge(int i, int j, double dist) {
-			super();
-			this.i = i;
-			this.j = j;
-			this.dist = dist;
-		}
-
-		public int getI() {
-			return i;
-		}
-
-		public int getJ() {
-			return j;
-		}
-
-		public int getK() {
-			if (i == 0) {
-				return j == 1 ? 2 : 1;
-			} else if (i == 1) {
-				return j == 0 ? 2 : 0;
-			} else {
-				return j == 0 ? 1 : 0;
-			}
-		}
-
-		public double getDist() {
-			return dist;
-		}
-
-		@Override
-		public int compareTo(TriangleEdge o) {
-			return (int) (o.getDist() - dist);
-		}
-
-		@Override
-		public String toString() {
-			return "TriangleEdge [i=" + i + ", j=" + j + ", dist=" + dist + "]";
-		}
-	}
+        // TODO: Check for proper limit
+        return /*z < 75 || */getArea() < (30 * 30); // = 3 * 25
+    }
+
+    /**
+     * Gets the approximate area of this vertex in square meters.
+     *
+     * @return the area
+     */
+    public double getArea() {
+        return area;
+    }
+
+    /**
+     * Gets the (linear interpolated) mid point of c1 and c2.
+     *
+     * @param c1 the first coordinate
+     * @param c2 the second coordinate
+     * @return the mid point
+     */
+    public EleCoordinate getMid(EleCoordinate c1, EleCoordinate c2) {
+        double x = (c1.getX() + c2.getX()) / 2.0;
+        double y = (c1.getY() + c2.getY()) / 2.0;
+
+        double z = (c1.getEle() + c2.getEle()) / 2.0;
+        if (c1.greatCircleDistance(c2) > MIN_DIST) {
+            double hgtZ = ElevationHelper.getSrtmElevation(new LatLon(y, x));
+
+            if (ElevationHelper.isValidElevation(hgtZ)) {
+                z = hgtZ;
+            }
+        }
+
+        return new EleCoordinate(y, x, z);
+    }
+
+    /**
+     * Gets the coordinate for the given index.
+     *
+     * @param index the index between 0 and NPOINTS:
+     * @return the elevation coordinate instance
+     * @throws IllegalArgumentException, if index is invalid
+     */
+    public EleCoordinate get(int index) {
+        if (index < 0 || index >= NPOINTS) throw new IllegalArgumentException("Invalid index: " + index);
+
+        return points[index];
+    }
+
+    /**
+     * Gets the average elevation of this vertex.
+     *
+     * @return the ele
+     */
+    public double getEle() {
+
+        return avrgEle;
+    }
+
+    @Override
+    public String toString() {
+        return "EleVertex [avrgEle=" + avrgEle + ", area=" + area + ", points="
+                + Arrays.toString(points) + "]";
+    }
+
+
+
+
+    class TriangleEdge implements Comparable<TriangleEdge> {
+        private final int i;
+        private final int j;
+        private final double dist;
+
+        public TriangleEdge(int i, int j, double dist) {
+            super();
+            this.i = i;
+            this.j = j;
+            this.dist = dist;
+        }
+
+        public int getI() {
+            return i;
+        }
+
+        public int getJ() {
+            return j;
+        }
+
+        public int getK() {
+            if (i == 0) {
+                return j == 1 ? 2 : 1;
+            } else if (i == 1) {
+                return j == 0 ? 2 : 0;
+            } else {
+                return j == 0 ? 1 : 0;
+            }
+        }
+
+        public double getDist() {
+            return dist;
+        }
+
+        @Override
+        public int compareTo(TriangleEdge o) {
+            return (int) (o.getDist() - dist);
+        }
+
+        @Override
+        public String toString() {
+            return "TriangleEdge [i=" + i + ", j=" + j + ", dist=" + dist + "]";
+        }
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java	(revision 32315)
@@ -32,201 +32,201 @@
  */
 public class ElevationGridLayer extends Layer implements TileLoaderListener {
-	private static final int ELE_ZOOM_LEVEL = 13;
-	private final IVertexRenderer vertexRenderer;
-	private final MemoryTileCache tileCache;
-	protected TileSource tileSource;
-	protected ElevationGridTileLoader tileLoader;
-	protected TileController tileController;
-
-	private Bounds lastBounds;
-	private TileSet tileSet;
-
-	/**
-	 * @param info
-	 */
-	public ElevationGridLayer(String name) {
-		super(name);
-
-		setOpacity(0.8);
-		setBackgroundLayer(true);
-		vertexRenderer = new SimpleVertexRenderer();
-
-		tileCache = new MemoryTileCache();
-		tileCache.setCacheSize(500);
-		tileSource = new ElevationGridTileSource(name);
-		tileLoader = new ElevationGridTileLoader(this);
-		tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader);
-	}
-
-	@Override
-	public void paint(Graphics2D g, MapView mv, Bounds box) {
-		boolean needsNewTileSet = tileSet == null || (lastBounds == null || !lastBounds.equals(box));
-
-		if (needsNewTileSet) {
-			tileSet = new TileSet(box.getMin(), box.getMax(), ELE_ZOOM_LEVEL); // we use a vector format with constant zoom level
-			lastBounds = box;
-			System.out.println("paint " + tileSet);
-		}
-
-		if (tileSet.insane()) {
-			myDrawString(g, tr("zoom in to load any tiles"), 120, 120);
-			return;
-		} else if (tileSet.tooLarge()) {
-			myDrawString(g, tr("zoom in to load more tiles"), 120, 120);
-			return;
-		} else if (tileSet.tooSmall()) {
-			myDrawString(g, tr("increase zoom level to see more detail"), 120, 120);
-			return;
-		}
-
-		for(int x = tileSet.x0; x <= tileSet.x1; x++) {
-			for(int y = tileSet.y0; y <= tileSet.y1; y++) {
-				Tile t = tileController.getTile(x, y, ELE_ZOOM_LEVEL);
-
-				if (t != null && t.isLoaded() && t instanceof ElevationGridTile) {
-					((ElevationGridTile)t).paintTile(g, mv, vertexRenderer);
-				} else {
-					// give some consolation...
-					Point topLeft = mv.getPoint(new LatLon(tileSource.tileXYToLatLon(x, y, ELE_ZOOM_LEVEL)));
-					t.paint(g, topLeft.x, topLeft.y);
-				}
-			}
-		}
-	}
-
-	@Override
-	public String getToolTipText() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void visitBoundingBox(BoundingXYVisitor v) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public Action[] getMenuEntries() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void tileLoadingFinished(Tile tile, boolean success) {
-		try {
-			if (Main.map != null) {
-				Main.map.repaint(100);
-			}
-		} catch(Exception ex) {
-			System.err.println(ex);
-			ex.printStackTrace(System.err);
-		}
-	}
-
-	@Override
-	public Icon getIcon() {
-		return ImageProvider.get("layer", "elevation");
-	}
-
-	@Override
-	public void mergeFrom(Layer from) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public boolean isMergable(Layer other) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public Object getInfoComponent() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-
-	// Stolen from TMSLayer...
-	void myDrawString(Graphics g, String text, int x, int y) {
-		Color oldColor = g.getColor();
-		g.setColor(Color.black);
-		g.drawString(text,x+1,y+1);
-		g.setColor(oldColor);
-		g.drawString(text,x,y);
-	}
-
-	private class TileSet {
-		int x0, x1, y0, y1;
-		int tileMax = -1;
-
-		/**
-		 * Create a TileSet by known LatLon bbox without layer shift correction
-		 */
-		public TileSet(LatLon topLeft, LatLon botRight, int zoom) {
-			if (zoom == 0)
-				return;
-
-			TileXY p0 = tileSource.latLonToTileXY(topLeft.lat(), topLeft.lon(), zoom);
-			TileXY p1 = tileSource.latLonToTileXY(botRight.lat(), botRight.lon(), zoom);
-
-			x0 = p0.getXIndex();
-			y0 = p0.getYIndex();
-			x1 = p1.getXIndex();
-			y1 = p1.getYIndex();
-			if (x0 > x1) {
-				int tmp = x0;
-				x0 = x1;
-				x1 = tmp;
-			}
-			if (y0 > y1) {
-				int tmp = y0;
-				y0 = y1;
-				y1 = tmp;
-			}
-			tileMax = (int)Math.pow(2.0, zoom);
-			if (x0 < 0) {
-				x0 = 0;
-			}
-			if (y0 < 0) {
-				y0 = 0;
-			}
-			if (x1 > tileMax) {
-				x1 = tileMax;
-			}
-			if (y1 > tileMax) {
-				y1 = tileMax;
-			}
-		}
-
-		int size() {
-			int x_span = x1 - x0 + 1;
-			int y_span = y1 - y0 + 1;
-			return x_span * y_span;
-		}
-
-		@Override
-		public String toString() {
-			return "TileSet [x0=" + x0 + ", x1=" + x1 + ", y0=" + y0 + ", y1="
-					+ y1 + ", size()=" + size() + ", tilesSpanned()="
-					+ tilesSpanned() + "]";
-		}
-
-		double tilesSpanned() {
-			return Math.sqrt(1.0 * this.size());
-		}
-
-		boolean tooSmall() {
-			return this.tilesSpanned() < 1;
-		}
-
-		boolean tooLarge() {
-			return this.tilesSpanned() > 50;
-		}
-
-		boolean insane() {
-			return this.tilesSpanned() > 200;
-		}
-	}
+    private static final int ELE_ZOOM_LEVEL = 13;
+    private final IVertexRenderer vertexRenderer;
+    private final MemoryTileCache tileCache;
+    protected TileSource tileSource;
+    protected ElevationGridTileLoader tileLoader;
+    protected TileController tileController;
+
+    private Bounds lastBounds;
+    private TileSet tileSet;
+
+    /**
+     * @param info
+     */
+    public ElevationGridLayer(String name) {
+        super(name);
+
+        setOpacity(0.8);
+        setBackgroundLayer(true);
+        vertexRenderer = new SimpleVertexRenderer();
+
+        tileCache = new MemoryTileCache();
+        tileCache.setCacheSize(500);
+        tileSource = new ElevationGridTileSource(name);
+        tileLoader = new ElevationGridTileLoader(this);
+        tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader);
+    }
+
+    @Override
+    public void paint(Graphics2D g, MapView mv, Bounds box) {
+        boolean needsNewTileSet = tileSet == null || (lastBounds == null || !lastBounds.equals(box));
+
+        if (needsNewTileSet) {
+            tileSet = new TileSet(box.getMin(), box.getMax(), ELE_ZOOM_LEVEL); // we use a vector format with constant zoom level
+            lastBounds = box;
+            System.out.println("paint " + tileSet);
+        }
+
+        if (tileSet.insane()) {
+            myDrawString(g, tr("zoom in to load any tiles"), 120, 120);
+            return;
+        } else if (tileSet.tooLarge()) {
+            myDrawString(g, tr("zoom in to load more tiles"), 120, 120);
+            return;
+        } else if (tileSet.tooSmall()) {
+            myDrawString(g, tr("increase zoom level to see more detail"), 120, 120);
+            return;
+        }
+
+        for(int x = tileSet.x0; x <= tileSet.x1; x++) {
+            for(int y = tileSet.y0; y <= tileSet.y1; y++) {
+                Tile t = tileController.getTile(x, y, ELE_ZOOM_LEVEL);
+
+                if (t != null && t.isLoaded() && t instanceof ElevationGridTile) {
+                    ((ElevationGridTile)t).paintTile(g, mv, vertexRenderer);
+                } else {
+                    // give some consolation...
+                    Point topLeft = mv.getPoint(new LatLon(tileSource.tileXYToLatLon(x, y, ELE_ZOOM_LEVEL)));
+                    t.paint(g, topLeft.x, topLeft.y);
+                }
+            }
+        }
+    }
+
+    @Override
+    public String getToolTipText() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void visitBoundingBox(BoundingXYVisitor v) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Action[] getMenuEntries() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void tileLoadingFinished(Tile tile, boolean success) {
+        try {
+            if (Main.map != null) {
+                Main.map.repaint(100);
+            }
+        } catch(Exception ex) {
+            System.err.println(ex);
+            ex.printStackTrace(System.err);
+        }
+    }
+
+    @Override
+    public Icon getIcon() {
+        return ImageProvider.get("layer", "elevation");
+    }
+
+    @Override
+    public void mergeFrom(Layer from) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isMergable(Layer other) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Object getInfoComponent() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    // Stolen from TMSLayer...
+    void myDrawString(Graphics g, String text, int x, int y) {
+        Color oldColor = g.getColor();
+        g.setColor(Color.black);
+        g.drawString(text,x+1,y+1);
+        g.setColor(oldColor);
+        g.drawString(text,x,y);
+    }
+
+    private class TileSet {
+        int x0, x1, y0, y1;
+        int tileMax = -1;
+
+        /**
+         * Create a TileSet by known LatLon bbox without layer shift correction
+         */
+        public TileSet(LatLon topLeft, LatLon botRight, int zoom) {
+            if (zoom == 0)
+                return;
+
+            TileXY p0 = tileSource.latLonToTileXY(topLeft.lat(), topLeft.lon(), zoom);
+            TileXY p1 = tileSource.latLonToTileXY(botRight.lat(), botRight.lon(), zoom);
+
+            x0 = p0.getXIndex();
+            y0 = p0.getYIndex();
+            x1 = p1.getXIndex();
+            y1 = p1.getYIndex();
+            if (x0 > x1) {
+                int tmp = x0;
+                x0 = x1;
+                x1 = tmp;
+            }
+            if (y0 > y1) {
+                int tmp = y0;
+                y0 = y1;
+                y1 = tmp;
+            }
+            tileMax = (int)Math.pow(2.0, zoom);
+            if (x0 < 0) {
+                x0 = 0;
+            }
+            if (y0 < 0) {
+                y0 = 0;
+            }
+            if (x1 > tileMax) {
+                x1 = tileMax;
+            }
+            if (y1 > tileMax) {
+                y1 = tileMax;
+            }
+        }
+
+        int size() {
+            int x_span = x1 - x0 + 1;
+            int y_span = y1 - y0 + 1;
+            return x_span * y_span;
+        }
+
+        @Override
+        public String toString() {
+            return "TileSet [x0=" + x0 + ", x1=" + x1 + ", y0=" + y0 + ", y1="
+                    + y1 + ", size()=" + size() + ", tilesSpanned()="
+                    + tilesSpanned() + "]";
+        }
+
+        double tilesSpanned() {
+            return Math.sqrt(1.0 * this.size());
+        }
+
+        boolean tooSmall() {
+            return this.tilesSpanned() < 1;
+        }
+
+        boolean tooLarge() {
+            return this.tilesSpanned() > 50;
+        }
+
+        boolean insane() {
+            return this.tilesSpanned() > 200;
+        }
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java	(revision 32315)
@@ -25,149 +25,149 @@
 
 public class ElevationGridTile extends Tile {
-	private final BlockingDeque<EleVertex> toDo = new LinkedBlockingDeque<>();
-	private final BlockingDeque<EleVertex> vertices = new LinkedBlockingDeque<>();
+    private final BlockingDeque<EleVertex> toDo = new LinkedBlockingDeque<>();
+    private final BlockingDeque<EleVertex> vertices = new LinkedBlockingDeque<>();
 
-	private Bounds box;
+    private Bounds box;
 
-	public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom) {
-		super(source, xtile, ytile, zoom);
+    public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom) {
+        super(source, xtile, ytile, zoom);
 
-		box = tile2Bounds(xtile, ytile, zoom);
-		initQueue();
-	}
+        box = tile2Bounds(xtile, ytile, zoom);
+        initQueue();
+    }
 
-	public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom,
-			BufferedImage image) {
-		super(source, xtile, ytile, zoom, image);
+    public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom,
+            BufferedImage image) {
+        super(source, xtile, ytile, zoom, image);
 
 
-	}
+    }
 
-	@Override
-	public void loadPlaceholderFromCache(TileCache cache) {
-		// TODO Auto-generated method stub
-		super.loadPlaceholderFromCache(cache);
+    @Override
+    public void loadPlaceholderFromCache(TileCache cache) {
+        // TODO Auto-generated method stub
+        super.loadPlaceholderFromCache(cache);
 
-		//System.out.println("loadPlaceholderFromCache");
-	}
+        //System.out.println("loadPlaceholderFromCache");
+    }
 
-	@Override
-	public String getUrl() throws IOException {
-		// TODO Auto-generated method stub
-		return super.getUrl();
-	}
+    @Override
+    public String getUrl() throws IOException {
+        // TODO Auto-generated method stub
+        return super.getUrl();
+    }
 
-	/**
-	 * Use {@link ElevationGridTile#paintTile(Graphics2D, MapView, IVertexRenderer)} to render the tile as grid. This method just issues a debug text.
-	 */
-	@Override
-	public void paint(Graphics g, int x, int y) {
-		super.paint(g, x, y);
+    /**
+     * Use {@link ElevationGridTile#paintTile(Graphics2D, MapView, IVertexRenderer)} to render the tile as grid. This method just issues a debug text.
+     */
+    @Override
+    public void paint(Graphics g, int x, int y) {
+        super.paint(g, x, y);
 
-		//g.drawString(String.format("EGT %d/%d ", getXtile(), getYtile()), x, y);
-		g.drawString(getStatus(), x, y);
-	}
+        //g.drawString(String.format("EGT %d/%d ", getXtile(), getYtile()), x, y);
+        g.drawString(getStatus(), x, y);
+    }
 
-	/**
-	 * Paints the vertices of this tile.
-	 *
-	 * @param g the graphics context
-	 * @param mv the map view
-	 * @param vertexRenderer the vertex renderer
-	 */
-	public void paintTile(Graphics2D g, MapView mv, IVertexRenderer vertexRenderer) {
-		BlockingDeque<EleVertex> list = getVertices();
-		for (EleVertex eleVertex : list) {
-			Point p0 = mv.getPoint(eleVertex.get(0));
-			Point p1 = mv.getPoint(eleVertex.get(1));
-			Point p2 = mv.getPoint(eleVertex.get(2));
-			Triangle shape = new Triangle(p0, p1, p2);
+    /**
+     * Paints the vertices of this tile.
+     *
+     * @param g the graphics context
+     * @param mv the map view
+     * @param vertexRenderer the vertex renderer
+     */
+    public void paintTile(Graphics2D g, MapView mv, IVertexRenderer vertexRenderer) {
+        BlockingDeque<EleVertex> list = getVertices();
+        for (EleVertex eleVertex : list) {
+            Point p0 = mv.getPoint(eleVertex.get(0));
+            Point p1 = mv.getPoint(eleVertex.get(1));
+            Point p2 = mv.getPoint(eleVertex.get(2));
+            Triangle shape = new Triangle(p0, p1, p2);
 
-			// obtain vertex color
-			g.setColor(vertexRenderer.getElevationColor(eleVertex));
-			// TODO: Move to renderer
-			g.fill(shape);
-		}
-	}
+            // obtain vertex color
+            g.setColor(vertexRenderer.getElevationColor(eleVertex));
+            // TODO: Move to renderer
+            g.fill(shape);
+        }
+    }
 
-	@Override
-	public void loadImage(InputStream input) throws IOException {
-		if (isLoaded()) return;
+    @Override
+    public void loadImage(InputStream input) throws IOException {
+        if (isLoaded()) return;
 
-		// TODO: Save
+        // TODO: Save
 
-		// We abuse the loadImage method to render the vertices...
-		//
-		while (toDo.size() > 0) {
-			EleVertex vertex = toDo.poll();
+        // We abuse the loadImage method to render the vertices...
+        //
+        while (toDo.size() > 0) {
+            EleVertex vertex = toDo.poll();
 
-			if (vertex.isFinished()) {
-				vertices.add(vertex);
-			} else {
-				List<EleVertex> newV = vertex.divide();
-				for (EleVertex eleVertex : newV) {
-					toDo.add(eleVertex);
-				}
-			}
-		}
-		setLoaded(true);
-	}
+            if (vertex.isFinished()) {
+                vertices.add(vertex);
+            } else {
+                List<EleVertex> newV = vertex.divide();
+                for (EleVertex eleVertex : newV) {
+                    toDo.add(eleVertex);
+                }
+            }
+        }
+        setLoaded(true);
+    }
 
-	public BlockingDeque<EleVertex> getVertices() {
-		return vertices;
-	}
+    public BlockingDeque<EleVertex> getVertices() {
+        return vertices;
+    }
 
-	/**
-	 * See also <a href="http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_bounding_box">OSM Wiki</a>
-	 * @param x the x
-	 * @param y the y
-	 * @param zoom the zoom
-	 * @return the bounds
-	 */
-	private Bounds tile2Bounds(final int x, final int y, final int zoom) {
-		return new Bounds(
-				new LatLon(source.tileXYToLatLon(x, y, zoom)),
-				new LatLon(source.tileXYToLatLon(x + 1, y + 1, zoom)));
-	}
+    /**
+     * See also <a href="http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_bounding_box">OSM Wiki</a>
+     * @param x the x
+     * @param y the y
+     * @param zoom the zoom
+     * @return the bounds
+     */
+    private Bounds tile2Bounds(final int x, final int y, final int zoom) {
+        return new Bounds(
+                new LatLon(source.tileXYToLatLon(x, y, zoom)),
+                new LatLon(source.tileXYToLatLon(x + 1, y + 1, zoom)));
+    }
 
-	/**
-	 * Inits the 'todo' queue with the initial vertices.
-	 */
-	private void initQueue() {
-		LatLon min = box.getMin();
-		LatLon max = box.getMax();
+    /**
+     * Inits the 'todo' queue with the initial vertices.
+     */
+    private void initQueue() {
+        LatLon min = box.getMin();
+        LatLon max = box.getMax();
 
-		// compute missing coordinates
-		LatLon h1 = new LatLon(min.lat(), max.lon());
-		LatLon h2 = new LatLon(max.lat(), min.lon());
+        // compute missing coordinates
+        LatLon h1 = new LatLon(min.lat(), max.lon());
+        LatLon h2 = new LatLon(max.lat(), min.lon());
 
-		double eleMin = ElevationHelper.getSrtmElevation(min);
-		double eleMax = ElevationHelper.getSrtmElevation(max);
+        double eleMin = ElevationHelper.getSrtmElevation(min);
+        double eleMax = ElevationHelper.getSrtmElevation(max);
 
-		// SRTM files present?
-		if (!ElevationHelper.isValidElevation(eleMax) || !ElevationHelper.isValidElevation(eleMin)) {
-			setError(tr("No SRTM data"));
-			return;
-		}
+        // SRTM files present?
+        if (!ElevationHelper.isValidElevation(eleMax) || !ElevationHelper.isValidElevation(eleMin)) {
+            setError(tr("No SRTM data"));
+            return;
+        }
 
-		// compute elevation coords
-		EleCoordinate p0 = new EleCoordinate(min, eleMin);
-		EleCoordinate p1 = new EleCoordinate(h1, ElevationHelper.getSrtmElevation(h1));
-		EleCoordinate p2 = new EleCoordinate(max, eleMax);
-		EleCoordinate p3 = new EleCoordinate(h2, ElevationHelper.getSrtmElevation(h2));
+        // compute elevation coords
+        EleCoordinate p0 = new EleCoordinate(min, eleMin);
+        EleCoordinate p1 = new EleCoordinate(h1, ElevationHelper.getSrtmElevation(h1));
+        EleCoordinate p2 = new EleCoordinate(max, eleMax);
+        EleCoordinate p3 = new EleCoordinate(h2, ElevationHelper.getSrtmElevation(h2));
 
-		// compute initial vertices
-		EleVertex v1 = new EleVertex(p0, p1, p2);
-		EleVertex v2 = new EleVertex(p2, p3, p0);
-		// enqueue vertices
-		toDo.add(v1);
-		toDo.add(v2);
-	}
+        // compute initial vertices
+        EleVertex v1 = new EleVertex(p0, p1, p2);
+        EleVertex v2 = new EleVertex(p2, p3, p0);
+        // enqueue vertices
+        toDo.add(v1);
+        toDo.add(v2);
+    }
 
-	@Override
-	public String toString() {
-		return "ElevationGridTile [box=" + box + ", xtile=" + xtile
-				+ ", ytile=" + ytile + "]";
-	}
+    @Override
+    public String toString() {
+        return "ElevationGridTile [box=" + box + ", xtile=" + xtile
+                + ", ytile=" + ytile + "]";
+    }
 
 
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileController.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileController.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileController.java	(revision 32315)
@@ -16,40 +16,40 @@
 public class ElevationGridTileController extends TileController {
 
-	/**
-	 * @param source
-	 * @param tileCache
-	 * @param listener
-	 */
-	public ElevationGridTileController(TileSource source, TileCache tileCache,
-			TileLoaderListener listener, TileLoader loader) {
-		super(source, tileCache, listener);
+    /**
+     * @param source
+     * @param tileCache
+     * @param listener
+     */
+    public ElevationGridTileController(TileSource source, TileCache tileCache,
+            TileLoaderListener listener, TileLoader loader) {
+        super(source, tileCache, listener);
 
-		tileSource = source; // FIXME: hard-coded in base class (although parameter is given)!!
-		tileLoader = loader; // FIXME: hard-coded in base class!
-	}
+        tileSource = source; // FIXME: hard-coded in base class (although parameter is given)!!
+        tileLoader = loader; // FIXME: hard-coded in base class!
+    }
 
-	@Override
-	public Tile getTile(int tilex, int tiley, int zoom) {
-		int max = (1 << zoom);
-		if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max)
-			return null;
-		Tile tile = tileCache.getTile(tileSource, tilex, tiley, zoom);
-		if (tile == null) {
-			// FIXME: Provide/use a factory method here
-			tile = new ElevationGridTile(tileSource, tilex, tiley, zoom);
-			tileCache.addTile(tile);
-			tile.loadPlaceholderFromCache(tileCache);
-		}
-		if (tile.hasError()) {
-			tile.loadPlaceholderFromCache(tileCache);
-		}
-		if (!tile.isLoaded()) {
-			tileLoader.createTileLoaderJob(tile).submit();
-		}
-		return tile;
-	}
+    @Override
+    public Tile getTile(int tilex, int tiley, int zoom) {
+        int max = (1 << zoom);
+        if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max)
+            return null;
+        Tile tile = tileCache.getTile(tileSource, tilex, tiley, zoom);
+        if (tile == null) {
+            // FIXME: Provide/use a factory method here
+            tile = new ElevationGridTile(tileSource, tilex, tiley, zoom);
+            tileCache.addTile(tile);
+            tile.loadPlaceholderFromCache(tileCache);
+        }
+        if (tile.hasError()) {
+            tile.loadPlaceholderFromCache(tileCache);
+        }
+        if (!tile.isLoaded()) {
+            tileLoader.createTileLoaderJob(tile).submit();
+        }
+        return tile;
+    }
 
-	/**
-	 *
-	 */
+    /**
+     *
+     */
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java	(revision 32315)
@@ -13,58 +13,58 @@
  */
 public class ElevationGridTileLoader implements TileLoader {
-	protected TileLoaderListener listener;
+    protected TileLoaderListener listener;
 
-	public ElevationGridTileLoader(TileLoaderListener listener) {
-		CheckParameterUtil.ensureParameterNotNull(listener);
-		this.listener = listener;
-	}
+    public ElevationGridTileLoader(TileLoaderListener listener) {
+        CheckParameterUtil.ensureParameterNotNull(listener);
+        this.listener = listener;
+    }
 
-	@Override
-	public TileJob createTileLoaderJob(final Tile tile) {
-		CheckParameterUtil.ensureParameterNotNull(tile);
+    @Override
+    public TileJob createTileLoaderJob(final Tile tile) {
+        CheckParameterUtil.ensureParameterNotNull(tile);
 
-		return new TileJob() {
+        return new TileJob() {
 
-			@Override
-			public void run() {
-				synchronized (tile) {
-					if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
-						return;
-					tile.initLoading();
-				}
-				try {
-					tile.loadImage(null);
-					tile.setLoaded(true);
-					listener.tileLoadingFinished(tile, true);
-				} catch (Exception e) {
-					tile.setError(e.getMessage());
-					listener.tileLoadingFinished(tile, false);
-				} finally {
-					tile.finishLoading();
-				}
-			}
+            @Override
+            public void run() {
+                synchronized (tile) {
+                    if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
+                        return;
+                    tile.initLoading();
+                }
+                try {
+                    tile.loadImage(null);
+                    tile.setLoaded(true);
+                    listener.tileLoadingFinished(tile, true);
+                } catch (Exception e) {
+                    tile.setError(e.getMessage());
+                    listener.tileLoadingFinished(tile, false);
+                } finally {
+                    tile.finishLoading();
+                }
+            }
 
-			@Override
-			public Tile getTile() {
-				return tile;
-			}
+            @Override
+            public Tile getTile() {
+                return tile;
+            }
 
-			@Override
-			public void submit() {
-				run();
-			}
+            @Override
+            public void submit() {
+                run();
+            }
 
-			@Override
-			public void submit(boolean force) {
-				submit();
+            @Override
+            public void submit(boolean force) {
+                submit();
 
-			}
-		};
-	}
+            }
+        };
+    }
 
-	@Override
-	public void cancelOutstandingTasks() {
-		// intentionally left blank
-	}
+    @Override
+    public void cancelOutstandingTasks() {
+        // intentionally left blank
+    }
 
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java	(revision 32315)
@@ -33,510 +33,510 @@
 IElevationProfileRenderer {
 
-	private static final int ROUND_RECT_RADIUS = 6;
-	/**
-	 *
-	 */
-	private static final int TRIANGLE_BASESIZE = 24;
-	/**
-	 *
-	 */
-	private static final int BASIC_WPT_RADIUS = 1;
-	private static final int BIG_WPT_RADIUS = BASIC_WPT_RADIUS * 16;
-
-	// predefined colors
-	private static final Color HIGH_COLOR = ElevationColors.EPMidBlue;
-	private static final Color LOW_COLOR = ElevationColors.EPMidBlue;
-	private static final Color START_COLOR = Color.GREEN;
-	private static final Color END_POINT = Color.RED;
-	private static final Color LEVEL_GAIN_COLOR = Color.GREEN;
-	private static final Color LEVEL_LOSS_COLOR = Color.RED;
-	private static final Color MARKER_POINT = Color.YELLOW;
-	// Predefined radians
-	private static final double RAD_180 = Math.PI;
-	// private static final double RAD_270 = Math.PI * 1.5;
-	private static final double RAD_90 = Math.PI * 0.5;
-
-	private final List<Rectangle> forbiddenRects = new ArrayList<>();
-
-	@Override
-	public Color getColorForWaypoint(IElevationProfile profile, WayPoint wpt,
-			ElevationWayPointKind kind) {
-
-		if (wpt == null || profile == null) {
-			System.err.println(String.format(
-					"Cannot determine color: prof=%s, wpt=%s", profile, wpt));
-			return null;
-		}
-
-		switch (kind) {
-		case Plain:
-			return Color.LIGHT_GRAY;
-		case ElevationLevelLoss:
-			return LEVEL_LOSS_COLOR;
-		case ElevationLevelGain:
-			return LEVEL_GAIN_COLOR;
-		case Highlighted:
-			return Color.ORANGE;
-		case ElevationGainHigh:
-			return Color.getHSBColor(0.3f, 1.0f, 1.0f); // green
-		case ElevationLossHigh:
-			return Color.getHSBColor(0, 1.0f, 1.0f); // red
-		case ElevationGainLow:
-			return Color.getHSBColor(0.3f, 0.5f, 1.0f); // green with low sat
-		case ElevationLossLow:
-			return Color.getHSBColor(0, 0.5f, 1.0f); // red with low sat
-		case FullHour:
-			return MARKER_POINT;
-		case MaxElevation:
-			return HIGH_COLOR;
-		case MinElevation:
-			return LOW_COLOR;
-		case StartPoint:
-			return START_COLOR;
-		case EndPoint:
-			return END_POINT;
-		default:
-			break;
-		}
-
-		throw new RuntimeException("Unknown way point kind: " + kind);
-	}
-
-	@Override
-	public void renderWayPoint(Graphics g, IElevationProfile profile,
-			MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
-
-		CheckParameterUtil.ensureParameterNotNull(g, "graphics");
-		CheckParameterUtil.ensureParameterNotNull(profile, "profile");
-		CheckParameterUtil.ensureParameterNotNull(mv, "map view");
-
-		if (wpt == null) {
-			System.err.println(String.format(
-					"Cannot paint: mv=%s, prof=%s, wpt=%s", mv, profile, wpt));
-			return;
-		}
-
-		switch (kind) {
-		case MinElevation:
-		case MaxElevation:
-			renderMinMaxPoint(g, profile, mv, wpt, kind);
-			break;
-		case EndPoint:
-		case StartPoint:
-			renderStartEndPoint(g, profile, mv, wpt, kind);
-			break;
-		default:
-			renderRegularWayPoint(g, profile, mv, wpt, kind);
-			break;
-		}
-	}
-
-	@Override
-	public void renderLine(Graphics g, IElevationProfile profile,
-			MapView mv, WayPoint wpt1, WayPoint wpt2, ElevationWayPointKind kind) {
-
-		CheckParameterUtil.ensureParameterNotNull(g, "graphics");
-		CheckParameterUtil.ensureParameterNotNull(profile, "profile");
-		CheckParameterUtil.ensureParameterNotNull(mv, "map view");
-
-		if (wpt1 == null || wpt2 == null) {
-			System.err.println(String.format(
-					"Cannot paint line: mv=%s, prof=%s, kind = %s", mv, profile, kind));
-			return;
-		}
-
-		// obtain and set color
-		g.setColor(getColorForWaypoint(profile, wpt2, kind));
-
-		// transform to view
-		Point pnt1 = mv.getPoint(wpt1.getEastNorth());
-		Point pnt2 = mv.getPoint(wpt2.getEastNorth());
-
-		// use thick line, if possible
-		if (g instanceof Graphics2D) {
-			Graphics2D g2 = (Graphics2D) g;
-			Stroke oldS = g2.getStroke();
-			try {
-				g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-				g2.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y);
-			} finally {
-				// must be restored; otherwise other layers may using this style, too
-				g2.setStroke(oldS);
-			}
-		} else {
-			// only poor man's graphics
-			g.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y);
-		}
-	}
-
-	/**
-	 * Renders a regular way point.
-	 *
-	 * @param g
-	 *            The graphics context.
-	 * @param profile
-	 *            The elevation profile.
-	 * @param mv
-	 *            The map view instance.
-	 * @param wpt
-	 *            The way point to render.
-	 * @param kind
-	 *            The way point kind (start, end, max,...).
-	 */
-	private void renderRegularWayPoint(Graphics g, IElevationProfile profile,
-			MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
-
-		Color c = getColorForWaypoint(profile, wpt, kind);
-		Point pnt = mv.getPoint(wpt.getEastNorth());
-
-		/* Paint full hour label */
-		if (kind == ElevationWayPointKind.FullHour) {
-			int hour = ElevationHelper.getHourOfWayPoint(wpt);
-			drawLabel(String.format("%02d:00", hour), pnt.x, pnt.y
-					+ g.getFontMetrics().getHeight(), g);
-		}
-
-		/* Paint label for elevation levels */
-		if (kind == ElevationWayPointKind.ElevationLevelGain || kind == ElevationWayPointKind.ElevationLevelLoss) {
-			int ele = ((int) Math.rint(ElevationHelper.getElevation(wpt) / 100.0)) * 100;
-			drawLabelWithTriangle(ElevationHelper.getElevationText(ele), pnt.x, pnt.y
-					+ g.getFontMetrics().getHeight(), g, Color.darkGray, 8,
-					getColorForWaypoint(profile, wpt, kind),
-					kind == ElevationWayPointKind.ElevationLevelGain ? TriangleDir.Up : TriangleDir.Down);
-		}
-
-		/* Paint cursor labels */
-		if (kind == ElevationWayPointKind.Highlighted) {
-			drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS);
-			drawLabel(ElevationHelper.getTimeText(wpt), pnt.x, pnt.y
-					- g.getFontMetrics().getHeight() - 5, g);
-			drawLabel(ElevationHelper.getElevationText(wpt), pnt.x, pnt.y
-					+ g.getFontMetrics().getHeight() + 5, g);
-		}
-	}
-
-	/**
-	 * Renders a min/max point
-	 *
-	 * @param g
-	 *            The graphics context.
-	 * @param profile
-	 *            The elevation profile.
-	 * @param mv
-	 *            The map view instance.
-	 * @param wpt
-	 *            The way point to render.
-	 * @param kind
-	 *            The way point kind (start, end, max,...).
-	 */
-	private void renderMinMaxPoint(Graphics g, IElevationProfile profile,
-			MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
-
-		Color c = getColorForWaypoint(profile, wpt, kind);
-		int eleH = (int) ElevationHelper.getElevation(wpt);
-		Point pnt = mv.getPoint(wpt.getEastNorth());
-
-		TriangleDir td = TriangleDir.Up;
-
-		switch (kind) {
-		case MaxElevation:
-			td = TriangleDir.Up;
-			break;
-		case MinElevation:
-			td = TriangleDir.Down;
-			break;
-		case EndPoint:
-			td = TriangleDir.Left;
-			break;
-		case StartPoint:
-			td = TriangleDir.Right;
-			break;
-		default:
-			return; // nothing to do
-		}
-
-		drawRegularTriangle(g, c, td, pnt.x, pnt.y,
-				DefaultElevationProfileRenderer.TRIANGLE_BASESIZE);
-
-		drawLabel(ElevationHelper.getElevationText(eleH), pnt.x, pnt.y
-				+ g.getFontMetrics().getHeight(), g, c);
-	}
-
-	/**
-	 * Draws a regular triangle.
-	 *
-	 * @param g
-	 *            The graphics context.
-	 * @param c
-	 *            The fill color of the triangle.
-	 * @param dir
-	 *            The direction of the triangle
-	 * @param x
-	 *            The x coordinate in the graphics context.
-	 * @param y
-	 *            The y coordinate in the graphics context.
-	 * @param baseLength
-	 *            The side length in pixel of the triangle.
-	 */
-	private void drawRegularTriangle(Graphics g, Color c, TriangleDir dir,
-			int x, int y, int baseLength) {
-		if (baseLength < 2)
-			return; // cannot render triangle
-
-		int b2 = baseLength >> 1;
-
-		// coordinates for upwards directed triangle
-		Point p[] = new Point[3];
-
-		for (int i = 0; i < p.length; i++) {
-			p[i] = new Point();
-		}
-
-		p[0].x = -b2;
-		p[0].y = b2;
-
-		p[1].x = b2;
-		p[1].y = b2;
-
-		p[2].x = 0;
-		p[2].y = -b2;
-
-		Triangle t = new Triangle(p[0], p[1], p[2]);
-
-		// rotation angle in rad
-		double theta = 0.0;
-
-		switch (dir) {
-		case Up:
-			theta = 0.0;
-			break;
-		case Down:
-			theta = RAD_180;
-			break;
-		case Left:
-			theta = -RAD_90;
-			break;
-		case Right:
-			theta = RAD_90;
-			break;
-		}
-
-		// rotate shape
-		AffineTransform at = AffineTransform.getRotateInstance(theta);
-		Shape tRot = at.createTransformedShape(t);
-		// translate shape
-		AffineTransform at2 = AffineTransform.getTranslateInstance(x, y);
-		Shape ts = at2.createTransformedShape(tRot);
-
-		// draw the shape
-		Graphics2D g2 = (Graphics2D) g;
-		if (g2 != null) {
-			Color oldC = g2.getColor();
-			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-					RenderingHints.VALUE_ANTIALIAS_ON);
-			g2.setColor(c);
-			g2.fill(ts);
-			g2.setColor(oldC);
-		}
-	}
-
-	/**
-	 * Renders a start/end point.
-	 *
-	 * @param g
-	 *            The graphics context.
-	 * @param profile
-	 *            The elevation profile.
-	 * @param mv
-	 *            The map view instance.
-	 * @param wpt
-	 *            The way point to render.
-	 * @param kind
-	 *            The way point kind (start, end, max,...).
-	 */
-	private void renderStartEndPoint(Graphics g, IElevationProfile profile,
-			MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
-
-		Color c = getColorForWaypoint(profile, wpt, kind);
-		Point pnt = mv.getPoint(wpt.getEastNorth());
-		drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS);
-	}
-
-	/**
-	 * Draws a shaded sphere.
-	 *
-	 * @param g
-	 *            The graphics context.
-	 * @param firstCol
-	 *            The focus color (usually white).
-	 * @param secondCol
-	 *            The sphere color.
-	 * @param x
-	 *            The x coordinate of the sphere center.
-	 * @param y
-	 *            The y coordinate of the sphere center.
-	 * @param radius
-	 *            The radius of the sphere.
-	 */
-	private void drawSphere(Graphics g, Color firstCol, Color secondCol, int x,
-			int y, int radius) {
-		Point2D center = new Point2D.Float(x, y);
-		Point2D focus = new Point2D.Float(x - (radius * 0.6f), y
-				- (radius * 0.6f));
-		float[] dist = { 0.1f, 0.2f, 1.0f };
-		Color[] colors = { firstCol, secondCol, Color.DARK_GRAY };
-		RadialGradientPaint p = new RadialGradientPaint(center, radius, focus,
-				dist, colors, CycleMethod.NO_CYCLE);
-
-		Graphics2D g2 = (Graphics2D) g;
-		if (g2 != null) {
-			g2.setPaint(p);
-			int r2 = radius / 2;
-			g2.fillOval(x - r2, y - r2, radius, radius);
-		}
-	}
-
-	/**
-	 * Draws a label within a filled rounded rectangle with standard gradient colors.
-	 *
-	 * @param s
-	 *            The text to draw.
-	 * @param x
-	 *            The x coordinate of the label.
-	 * @param y
-	 *            The y coordinate of the label.
-	 * @param g
-	 *            The graphics context.
-	 */
-	private void drawLabel(String s, int x, int y, Graphics g) {
-		drawLabel(s, x, y, g, Color.GRAY);
-	}
-
-	/**
-	 * Draws a label within a filled rounded rectangle with the specified second gradient color (first color is <tt>Color.WHITE<tt>).
-	 *
-	 * @param s
-	 *            The text to draw.
-	 * @param x
-	 *            The x coordinate of the label.
-	 * @param y
-	 *            The y coordinate of the label.
-	 * @param g
-	 *            The graphics context.
-	 * @param secondGradColor
-	 *            The second color of the gradient.
-	 */
-	private void drawLabel(String s, int x, int y, Graphics g,
-			Color secondGradColor) {
-		Graphics2D g2d = (Graphics2D) g;
-
-		int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10;
-		int height = g.getFont().getSize() + g.getFontMetrics().getLeading()
-				+ 5;
-
-		Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width,
-				height);
-
-		if (isForbiddenArea(r)) {
-			return; // no space left, skip this label
-		}
-
-		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-				RenderingHints.VALUE_ANTIALIAS_ON);
-		GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y
-				+ (height / 2), secondGradColor, false);
-		g2d.setPaint(gradient);
-
-		g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
-				ROUND_RECT_RADIUS);
-
-		g2d.setColor(Color.BLACK);
-
-		g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
-				ROUND_RECT_RADIUS);
-		g2d.drawString(s, x - (width / 2) + 5, y + (height / 2) - 3);
-
-		forbiddenRects.add(r);
-	}
-
-	/**
-	 * Draws a label with an additional triangle on the left side.
-	 *
-	 * @param s
-	 *            The text to draw.
-	 * @param x
-	 *            The x coordinate of the label.
-	 * @param y
-	 *            The y coordinate of the label.
-	 * @param g
-	 *            The graphics context.
-	 * @param secondGradColor
-	 *            The second color of the gradient.
-	 * @param baseLength
-	 *            The base length of the triangle in pixels.
-	 * @param triangleColor
-	 *            The color of the triangle.
-	 * @param triangleDir
-	 *            The direction of the triangle.
-	 */
-	private void drawLabelWithTriangle(String s, int x, int y, Graphics g,
-			Color secondGradColor, int baseLength, Color triangleColor,
-			TriangleDir triangleDir) {
-		Graphics2D g2d = (Graphics2D) g;
-
-		int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10 + baseLength + 5;
-		int height = g.getFont().getSize() + g.getFontMetrics().getLeading() + 5;
-
-		Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, height);
-
-		if (isForbiddenArea(r)) {
-			return; // no space left, skip this label
-		}
-
-		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-				RenderingHints.VALUE_ANTIALIAS_ON);
-		GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y
-				+ (height / 2), secondGradColor, false);
-		g2d.setPaint(gradient);
-
-		g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
-				ROUND_RECT_RADIUS);
-
-		g2d.setColor(Color.BLACK);
-
-		g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
-				ROUND_RECT_RADIUS);
-		g2d.drawString(s, x - (width / 2) + 8 + baseLength, y + (height / 2) - 3);
-		drawRegularTriangle(g2d, triangleColor, triangleDir, r.x + baseLength,
-				r.y + baseLength, baseLength);
-
-		forbiddenRects.add(r);
-	}
-
-	/**
-	 * Checks, if the rectangle has been 'reserved' by an previous draw action.
-	 *
-	 * @param r
-	 *            The area to check for.
-	 * @return true, if area is already occupied by another rectangle.
-	 */
-	private boolean isForbiddenArea(Rectangle r) {
-
-		for (Rectangle rTest : forbiddenRects) {
-			if (r.intersects(rTest))
-				return true;
-		}
-		return false;
-	}
-
-	@Override
-	public void beginRendering() {
-		forbiddenRects.clear();
-	}
-
-	@Override
-	public void finishRendering() {
-		// nothing to do currently
-	}
+    private static final int ROUND_RECT_RADIUS = 6;
+    /**
+     *
+     */
+    private static final int TRIANGLE_BASESIZE = 24;
+    /**
+     *
+     */
+    private static final int BASIC_WPT_RADIUS = 1;
+    private static final int BIG_WPT_RADIUS = BASIC_WPT_RADIUS * 16;
+
+    // predefined colors
+    private static final Color HIGH_COLOR = ElevationColors.EPMidBlue;
+    private static final Color LOW_COLOR = ElevationColors.EPMidBlue;
+    private static final Color START_COLOR = Color.GREEN;
+    private static final Color END_POINT = Color.RED;
+    private static final Color LEVEL_GAIN_COLOR = Color.GREEN;
+    private static final Color LEVEL_LOSS_COLOR = Color.RED;
+    private static final Color MARKER_POINT = Color.YELLOW;
+    // Predefined radians
+    private static final double RAD_180 = Math.PI;
+    // private static final double RAD_270 = Math.PI * 1.5;
+    private static final double RAD_90 = Math.PI * 0.5;
+
+    private final List<Rectangle> forbiddenRects = new ArrayList<>();
+
+    @Override
+    public Color getColorForWaypoint(IElevationProfile profile, WayPoint wpt,
+            ElevationWayPointKind kind) {
+
+        if (wpt == null || profile == null) {
+            System.err.println(String.format(
+                    "Cannot determine color: prof=%s, wpt=%s", profile, wpt));
+            return null;
+        }
+
+        switch (kind) {
+        case Plain:
+            return Color.LIGHT_GRAY;
+        case ElevationLevelLoss:
+            return LEVEL_LOSS_COLOR;
+        case ElevationLevelGain:
+            return LEVEL_GAIN_COLOR;
+        case Highlighted:
+            return Color.ORANGE;
+        case ElevationGainHigh:
+            return Color.getHSBColor(0.3f, 1.0f, 1.0f); // green
+        case ElevationLossHigh:
+            return Color.getHSBColor(0, 1.0f, 1.0f); // red
+        case ElevationGainLow:
+            return Color.getHSBColor(0.3f, 0.5f, 1.0f); // green with low sat
+        case ElevationLossLow:
+            return Color.getHSBColor(0, 0.5f, 1.0f); // red with low sat
+        case FullHour:
+            return MARKER_POINT;
+        case MaxElevation:
+            return HIGH_COLOR;
+        case MinElevation:
+            return LOW_COLOR;
+        case StartPoint:
+            return START_COLOR;
+        case EndPoint:
+            return END_POINT;
+        default:
+            break;
+        }
+
+        throw new RuntimeException("Unknown way point kind: " + kind);
+    }
+
+    @Override
+    public void renderWayPoint(Graphics g, IElevationProfile profile,
+            MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
+
+        CheckParameterUtil.ensureParameterNotNull(g, "graphics");
+        CheckParameterUtil.ensureParameterNotNull(profile, "profile");
+        CheckParameterUtil.ensureParameterNotNull(mv, "map view");
+
+        if (wpt == null) {
+            System.err.println(String.format(
+                    "Cannot paint: mv=%s, prof=%s, wpt=%s", mv, profile, wpt));
+            return;
+        }
+
+        switch (kind) {
+        case MinElevation:
+        case MaxElevation:
+            renderMinMaxPoint(g, profile, mv, wpt, kind);
+            break;
+        case EndPoint:
+        case StartPoint:
+            renderStartEndPoint(g, profile, mv, wpt, kind);
+            break;
+        default:
+            renderRegularWayPoint(g, profile, mv, wpt, kind);
+            break;
+        }
+    }
+
+    @Override
+    public void renderLine(Graphics g, IElevationProfile profile,
+            MapView mv, WayPoint wpt1, WayPoint wpt2, ElevationWayPointKind kind) {
+
+        CheckParameterUtil.ensureParameterNotNull(g, "graphics");
+        CheckParameterUtil.ensureParameterNotNull(profile, "profile");
+        CheckParameterUtil.ensureParameterNotNull(mv, "map view");
+
+        if (wpt1 == null || wpt2 == null) {
+            System.err.println(String.format(
+                    "Cannot paint line: mv=%s, prof=%s, kind = %s", mv, profile, kind));
+            return;
+        }
+
+        // obtain and set color
+        g.setColor(getColorForWaypoint(profile, wpt2, kind));
+
+        // transform to view
+        Point pnt1 = mv.getPoint(wpt1.getEastNorth());
+        Point pnt2 = mv.getPoint(wpt2.getEastNorth());
+
+        // use thick line, if possible
+        if (g instanceof Graphics2D) {
+            Graphics2D g2 = (Graphics2D) g;
+            Stroke oldS = g2.getStroke();
+            try {
+                g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+                g2.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y);
+            } finally {
+                // must be restored; otherwise other layers may using this style, too
+                g2.setStroke(oldS);
+            }
+        } else {
+            // only poor man's graphics
+            g.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y);
+        }
+    }
+
+    /**
+     * Renders a regular way point.
+     *
+     * @param g
+     *            The graphics context.
+     * @param profile
+     *            The elevation profile.
+     * @param mv
+     *            The map view instance.
+     * @param wpt
+     *            The way point to render.
+     * @param kind
+     *            The way point kind (start, end, max,...).
+     */
+    private void renderRegularWayPoint(Graphics g, IElevationProfile profile,
+            MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
+
+        Color c = getColorForWaypoint(profile, wpt, kind);
+        Point pnt = mv.getPoint(wpt.getEastNorth());
+
+        /* Paint full hour label */
+        if (kind == ElevationWayPointKind.FullHour) {
+            int hour = ElevationHelper.getHourOfWayPoint(wpt);
+            drawLabel(String.format("%02d:00", hour), pnt.x, pnt.y
+                    + g.getFontMetrics().getHeight(), g);
+        }
+
+        /* Paint label for elevation levels */
+        if (kind == ElevationWayPointKind.ElevationLevelGain || kind == ElevationWayPointKind.ElevationLevelLoss) {
+            int ele = ((int) Math.rint(ElevationHelper.getElevation(wpt) / 100.0)) * 100;
+            drawLabelWithTriangle(ElevationHelper.getElevationText(ele), pnt.x, pnt.y
+                    + g.getFontMetrics().getHeight(), g, Color.darkGray, 8,
+                    getColorForWaypoint(profile, wpt, kind),
+                    kind == ElevationWayPointKind.ElevationLevelGain ? TriangleDir.Up : TriangleDir.Down);
+        }
+
+        /* Paint cursor labels */
+        if (kind == ElevationWayPointKind.Highlighted) {
+            drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS);
+            drawLabel(ElevationHelper.getTimeText(wpt), pnt.x, pnt.y
+                    - g.getFontMetrics().getHeight() - 5, g);
+            drawLabel(ElevationHelper.getElevationText(wpt), pnt.x, pnt.y
+                    + g.getFontMetrics().getHeight() + 5, g);
+        }
+    }
+
+    /**
+     * Renders a min/max point
+     *
+     * @param g
+     *            The graphics context.
+     * @param profile
+     *            The elevation profile.
+     * @param mv
+     *            The map view instance.
+     * @param wpt
+     *            The way point to render.
+     * @param kind
+     *            The way point kind (start, end, max,...).
+     */
+    private void renderMinMaxPoint(Graphics g, IElevationProfile profile,
+            MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
+
+        Color c = getColorForWaypoint(profile, wpt, kind);
+        int eleH = (int) ElevationHelper.getElevation(wpt);
+        Point pnt = mv.getPoint(wpt.getEastNorth());
+
+        TriangleDir td = TriangleDir.Up;
+
+        switch (kind) {
+        case MaxElevation:
+            td = TriangleDir.Up;
+            break;
+        case MinElevation:
+            td = TriangleDir.Down;
+            break;
+        case EndPoint:
+            td = TriangleDir.Left;
+            break;
+        case StartPoint:
+            td = TriangleDir.Right;
+            break;
+        default:
+            return; // nothing to do
+        }
+
+        drawRegularTriangle(g, c, td, pnt.x, pnt.y,
+                DefaultElevationProfileRenderer.TRIANGLE_BASESIZE);
+
+        drawLabel(ElevationHelper.getElevationText(eleH), pnt.x, pnt.y
+                + g.getFontMetrics().getHeight(), g, c);
+    }
+
+    /**
+     * Draws a regular triangle.
+     *
+     * @param g
+     *            The graphics context.
+     * @param c
+     *            The fill color of the triangle.
+     * @param dir
+     *            The direction of the triangle
+     * @param x
+     *            The x coordinate in the graphics context.
+     * @param y
+     *            The y coordinate in the graphics context.
+     * @param baseLength
+     *            The side length in pixel of the triangle.
+     */
+    private void drawRegularTriangle(Graphics g, Color c, TriangleDir dir,
+            int x, int y, int baseLength) {
+        if (baseLength < 2)
+            return; // cannot render triangle
+
+        int b2 = baseLength >> 1;
+
+        // coordinates for upwards directed triangle
+        Point p[] = new Point[3];
+
+        for (int i = 0; i < p.length; i++) {
+            p[i] = new Point();
+        }
+
+        p[0].x = -b2;
+        p[0].y = b2;
+
+        p[1].x = b2;
+        p[1].y = b2;
+
+        p[2].x = 0;
+        p[2].y = -b2;
+
+        Triangle t = new Triangle(p[0], p[1], p[2]);
+
+        // rotation angle in rad
+        double theta = 0.0;
+
+        switch (dir) {
+        case Up:
+            theta = 0.0;
+            break;
+        case Down:
+            theta = RAD_180;
+            break;
+        case Left:
+            theta = -RAD_90;
+            break;
+        case Right:
+            theta = RAD_90;
+            break;
+        }
+
+        // rotate shape
+        AffineTransform at = AffineTransform.getRotateInstance(theta);
+        Shape tRot = at.createTransformedShape(t);
+        // translate shape
+        AffineTransform at2 = AffineTransform.getTranslateInstance(x, y);
+        Shape ts = at2.createTransformedShape(tRot);
+
+        // draw the shape
+        Graphics2D g2 = (Graphics2D) g;
+        if (g2 != null) {
+            Color oldC = g2.getColor();
+            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                    RenderingHints.VALUE_ANTIALIAS_ON);
+            g2.setColor(c);
+            g2.fill(ts);
+            g2.setColor(oldC);
+        }
+    }
+
+    /**
+     * Renders a start/end point.
+     *
+     * @param g
+     *            The graphics context.
+     * @param profile
+     *            The elevation profile.
+     * @param mv
+     *            The map view instance.
+     * @param wpt
+     *            The way point to render.
+     * @param kind
+     *            The way point kind (start, end, max,...).
+     */
+    private void renderStartEndPoint(Graphics g, IElevationProfile profile,
+            MapView mv, WayPoint wpt, ElevationWayPointKind kind) {
+
+        Color c = getColorForWaypoint(profile, wpt, kind);
+        Point pnt = mv.getPoint(wpt.getEastNorth());
+        drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS);
+    }
+
+    /**
+     * Draws a shaded sphere.
+     *
+     * @param g
+     *            The graphics context.
+     * @param firstCol
+     *            The focus color (usually white).
+     * @param secondCol
+     *            The sphere color.
+     * @param x
+     *            The x coordinate of the sphere center.
+     * @param y
+     *            The y coordinate of the sphere center.
+     * @param radius
+     *            The radius of the sphere.
+     */
+    private void drawSphere(Graphics g, Color firstCol, Color secondCol, int x,
+            int y, int radius) {
+        Point2D center = new Point2D.Float(x, y);
+        Point2D focus = new Point2D.Float(x - (radius * 0.6f), y
+                - (radius * 0.6f));
+        float[] dist = { 0.1f, 0.2f, 1.0f };
+        Color[] colors = { firstCol, secondCol, Color.DARK_GRAY };
+        RadialGradientPaint p = new RadialGradientPaint(center, radius, focus,
+                dist, colors, CycleMethod.NO_CYCLE);
+
+        Graphics2D g2 = (Graphics2D) g;
+        if (g2 != null) {
+            g2.setPaint(p);
+            int r2 = radius / 2;
+            g2.fillOval(x - r2, y - r2, radius, radius);
+        }
+    }
+
+    /**
+     * Draws a label within a filled rounded rectangle with standard gradient colors.
+     *
+     * @param s
+     *            The text to draw.
+     * @param x
+     *            The x coordinate of the label.
+     * @param y
+     *            The y coordinate of the label.
+     * @param g
+     *            The graphics context.
+     */
+    private void drawLabel(String s, int x, int y, Graphics g) {
+        drawLabel(s, x, y, g, Color.GRAY);
+    }
+
+    /**
+     * Draws a label within a filled rounded rectangle with the specified second gradient color (first color is <tt>Color.WHITE<tt>).
+     *
+     * @param s
+     *            The text to draw.
+     * @param x
+     *            The x coordinate of the label.
+     * @param y
+     *            The y coordinate of the label.
+     * @param g
+     *            The graphics context.
+     * @param secondGradColor
+     *            The second color of the gradient.
+     */
+    private void drawLabel(String s, int x, int y, Graphics g,
+            Color secondGradColor) {
+        Graphics2D g2d = (Graphics2D) g;
+
+        int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10;
+        int height = g.getFont().getSize() + g.getFontMetrics().getLeading()
+                + 5;
+
+        Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width,
+                height);
+
+        if (isForbiddenArea(r)) {
+            return; // no space left, skip this label
+        }
+
+        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+        GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y
+                + (height / 2), secondGradColor, false);
+        g2d.setPaint(gradient);
+
+        g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
+                ROUND_RECT_RADIUS);
+
+        g2d.setColor(Color.BLACK);
+
+        g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
+                ROUND_RECT_RADIUS);
+        g2d.drawString(s, x - (width / 2) + 5, y + (height / 2) - 3);
+
+        forbiddenRects.add(r);
+    }
+
+    /**
+     * Draws a label with an additional triangle on the left side.
+     *
+     * @param s
+     *            The text to draw.
+     * @param x
+     *            The x coordinate of the label.
+     * @param y
+     *            The y coordinate of the label.
+     * @param g
+     *            The graphics context.
+     * @param secondGradColor
+     *            The second color of the gradient.
+     * @param baseLength
+     *            The base length of the triangle in pixels.
+     * @param triangleColor
+     *            The color of the triangle.
+     * @param triangleDir
+     *            The direction of the triangle.
+     */
+    private void drawLabelWithTriangle(String s, int x, int y, Graphics g,
+            Color secondGradColor, int baseLength, Color triangleColor,
+            TriangleDir triangleDir) {
+        Graphics2D g2d = (Graphics2D) g;
+
+        int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10 + baseLength + 5;
+        int height = g.getFont().getSize() + g.getFontMetrics().getLeading() + 5;
+
+        Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, height);
+
+        if (isForbiddenArea(r)) {
+            return; // no space left, skip this label
+        }
+
+        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+        GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y
+                + (height / 2), secondGradColor, false);
+        g2d.setPaint(gradient);
+
+        g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
+                ROUND_RECT_RADIUS);
+
+        g2d.setColor(Color.BLACK);
+
+        g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS,
+                ROUND_RECT_RADIUS);
+        g2d.drawString(s, x - (width / 2) + 8 + baseLength, y + (height / 2) - 3);
+        drawRegularTriangle(g2d, triangleColor, triangleDir, r.x + baseLength,
+                r.y + baseLength, baseLength);
+
+        forbiddenRects.add(r);
+    }
+
+    /**
+     * Checks, if the rectangle has been 'reserved' by an previous draw action.
+     *
+     * @param r
+     *            The area to check for.
+     * @return true, if area is already occupied by another rectangle.
+     */
+    private boolean isForbiddenArea(Rectangle r) {
+
+        for (Rectangle rTest : forbiddenRects) {
+            if (r.intersects(rTest))
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void beginRendering() {
+        forbiddenRects.clear();
+    }
+
+    @Override
+    public void finishRendering() {
+        // nothing to do currently
+    }
 
 
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java	(revision 32315)
@@ -47,415 +47,415 @@
 public class ElevationProfileDialog extends ToggleDialog implements LayerChangeListener, ComponentListener {
 
-	private static final String EMPTY_DATA_STRING = "-";
-	private static final long serialVersionUID = -868463893732535577L;
-	/* Elevation profile instance */
-	private IElevationModel model;
-	/* GPX data */
-	private GpxLayer activeLayer = null;
-	private final HashMap<GpxLayer, ElevationModel> layerMap = new HashMap<>();
-
-	/* UI elements */
-	private final ElevationProfilePanel profPanel;
-	private final JLabel minHeightLabel;
-	private final JLabel maxHeightLabel;
-	private final JLabel avrgHeightLabel;
-	private final JLabel elevationGainLabel;
-	private final JLabel totalTimeLabel;
-	private final JLabel distLabel;
-	private final JComboBox<IElevationProfile> trackCombo;
-	private final JButton zoomButton;
-
-	/* Listener to the elevation model */
-	private final List<IElevationModelListener> listeners = new ArrayList<>();
-
-	/**
-	 * Corresponding layer instance within map view.
-	 */
-	private ElevationProfileLayer profileLayer;
-
-	/**
-	 * Default constructor
-	 */
-	public ElevationProfileDialog() {
-		this(tr("Elevation Profile"), "elevation",
-				tr("Open the elevation profile window."), null, 200, true);
-	}
-
-	/**
-	 * Constructor (see below)
-	 */
-	public ElevationProfileDialog(String name, String iconName, String tooltip,
-			Shortcut shortcut, int preferredHeight) {
-		this(name, iconName, tooltip, shortcut, preferredHeight, false);
-	}
-
-	/**
-	 * Constructor
-	 *
-	 * @param name
-	 *            the name of the dialog
-	 * @param iconName
-	 *            the name of the icon to be displayed
-	 * @param tooltip
-	 *            the tool tip
-	 * @param shortcut
-	 *            the shortcut
-	 * @param preferredHeight
-	 *            the preferred height for the dialog
-	 * @param defShow
-	 *            if the dialog should be shown by default, if there is no
-	 *            preference
-	 */
-	public ElevationProfileDialog(String name, String iconName, String tooltip,
-			Shortcut shortcut, int preferredHeight, boolean defShow) {
-		super(name, iconName, tooltip, shortcut, preferredHeight, defShow);
-
-		// create model
-		model = new ElevationModel();
-
-		// top panel
-		JPanel rootPanel = new JPanel();
-		GridLayout gridLayout1 = new GridLayout(2, 1);
-		rootPanel.setLayout(gridLayout1);
-
-		// statistics panel
-		JPanel statPanel = new JPanel();
-		GridLayout gridLayoutStat = new GridLayout(2, 6);
-		statPanel.setLayout(gridLayoutStat);
-
-		// first row: Headlines with bold font
-		String[] labels = new String[]{tr("Min"), tr("Avrg"), tr("Max"), tr("Dist"), tr("Gain"), tr("Time")};
-		for (int i = 0; i < labels.length; i++) {
-			JLabel lbl = new JLabel(labels[i]);
-			lbl.setFont(getFont().deriveFont(Font.BOLD));
-			statPanel.add(lbl);
-		}
-
-		// second row
-		minHeightLabel = new JLabel("0 m");
-		statPanel.add(minHeightLabel);
-		avrgHeightLabel = new JLabel("0 m");
-		statPanel.add(avrgHeightLabel);
-		maxHeightLabel = new JLabel("0 m");
-		statPanel.add(maxHeightLabel);
-		distLabel = new JLabel("0 km");
-		statPanel.add(distLabel);
-		elevationGainLabel = new JLabel("0 m");
-		statPanel.add(elevationGainLabel);
-		totalTimeLabel = new JLabel("0");
-		statPanel.add(totalTimeLabel);
-
-		// track selection panel
-		JPanel trackPanel = new JPanel();
-		FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
-		trackPanel.setLayout(fl);
-
-		JLabel lbTrack = new JLabel(tr("Tracks"));
-		lbTrack.setFont(getFont().deriveFont(Font.BOLD));
-		trackPanel.add(lbTrack);
-
-		zoomButton = new JButton(tr("Zoom"));
-		zoomButton.addActionListener(new ActionListener() {
-			@Override
-			public void actionPerformed(ActionEvent arg0) {
-				if (model != null) {
-					IElevationProfile profile = model.getCurrentProfile();
-					if (profile != null) {
-						Main.map.mapView.zoomTo(profile.getBounds());
-					}
-				}
-
-			}
-		});
-		zoomButton.setEnabled(false);
-
-		trackCombo = new JComboBox<>(new TrackModel());
-		trackCombo.setPreferredSize(new Dimension(200, 24)); // HACK!
-		trackCombo.setEnabled(false); // we have no model on startup
-
-		trackPanel.add(trackCombo);
-		trackPanel.add(zoomButton);
-
-		// assemble root panel
-		rootPanel.add(statPanel);
-		rootPanel.add(trackPanel);
-
-		JPanel mainPanel = new JPanel(new BorderLayout());
-		mainPanel.add(rootPanel, BorderLayout.PAGE_END);
-
-		// add chart component
-		profPanel = new ElevationProfilePanel(null);
-		mainPanel.add(profPanel, BorderLayout.CENTER);
-		profPanel.addComponentListener(this);
-
-		createLayout(mainPanel, true, null);
-	}
-
-	@Override
-	public void showNotify() {
-		MapView.addLayerChangeListener(this);
-		if (Main.isDisplayingMapView()) {
-			Layer layer = Main.map.mapView.getActiveLayer();
-			if (layer instanceof GpxLayer) {
-				setActiveLayer((GpxLayer) layer);
-			}
-		}
-	}
-
-	@Override
-	public void hideNotify() {
-		MapView.removeLayerChangeListener(this);
-	}
-
-	/**
-	 * Gets the elevation model instance.
-	 * @return
-	 */
-	public IElevationModel getModel() {
-		return model;
-	}
-
-	/**
-	 * Sets the elevation model instance.
-	 * @param model The new model.
-	 */
-	public void setModel(IElevationModel model) {
-		if (this.model != model) {
-			this.model = model;
-			profPanel.setElevationModel(model);
-			updateView();
-		}
-	}
-
-	/**
-	 * Gets the associated layer instance of the elevation profile.
-	 * @return
-	 */
-	public ElevationProfileLayer getProfileLayer() {
-		return profileLayer;
-	}
-
-	/**
-	 * Sets the associated layer instance of the elevation profile.
-	 * @param profileLayer The elevation profile layer.
-	 */
-	public void setProfileLayer(ElevationProfileLayer profileLayer) {
-		if (this.profileLayer != profileLayer) {
-			if (this.profileLayer != null) {
-				profPanel.removeSelectionListener(this.profileLayer);
-			}
-			this.profileLayer = profileLayer;
-			profPanel.addSelectionListener(this.profileLayer);
-		}
-	}
-
-	/**
-	 * Refreshes the dialog when model data have changed and notifies clients
-	 * that the model has changed.
-	 */
-	private void updateView() {
-		if (model == null) {
-			disableView();
-			return;
-		}
-
-		IElevationProfile profile = model.getCurrentProfile();
-		if (profile != null) {
-			// Show name of profile in title
-			setTitle(String.format("%s: %s", tr("Elevation Profile"), profile.getName()));
-
-			if (profile.hasElevationData()) {
-				// Show elevation data
-				minHeightLabel.setText(
-						ElevationHelper.getElevationText(profile.getMinHeight()));
-				maxHeightLabel.setText(
-						ElevationHelper.getElevationText(profile.getMaxHeight()));
-				avrgHeightLabel.setText(
-						ElevationHelper.getElevationText(profile.getAverageHeight()));
-				elevationGainLabel.setText(
-						ElevationHelper.getElevationText(profile.getGain()));
-			}
-
-			// compute values for time and distance
-			long diff = profile.getTimeDifference();
-			long minutes = diff / (1000 * 60);
-			long hours = minutes / 60;
-			minutes = minutes % 60;
-
-			double dist = profile.getDistance();
-
-			totalTimeLabel.setText(String.format("%d:%02d h", hours, minutes));
-			distLabel.setText(SystemOfMeasurement.getSystemOfMeasurement().getDistText(dist));
-			trackCombo.setEnabled(model.profileCount() > 1);
-			trackCombo.setModel(new TrackModel());
-			zoomButton.setEnabled(true);
-		} else { // no elevation data, -> switch back to empty view
-			disableView();
-		}
-
-		fireModelChanged();
-		repaint();
-	}
-
-	private void disableView() {
-		setTitle(String.format("%s: (No data)", tr("Elevation Profile")));
-
-		minHeightLabel.setText(EMPTY_DATA_STRING);
-		maxHeightLabel.setText(EMPTY_DATA_STRING);
-		avrgHeightLabel.setText(EMPTY_DATA_STRING);
-		elevationGainLabel.setText(EMPTY_DATA_STRING);
-		totalTimeLabel.setText(EMPTY_DATA_STRING);
-		distLabel.setText(EMPTY_DATA_STRING);
-		trackCombo.setEnabled(false);
-		zoomButton.setEnabled(false);
-	}
-
-	/**
-	 * Fires the 'model changed' event to all listeners.
-	 */
-	protected void fireModelChanged() {
-		for (IElevationModelListener listener : listeners) {
-			listener.elevationProfileChanged(getModel().getCurrentProfile());
-		}
-	}
-
-	/**
-	 * Adds a model listener to this instance.
-	 *
-	 * @param listener
-	 *            The listener to add.
-	 */
-	public void addModelListener(IElevationModelListener listener) {
-		this.listeners.add(listener);
-	}
-
-	/**
-	 * Removes a model listener from this instance.
-	 *
-	 * @param listener
-	 *            The listener to remove.
-	 */
-	public void removeModelListener(IElevationModelListener listener) {
-		this.listeners.remove(listener);
-	}
-
-	/**
-	 * Removes all listeners from this instance.
-	 */
-	public void removeAllListeners() {
-		this.listeners.clear();
-	}
-
-	@Override
-	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-		if (newLayer instanceof GpxLayer) {
-			setActiveLayer((GpxLayer) newLayer);
-		}
-	}
-
-	private void setActiveLayer(GpxLayer newLayer) {
-		if (activeLayer != newLayer) {
-			activeLayer = newLayer;
-
-			// layer does not exist -> create
-			if (!layerMap.containsKey(newLayer)) {
-				GpxData gpxData = newLayer.data;
-				ElevationModel newEM = new ElevationModel(newLayer.getName(),
-						gpxData);
-				layerMap.put(newLayer, newEM);
-			}
-
-			ElevationModel em = layerMap.get(newLayer);
-			setModel(em);
-		}
-	}
-
-	@Override
-	public void layerAdded(Layer newLayer) {
-		if (newLayer instanceof GpxLayer) {
-			GpxLayer gpxLayer = (GpxLayer) newLayer;
-			setActiveLayer(gpxLayer);
-		}
-	}
-
-	@Override
-	public void layerRemoved(Layer oldLayer) {
-		if (layerMap.containsKey(oldLayer)) {
-			layerMap.remove(oldLayer);
-		}
-
-		if (layerMap.size() == 0) {
-			setModel(null);
-			if (profileLayer != null) {
-				profileLayer.setProfile(null);
-			}
-		}
-	}
-
-	@Override
-	public void componentHidden(ComponentEvent e) {
-	}
-
-	@Override
-	public void componentMoved(ComponentEvent e) {
-	}
-
-	@Override
-	public void componentResized(ComponentEvent e) {
-	}
-
-	@Override
-	public void componentShown(ComponentEvent e) {
-	}
-
-	class TrackModel implements ComboBoxModel<IElevationProfile> {
-		private Collection<ListDataListener> listeners;
-
-		@Override
-		public void addListDataListener(ListDataListener arg0) {
-			if (listeners == null) {
-				listeners = new ArrayList<>();
-			}
-			listeners.add(arg0);
-		}
-
-		@Override
-		public IElevationProfile getElementAt(int index) {
-			if (model == null) return null;
-
-			IElevationProfile ep = model.getProfiles().get(index);
-			return ep;
-		}
-
-		@Override
-		public int getSize() {
-			if (model == null) return 0;
-
-			return model.profileCount();
-		}
-
-		@Override
-		public void removeListDataListener(ListDataListener listener) {
-			if (listeners == null) return;
-
-			listeners.remove(listener);
-		}
-
-		@Override
-		public IElevationProfile getSelectedItem() {
-			if (model == null) return null;
-
-			return model.getCurrentProfile();
-		}
-
-		@Override
-		public void setSelectedItem(Object selectedObject) {
-			if (model != null && selectedObject instanceof IElevationProfile) {
-				model.setCurrentProfile((IElevationProfile) selectedObject);
-				profileLayer.setProfile(model.getCurrentProfile());
-
-				repaint();
-			}
-		}
-	}
+    private static final String EMPTY_DATA_STRING = "-";
+    private static final long serialVersionUID = -868463893732535577L;
+    /* Elevation profile instance */
+    private IElevationModel model;
+    /* GPX data */
+    private GpxLayer activeLayer = null;
+    private final HashMap<GpxLayer, ElevationModel> layerMap = new HashMap<>();
+
+    /* UI elements */
+    private final ElevationProfilePanel profPanel;
+    private final JLabel minHeightLabel;
+    private final JLabel maxHeightLabel;
+    private final JLabel avrgHeightLabel;
+    private final JLabel elevationGainLabel;
+    private final JLabel totalTimeLabel;
+    private final JLabel distLabel;
+    private final JComboBox<IElevationProfile> trackCombo;
+    private final JButton zoomButton;
+
+    /* Listener to the elevation model */
+    private final List<IElevationModelListener> listeners = new ArrayList<>();
+
+    /**
+     * Corresponding layer instance within map view.
+     */
+    private ElevationProfileLayer profileLayer;
+
+    /**
+     * Default constructor
+     */
+    public ElevationProfileDialog() {
+        this(tr("Elevation Profile"), "elevation",
+                tr("Open the elevation profile window."), null, 200, true);
+    }
+
+    /**
+     * Constructor (see below)
+     */
+    public ElevationProfileDialog(String name, String iconName, String tooltip,
+            Shortcut shortcut, int preferredHeight) {
+        this(name, iconName, tooltip, shortcut, preferredHeight, false);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param name
+     *            the name of the dialog
+     * @param iconName
+     *            the name of the icon to be displayed
+     * @param tooltip
+     *            the tool tip
+     * @param shortcut
+     *            the shortcut
+     * @param preferredHeight
+     *            the preferred height for the dialog
+     * @param defShow
+     *            if the dialog should be shown by default, if there is no
+     *            preference
+     */
+    public ElevationProfileDialog(String name, String iconName, String tooltip,
+            Shortcut shortcut, int preferredHeight, boolean defShow) {
+        super(name, iconName, tooltip, shortcut, preferredHeight, defShow);
+
+        // create model
+        model = new ElevationModel();
+
+        // top panel
+        JPanel rootPanel = new JPanel();
+        GridLayout gridLayout1 = new GridLayout(2, 1);
+        rootPanel.setLayout(gridLayout1);
+
+        // statistics panel
+        JPanel statPanel = new JPanel();
+        GridLayout gridLayoutStat = new GridLayout(2, 6);
+        statPanel.setLayout(gridLayoutStat);
+
+        // first row: Headlines with bold font
+        String[] labels = new String[]{tr("Min"), tr("Avrg"), tr("Max"), tr("Dist"), tr("Gain"), tr("Time")};
+        for (int i = 0; i < labels.length; i++) {
+            JLabel lbl = new JLabel(labels[i]);
+            lbl.setFont(getFont().deriveFont(Font.BOLD));
+            statPanel.add(lbl);
+        }
+
+        // second row
+        minHeightLabel = new JLabel("0 m");
+        statPanel.add(minHeightLabel);
+        avrgHeightLabel = new JLabel("0 m");
+        statPanel.add(avrgHeightLabel);
+        maxHeightLabel = new JLabel("0 m");
+        statPanel.add(maxHeightLabel);
+        distLabel = new JLabel("0 km");
+        statPanel.add(distLabel);
+        elevationGainLabel = new JLabel("0 m");
+        statPanel.add(elevationGainLabel);
+        totalTimeLabel = new JLabel("0");
+        statPanel.add(totalTimeLabel);
+
+        // track selection panel
+        JPanel trackPanel = new JPanel();
+        FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
+        trackPanel.setLayout(fl);
+
+        JLabel lbTrack = new JLabel(tr("Tracks"));
+        lbTrack.setFont(getFont().deriveFont(Font.BOLD));
+        trackPanel.add(lbTrack);
+
+        zoomButton = new JButton(tr("Zoom"));
+        zoomButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                if (model != null) {
+                    IElevationProfile profile = model.getCurrentProfile();
+                    if (profile != null) {
+                        Main.map.mapView.zoomTo(profile.getBounds());
+                    }
+                }
+
+            }
+        });
+        zoomButton.setEnabled(false);
+
+        trackCombo = new JComboBox<>(new TrackModel());
+        trackCombo.setPreferredSize(new Dimension(200, 24)); // HACK!
+        trackCombo.setEnabled(false); // we have no model on startup
+
+        trackPanel.add(trackCombo);
+        trackPanel.add(zoomButton);
+
+        // assemble root panel
+        rootPanel.add(statPanel);
+        rootPanel.add(trackPanel);
+
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(rootPanel, BorderLayout.PAGE_END);
+
+        // add chart component
+        profPanel = new ElevationProfilePanel(null);
+        mainPanel.add(profPanel, BorderLayout.CENTER);
+        profPanel.addComponentListener(this);
+
+        createLayout(mainPanel, true, null);
+    }
+
+    @Override
+    public void showNotify() {
+        MapView.addLayerChangeListener(this);
+        if (Main.isDisplayingMapView()) {
+            Layer layer = Main.map.mapView.getActiveLayer();
+            if (layer instanceof GpxLayer) {
+                setActiveLayer((GpxLayer) layer);
+            }
+        }
+    }
+
+    @Override
+    public void hideNotify() {
+        MapView.removeLayerChangeListener(this);
+    }
+
+    /**
+     * Gets the elevation model instance.
+     * @return
+     */
+    public IElevationModel getModel() {
+        return model;
+    }
+
+    /**
+     * Sets the elevation model instance.
+     * @param model The new model.
+     */
+    public void setModel(IElevationModel model) {
+        if (this.model != model) {
+            this.model = model;
+            profPanel.setElevationModel(model);
+            updateView();
+        }
+    }
+
+    /**
+     * Gets the associated layer instance of the elevation profile.
+     * @return
+     */
+    public ElevationProfileLayer getProfileLayer() {
+        return profileLayer;
+    }
+
+    /**
+     * Sets the associated layer instance of the elevation profile.
+     * @param profileLayer The elevation profile layer.
+     */
+    public void setProfileLayer(ElevationProfileLayer profileLayer) {
+        if (this.profileLayer != profileLayer) {
+            if (this.profileLayer != null) {
+                profPanel.removeSelectionListener(this.profileLayer);
+            }
+            this.profileLayer = profileLayer;
+            profPanel.addSelectionListener(this.profileLayer);
+        }
+    }
+
+    /**
+     * Refreshes the dialog when model data have changed and notifies clients
+     * that the model has changed.
+     */
+    private void updateView() {
+        if (model == null) {
+            disableView();
+            return;
+        }
+
+        IElevationProfile profile = model.getCurrentProfile();
+        if (profile != null) {
+            // Show name of profile in title
+            setTitle(String.format("%s: %s", tr("Elevation Profile"), profile.getName()));
+
+            if (profile.hasElevationData()) {
+                // Show elevation data
+                minHeightLabel.setText(
+                        ElevationHelper.getElevationText(profile.getMinHeight()));
+                maxHeightLabel.setText(
+                        ElevationHelper.getElevationText(profile.getMaxHeight()));
+                avrgHeightLabel.setText(
+                        ElevationHelper.getElevationText(profile.getAverageHeight()));
+                elevationGainLabel.setText(
+                        ElevationHelper.getElevationText(profile.getGain()));
+            }
+
+            // compute values for time and distance
+            long diff = profile.getTimeDifference();
+            long minutes = diff / (1000 * 60);
+            long hours = minutes / 60;
+            minutes = minutes % 60;
+
+            double dist = profile.getDistance();
+
+            totalTimeLabel.setText(String.format("%d:%02d h", hours, minutes));
+            distLabel.setText(SystemOfMeasurement.getSystemOfMeasurement().getDistText(dist));
+            trackCombo.setEnabled(model.profileCount() > 1);
+            trackCombo.setModel(new TrackModel());
+            zoomButton.setEnabled(true);
+        } else { // no elevation data, -> switch back to empty view
+            disableView();
+        }
+
+        fireModelChanged();
+        repaint();
+    }
+
+    private void disableView() {
+        setTitle(String.format("%s: (No data)", tr("Elevation Profile")));
+
+        minHeightLabel.setText(EMPTY_DATA_STRING);
+        maxHeightLabel.setText(EMPTY_DATA_STRING);
+        avrgHeightLabel.setText(EMPTY_DATA_STRING);
+        elevationGainLabel.setText(EMPTY_DATA_STRING);
+        totalTimeLabel.setText(EMPTY_DATA_STRING);
+        distLabel.setText(EMPTY_DATA_STRING);
+        trackCombo.setEnabled(false);
+        zoomButton.setEnabled(false);
+    }
+
+    /**
+     * Fires the 'model changed' event to all listeners.
+     */
+    protected void fireModelChanged() {
+        for (IElevationModelListener listener : listeners) {
+            listener.elevationProfileChanged(getModel().getCurrentProfile());
+        }
+    }
+
+    /**
+     * Adds a model listener to this instance.
+     *
+     * @param listener
+     *            The listener to add.
+     */
+    public void addModelListener(IElevationModelListener listener) {
+        this.listeners.add(listener);
+    }
+
+    /**
+     * Removes a model listener from this instance.
+     *
+     * @param listener
+     *            The listener to remove.
+     */
+    public void removeModelListener(IElevationModelListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    /**
+     * Removes all listeners from this instance.
+     */
+    public void removeAllListeners() {
+        this.listeners.clear();
+    }
+
+    @Override
+    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+        if (newLayer instanceof GpxLayer) {
+            setActiveLayer((GpxLayer) newLayer);
+        }
+    }
+
+    private void setActiveLayer(GpxLayer newLayer) {
+        if (activeLayer != newLayer) {
+            activeLayer = newLayer;
+
+            // layer does not exist -> create
+            if (!layerMap.containsKey(newLayer)) {
+                GpxData gpxData = newLayer.data;
+                ElevationModel newEM = new ElevationModel(newLayer.getName(),
+                        gpxData);
+                layerMap.put(newLayer, newEM);
+            }
+
+            ElevationModel em = layerMap.get(newLayer);
+            setModel(em);
+        }
+    }
+
+    @Override
+    public void layerAdded(Layer newLayer) {
+        if (newLayer instanceof GpxLayer) {
+            GpxLayer gpxLayer = (GpxLayer) newLayer;
+            setActiveLayer(gpxLayer);
+        }
+    }
+
+    @Override
+    public void layerRemoved(Layer oldLayer) {
+        if (layerMap.containsKey(oldLayer)) {
+            layerMap.remove(oldLayer);
+        }
+
+        if (layerMap.size() == 0) {
+            setModel(null);
+            if (profileLayer != null) {
+                profileLayer.setProfile(null);
+            }
+        }
+    }
+
+    @Override
+    public void componentHidden(ComponentEvent e) {
+    }
+
+    @Override
+    public void componentMoved(ComponentEvent e) {
+    }
+
+    @Override
+    public void componentResized(ComponentEvent e) {
+    }
+
+    @Override
+    public void componentShown(ComponentEvent e) {
+    }
+
+    class TrackModel implements ComboBoxModel<IElevationProfile> {
+        private Collection<ListDataListener> listeners;
+
+        @Override
+        public void addListDataListener(ListDataListener arg0) {
+            if (listeners == null) {
+                listeners = new ArrayList<>();
+            }
+            listeners.add(arg0);
+        }
+
+        @Override
+        public IElevationProfile getElementAt(int index) {
+            if (model == null) return null;
+
+            IElevationProfile ep = model.getProfiles().get(index);
+            return ep;
+        }
+
+        @Override
+        public int getSize() {
+            if (model == null) return 0;
+
+            return model.profileCount();
+        }
+
+        @Override
+        public void removeListDataListener(ListDataListener listener) {
+            if (listeners == null) return;
+
+            listeners.remove(listener);
+        }
+
+        @Override
+        public IElevationProfile getSelectedItem() {
+            if (model == null) return null;
+
+            return model.getCurrentProfile();
+        }
+
+        @Override
+        public void setSelectedItem(Object selectedObject) {
+            if (model != null && selectedObject instanceof IElevationProfile) {
+                model.setCurrentProfile((IElevationProfile) selectedObject);
+                profileLayer.setProfile(model.getCurrentProfile());
+
+                repaint();
+            }
+        }
+    }
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 32314)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 32315)
@@ -36,220 +36,220 @@
  */
 public class ElevationProfilePanel extends JPanel implements ComponentListener, MouseMotionListener {
-	/**
-	 * Serial version UID
-	 */
-	private static final long serialVersionUID = -7343429725259575319L;
-	private static final int BOTTOM_TEXT_Y_OFFSET = 7;
-
-	private IElevationModel model;
-	private Rectangle plotArea;
-	private final IElevationProfileRenderer renderer = new DefaultElevationProfileRenderer();
-	private int selectedIndex = -1;
-	private final List<IElevationProfileSelectionListener> selectionChangedListeners = new ArrayList<>();
-	private boolean isPainting;
-	private int step = 0;
-
-	/**
-	 * Constructs a new ElevationProfilePanel with the given elevation profile.
-	 * @param profile The elevation profile to show in the panel.
-	 */
-	public ElevationProfilePanel(IElevationModel profile) {
-		super();
-		this.model = profile;
-		setDoubleBuffered(true);
-		setBackground(Color.WHITE);
-		createOrUpdatePlotArea();
-		addComponentListener(this);
-		addMouseMotionListener(this);
-
-		Font lFont = getFont().deriveFont(9.0f);
-		setFont(lFont);
-	}
-
-	/**
-	 * Gets the elevation profile instance.
-	 * @return
-	 */
-	public IElevationModel getProfile() {
-		return model;
-	}
-
-	/**
-	 * Sets the new elevation profile instance.
-	 * @param model
-	 */
-	public void setElevationModel(IElevationModel model) {
-		if (this.model != model) {
-			this.model = model;
-			invalidate();
-		}
-	}
-
-	/**
-	 * Gets the plot area coordinates.
-	 * @return
-	 */
-	public Rectangle getPlotArea() {
-		return plotArea;
-	}
-
-	/**
-	 * Sets the plot area coordinates.
-	 * @param plotArea
-	 */
-	public void setPlotArea(Rectangle plotArea) {
-		this.plotArea = plotArea;
-	}
-
-	/**
-	 * Gets the selected index of the bar.
-	 * @return
-	 */
-	public int getSelectedIndex() {
-		return selectedIndex;
-	}
-
-	/**
-	 * Sets the selected index of the bar.
-	 * @param selectedIndex
-	 */
-	public void setSelectedIndex(int selectedIndex) {
-		this.selectedIndex = selectedIndex;
-
-		if (model != null) {
-			model.setCurrentProfile(selectedIndex);
-		}
-	}
-
-	/**
-	 * Gets the selected (highlighted) way point.
-	 * @return The selected way point or null, if no way point is selected.
-	 */
-	public WayPoint getSelectedWayPoint() {
-		if (model == null) return null;
-
-		IElevationProfile profile = model.getCurrentProfile();
-
-		int selWp = this.selectedIndex * step;
-		if (profile != null && profile.getWayPoints() != null && selWp > 0 && profile.getWayPoints().size() > selWp) {
-			return profile.getWayPoints().get(selWp);
-		} else {
-			return null;
-		}
-	}
-
-	/**
-	 * Adds a selection listener.
-	 * @param listener The listener instance to add.
-	 */
-	public void addSelectionListener(IElevationProfileSelectionListener listener) {
-		if (listener == null) return;
-
-		selectionChangedListeners.add(listener);
-	}
-
-	/**
-	 * Removes a selection listener from the list.
-	 * @param listener The listener instance to remove.
-	 */
-	public void removeSelectionListener(IElevationProfileSelectionListener listener) {
-		if (listener == null) return;
-
-		selectionChangedListeners.remove(listener);
-	}
-
-	/**
-	 * Removes all selection listeners.
-	 */
-	public void removeAllSelectionListeners() {
-		selectionChangedListeners.clear();
-	}
-
-	protected void fireSelectionChanged(WayPoint selWayPoint) {
-		for (IElevationProfileSelectionListener listener : selectionChangedListeners) {
-			listener.selectedWayPointChanged(selWayPoint);
-		}
-	}
-
-	@Override
-	public void paint(Graphics g) {
-		isPainting = true;
-
-		try {
-			super.paint(g);
-			createOrUpdatePlotArea();
-			int y1 = getPlotBottom();
-
-			g.setColor(Color.DARK_GRAY);
-			g.drawLine(plotArea.x, plotArea.y, plotArea.x, plotArea.y
-					+ plotArea.height);
-			g.drawLine(plotArea.x, plotArea.y + plotArea.height, plotArea.x
-					+ plotArea.width, plotArea.y + plotArea.height);
-
-
-			if (model != null) {
-				IElevationProfile profile = model.getCurrentProfile();
-				if (profile != null && profile.hasElevationData()) {
-					// Draw start and end date
-					drawAlignedString(formatDate(profile.getStart()), 5, y1 + BOTTOM_TEXT_Y_OFFSET,
-							TextAlignment.Left, g);
-					drawAlignedString(formatDate(profile.getEnd()),
-							getPlotRight(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Right, g);
-
-					// Show SRTM indicator
-					if (ElevationHelper.hasSrtmData(profile.getBounds())) {
-						String txt = "SRTM";
-						drawAlignedString(txt, getPlotHCenter(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Centered, g);
-					}
-					drawProfile(g);
-					drawElevationLines(g);
-				} else {
-					// No profile or profile supports no elevation data
-					drawAlignedString(tr("(No elevation data)"), getPlotHCenter(),
-							getPlotVCenter(), TextAlignment.Centered, g);
-				}
-			}
-		} finally {
-			isPainting = false;
-		}
-	}
-
-	/**
-	 * Draw a string with a specified alignment.
-	 * @param s The text to display.
-	 * @param x The x coordinate.
-	 * @param y The y coordinate.
-	 * @param align The text alignment.
-	 * @param g The graphics context.
-	 * @return The resulting rectangle of the drawn string.
-	 */
-	private Rectangle drawAlignedString(String s, int x, int y,
-			TextAlignment align, Graphics g) {
-		FontMetrics fm = g.getFontMetrics();
-		int w = fm.stringWidth(s);
-		int h = fm.getHeight();
-
-		int xoff = w / 2;
-		int yoff = h / 2;
-
-		if (align == TextAlignment.Left) {
-			xoff = 0;
-		}
-		if (align == TextAlignment.Right) {
-			xoff = w;
-		}
-
-		g.drawString(s, x - xoff, y + yoff);
-
-		return new Rectangle(x - xoff, y - yoff, w, h);
-	}
-
-	/**
-	 * Draw a string which is horizontally centered around (x,y).
-	 * @param s The text to display.
-	 * @param x The x coordinate.
-	 * @param y The y coordinate.
-	 * @param g The graphics context.
-	 * @return The resulting rectangle of the drawn string.
+    /**
+     * Serial version UID
+     */
+    private static final long serialVersionUID = -7343429725259575319L;
+    private static final int BOTTOM_TEXT_Y_OFFSET = 7;
+
+    private IElevationModel model;
+    private Rectangle plotArea;
+    private final IElevationProfileRenderer renderer = new DefaultElevationProfileRenderer();
+    private int selectedIndex = -1;
+    private final List<IElevationProfileSelectionListener> selectionChangedListeners = new ArrayList<>();
+    private boolean isPainting;
+    private int step = 0;
+
+    /**
+     * Constructs a new ElevationProfilePanel with the given elevation profile.
+     * @param profile The elevation profile to show in the panel.
+     */
+    public ElevationProfilePanel(IElevationModel profile) {
+        super();
+        this.model = profile;
+        setDoubleBuffered(true);
+        setBackground(Color.WHITE);
+        createOrUpdatePlotArea();
+        addComponentListener(this);
+        addMouseMotionListener(this);
+
+        Font lFont = getFont().deriveFont(9.0f);
+        setFont(lFont);
+    }
+
+    /**
+     * Gets the elevation profile instance.
+     * @return
+     */
+    public IElevationModel getProfile() {
+        return model;
+    }
+
+    /**
+     * Sets the new elevation profile instance.
+     * @param model
+     */
+    public void setElevationModel(IElevationModel model) {
+        if (this.model != model) {
+            this.model = model;
+            invalidate();
+        }
+    }
+
+    /**
+     * Gets the plot area coordinates.
+     * @return
+     */
+    public Rectangle getPlotArea() {
+        return plotArea;
+    }
+
+    /**
+     * Sets the plot area coordinates.
+     * @param plotArea
+     */
+    public void setPlotArea(Rectangle plotArea) {
+        this.plotArea = plotArea;
+    }
+
+    /**
+     * Gets the selected index of the bar.
+     * @return
+     */
+    public int getSelectedIndex() {
+        return selectedIndex;
+    }
+
+    /**
+     * Sets the selected index of the bar.
+     * @param selectedIndex
+     */
+    public void setSelectedIndex(int selectedIndex) {
+        this.selectedIndex = selectedIndex;
+
+        if (model != null) {
+            model.setCurrentProfile(selectedIndex);
+        }
+    }
+
+    /**
+     * Gets the selected (highlighted) way point.
+     * @return The selected way point or null, if no way point is selected.
+     */
+    public WayPoint getSelectedWayPoint() {
+        if (model == null) return null;
+
+        IElevationProfile profile = model.getCurrentProfile();
+
+        int selWp = this.selectedIndex * step;
+        if (profile != null && profile.getWayPoints() != null && selWp > 0 && profile.getWayPoints().size() > selWp) {
+            return profile.getWayPoints().get(selWp);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Adds a selection listener.
+     * @param listener The listener instance to add.
+     */
+    public void addSelectionListener(IElevationProfileSelectionListener listener) {
+        if (listener == null) return;
+
+        selectionChangedListeners.add(listener);
+    }
+
+    /**
+     * Removes a selection listener from the list.
+     * @param listener The listener instance to remove.
+     */
+    public void removeSelectionListener(IElevationProfileSelectionListener listener) {
+        if (listener == null) return;
+
+        selectionChangedListeners.remove(listener);
+    }
+
+    /**
+     * Removes all selection listeners.
+     */
+    public void removeAllSelectionListeners() {
+        selectionChangedListeners.clear();
+    }
+
+    protected void fireSelectionChanged(WayPoint selWayPoint) {
+        for (IElevationProfileSelectionListener listener : selectionChangedListeners) {
+            listener.selectedWayPointChanged(selWayPoint);
+        }
+    }
+
+    @Override
+    public void paint(Graphics g) {
+        isPainting = true;
+
+        try {
+            super.paint(g);
+            createOrUpdatePlotArea();
+            int y1 = getPlotBottom();
+
+            g.setColor(Color.DARK_GRAY);
+            g.drawLine(plotArea.x, plotArea.y, plotArea.x, plotArea.y
+                    + plotArea.height);
+            g.drawLine(plotArea.x, plotArea.y + plotArea.height, plotArea.x
+                    + plotArea.width, plotArea.y + plotArea.height);
+
+
+            if (model != null) {
+                IElevationProfile profile = model.getCurrentProfile();
+                if (profile != null && profile.hasElevationData()) {
+                    // Draw start and end date
+                    drawAlignedString(formatDate(profile.getStart()), 5, y1 + BOTTOM_TEXT_Y_OFFSET,
+                            TextAlignment.Left, g);
+                    drawAlignedString(formatDate(profile.getEnd()),
+                            getPlotRight(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Right, g);
+
+                    // Show SRTM indicator
+                    if (ElevationHelper.hasSrtmData(profile.getBounds())) {
+                        String txt = "SRTM";
+                        drawAlignedString(txt, getPlotHCenter(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Centered, g);
+                    }
+                    drawProfile(g);
+                    drawElevationLines(g);
+                } else {
+                    // No profile or profile supports no elevation data
+                    drawAlignedString(tr("(No elevation data)"), getPlotHCenter(),
+                            getPlotVCenter(), TextAlignment.Centered, g);
+                }
+            }
+        } finally {
+            isPainting = false;
+        }
+    }
+
+    /**
+     * Draw a string with a specified alignment.
+     * @param s The text to display.
+     * @param x The x coordinate.
+     * @param y The y coordinate.
+     * @param align The text alignment.
+     * @param g The graphics context.
+     * @return The resulting rectangle of the drawn string.
+     */
+    private Rectangle drawAlignedString(String s, int x, int y,
+            TextAlignment align, Graphics g) {
+        FontMetrics fm = g.getFontMetrics();
+        int w = fm.stringWidth(s);
+        int h = fm.getHeight();
+
+        int xoff = w / 2;
+        int yoff = h / 2;
+
+        if (align == TextAlignment.Left) {
+            xoff = 0;
+        }
+        if (align == TextAlignment.Right) {
+            xoff = w;
+        }
+
+        g.drawString(s, x - xoff, y + yoff);
+
+        return new Rectangle(x - xoff, y - yoff, w, h);
+    }
+
+    /**
+     * Draw a string which is horizontally centered around (x,y).
+     * @param s The text to display.
+     * @param x The x coordinate.
+     * @param y The y coordinate.
+     * @param g The graphics context.
+     * @return The resulting rectangle of the drawn string.
 
     private void drawHCenteredString(String s, int x, int y, Graphics g) {
@@ -257,262 +257,262 @@
     }*/
 
-	/**
-	 * Formats the date in a predefined manner: "21. Oct 2010, 12:10".
-	 * @param date
-	 * @return
-	 */
-	private String formatDate(Date date) {
-		Format formatter = new SimpleDateFormat("d MMM yy, HH:mm");
-
-		return formatter.format(date);
-	}
-
-	/**
-	 * Helper function to draw elevation axes.
-	 * @param g
-	 */
-	private void drawElevationLines(Graphics g) {
-		IElevationProfile profile = model.getCurrentProfile();
-
-		double diff = profile.getHeightDifference();
-
-		if (diff == 0.0) {
-			return;
-		}
-
-		double z10 = Math.floor(Math.log10(diff));
-		double scaleUnit = Math.pow(10, z10); // scale unit, e. g. 100 for
-		// values below 1000
-
-		int upperLimit = (int) (Math.round(Math.ceil(profile.getMaxHeight()
-				/ scaleUnit)) * scaleUnit);
-		int lowerLimit = (int) (Math.round(Math.floor(profile.getMinHeight()
-				/ scaleUnit)) * scaleUnit);
-		int su = (int) scaleUnit;
-
-		for (int i = lowerLimit; i <= upperLimit; i += su) {
-			int yLine = getYForEelevation(i);
-
-			// check bounds
-			if (yLine <= getPlotBottom() && yLine >= getPlotTop()) {
-				String txt = ElevationHelper.getElevationText(i);
-
-				Rectangle r = drawAlignedString(txt, getPlotHCenter(), yLine - 2,
-						TextAlignment.Right, g);
-				r.grow(2, 2);
-
-				// Draw left and right line segment
-				g.drawLine(getPlotLeftAxis(), yLine, r.x,
-						yLine);
-				g.drawLine(r.x + r.width, yLine, getPlotRight(),
-						yLine);
-				// Draw label with shadow
-				g.setColor(Color.WHITE);
-				drawAlignedString(txt, getPlotHCenter() + 1, yLine - 1,
-						TextAlignment.Right, g);
-				g.setColor(Color.BLACK);
-				drawAlignedString(txt, getPlotHCenter(), yLine - 2,
-						TextAlignment.Right, g);
-			}
-		}
-	}
-
-	/**
-	 * Gets the x value of the left border for axes (slightly smaller than the
-	 * left x).
-	 *
-	 * @return
-	 */
-	private int getPlotLeftAxis() {
-		return plotArea.x - 3;
-	}
-
-	/**
-	 * Gets the x value of the left border.
-	 *
-	 * @return
-	 */
-	private int getPlotLeft() {
-		return plotArea.x + 1;
-	}
-
-	/**
-	 * Gets the horizontal center coordinate (mid between left and right x).
-	 *
-	 * @return
-	 */
-	private int getPlotHCenter() {
-		return (getPlotLeft() + getPlotRight()) / 2;
-	}
-
-	/**
-	 * Gets the vertical center coordinate (mid between top and bottom y).
-	 *
-	 * @return
-	 */
-	private int getPlotVCenter() {
-		return (getPlotTop() + getPlotBottom()) / 2;
-	}
-
-	/**
-	 * Gets the x value of the right border.
-	 *
-	 * @return
-	 */
-	private int getPlotRight() {
-		return plotArea.x + plotArea.width - 1;
-	}
-
-	private int getPlotBottom() {
-		return plotArea.y + plotArea.height - 1;
-	}
-
-	private int getPlotTop() {
-		return plotArea.y + 1;
-	}
-
-	/**
-	 * Gets for an elevation value the according y coordinate in the plot area.
-	 *
-	 * @param elevation
-	 * @return The y coordinate in the plot area.
-	 */
-	private int getYForEelevation(int elevation) {
-		int y1 = getPlotBottom();
-
-		IElevationProfile profile = model.getCurrentProfile();
-
-		if (!profile.hasElevationData()) {
-			return y1;
-		}
-
-		double diff = profile.getHeightDifference();
-
-		return y1 - (int) Math.round(((elevation - profile.getMinHeight()) / diff * plotArea.height));
-	}
-
-	/**
-	 * Draws the elevation profile
-	 *
-	 * @param g
-	 */
-	private void drawProfile(Graphics g) {
-		IElevationProfile profile = model.getCurrentProfile();
-
-		int nwp = profile.getNumberOfWayPoints();
-		int n = Math.min(plotArea.width, nwp);
-
-		if (n == 0) return; // nothing to draw
-		// compute step size in panel (add 1 to make sure that
-		// the complete range fits into panel
-		step = (nwp / n) + 1;
-
-		int yBottom = getPlotBottom();
-		Color oldC = g.getColor();
-
-		for (int i = 0, ip = 0; i < n && ip < nwp; i++, ip += step) {
-			WayPoint wpt = profile.getWayPoints().get(ip);
-			int eleVal = (int) ElevationHelper.getElevation(wpt);
-			Color c = renderer.getColorForWaypoint(profile, wpt,
-					ElevationWayPointKind.Plain);
-
-			// draw cursor
-			if (i == this.selectedIndex) {
-				g.setColor(Color.BLACK);
-				drawAlignedString(ElevationHelper.getElevationText(eleVal),
-						(getPlotRight() + getPlotLeft()) / 2,
-						getPlotBottom() + 6,
-						TextAlignment.Centered,
-						g);
-
-				c = renderer.getColorForWaypoint(profile, wpt, ElevationWayPointKind.Highlighted);
-			}
-
-			int yEle = getYForEelevation(eleVal);
-			int x = getPlotLeft() + i;
-
-			g.setColor(c);
-			g.drawLine(x, yBottom, x, yEle);
-			g.setColor(ElevationColors.EPLightBlue);
-		}
-
-		g.setColor(oldC);
-	}
-
-	@Override
-	protected void paintBorder(Graphics g) {
-		super.paintBorder(g);
-
-		Border loweredbevel = BorderFactory.createLoweredBevelBorder();
-		this.setBorder(loweredbevel);
-	}
-
-	/**
-	 * Determines the size of the plot area depending on the panel size.
-	 */
-	private void createOrUpdatePlotArea() {
-		Dimension caSize = getSize();
-
-		if (plotArea == null) {
-			plotArea = new Rectangle(0, 0, caSize.width, caSize.height);
-		} else {
-			plotArea.width = caSize.width;
-			plotArea.height = caSize.height;
-		}
-
-		plotArea.setLocation(0, 0);
-		plotArea.grow(-10, -15);
-	}
-
-	@Override
-	public void componentHidden(ComponentEvent arg0) {
-		// TODO Auto-generated method stub
-	}
-
-	@Override
-	public void componentMoved(ComponentEvent arg0) {
-		// TODO Auto-generated method stub
-	}
-
-	@Override
-	public void componentResized(ComponentEvent arg0) {
-		createOrUpdatePlotArea();
-	}
-
-	@Override
-	public void componentShown(ComponentEvent arg0) {
-		// TODO Auto-generated method stub
-	}
-
-	@Override
-	public void mouseDragged(MouseEvent arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public void mouseMoved(MouseEvent arg0) {
-		if (isPainting || arg0.isControlDown() || arg0.isAltDown() || arg0.isShiftDown()) arg0.consume();
-
-		int x = arg0.getX();
-		int l = this.getX();
-		int pl = this.getPlotLeft();
-		int newIdx = x - l - pl;
-
-		if (newIdx != this.selectedIndex && newIdx >= 0) {
-			this.selectedIndex = newIdx;
-			this.repaint();
-			fireSelectionChanged(getSelectedWayPoint());
-		}
-	}
-
-	@Override
-	public String getToolTipText() {
-		WayPoint wpt = getSelectedWayPoint();
-		if (wpt != null) {
-			return  String.format("%s: %s", ElevationHelper.getTimeText(wpt), ElevationHelper.getElevationText(wpt));
-		}
-
-		return super.getToolTipText();
-	}
+    /**
+     * Formats the date in a predefined manner: "21. Oct 2010, 12:10".
+     * @param date
+     * @return
+     */
+    private String formatDate(Date date) {
+        Format formatter = new SimpleDateFormat("d MMM yy, HH:mm");
+
+        return formatter.format(date);
+    }
+
+    /**
+     * Helper function to draw elevation axes.
+     * @param g
+     */
+    private void drawElevationLines(Graphics g) {
+        IElevationProfile profile = model.getCurrentProfile();
+
+        double diff = profile.getHeightDifference();
+
+        if (diff == 0.0) {
+            return;
+        }
+
+        double z10 = Math.floor(Math.log10(diff));
+        double scaleUnit = Math.pow(10, z10); // scale unit, e. g. 100 for
+        // values below 1000
+
+        int upperLimit = (int) (Math.round(Math.ceil(profile.getMaxHeight()
+                / scaleUnit)) * scaleUnit);
+        int lowerLimit = (int) (Math.round(Math.floor(profile.getMinHeight()
+                / scaleUnit)) * scaleUnit);
+        int su = (int) scaleUnit;
+
+        for (int i = lowerLimit; i <= upperLimit; i += su) {
+            int yLine = getYForEelevation(i);
+
+            // check bounds
+            if (yLine <= getPlotBottom() && yLine >= getPlotTop()) {
+                String txt = ElevationHelper.getElevationText(i);
+
+                Rectangle r = drawAlignedString(txt, getPlotHCenter(), yLine - 2,
+                        TextAlignment.Right, g);
+                r.grow(2, 2);
+
+                // Draw left and right line segment
+                g.drawLine(getPlotLeftAxis(), yLine, r.x,
+                        yLine);
+                g.drawLine(r.x + r.width, yLine, getPlotRight(),
+                        yLine);
+                // Draw label with shadow
+                g.setColor(Color.WHITE);
+                drawAlignedString(txt, getPlotHCenter() + 1, yLine - 1,
+                        TextAlignment.Right, g);
+                g.setColor(Color.BLACK);
+                drawAlignedString(txt, getPlotHCenter(), yLine - 2,
+                        TextAlignment.Right, g);
+            }
+        }
+    }
+
+    /**
+     * Gets the x value of the left border for axes (slightly smaller than the
+     * left x).
+     *
+     * @return
+     */
+    private int getPlotLeftAxis() {
+        return plotArea.x - 3;
+    }
+
+    /**
+     * Gets the x value of the left border.
+     *
+     * @return
+     */
+    private int getPlotLeft() {
+        return plotArea.x + 1;
+    }
+
+    /**
+     * Gets the horizontal center coordinate (mid between left and right x).
+     *
+     * @return
+     */
+    private int getPlotHCenter() {
+        return (getPlotLeft() + getPlotRight()) / 2;
+    }
+
+    /**
+     * Gets the vertical center coordinate (mid between top and bottom y).
+     *
+     * @return
+     */
+    private int getPlotVCenter() {
+        return (getPlotTop() + getPlotBottom()) / 2;
+    }
+
+    /**
+     * Gets the x value of the right border.
+     *
+     * @return
+     */
+    private int getPlotRight() {
+        return plotArea.x + plotArea.width - 1;
+    }
+
+    private int getPlotBottom() {
+        return plotArea.y + plotArea.height - 1;
+    }
+
+    private int getPlotTop() {
+        return plotArea.y + 1;
+    }
+
+    /**
+     * Gets for an elevation value the according y coordinate in the plot area.
+     *
+     * @param elevation
+     * @return The y coordinate in the plot area.
+     */
+    private int getYForEelevation(int elevation) {
+        int y1 = getPlotBottom();
+
+        IElevationProfile profile = model.getCurrentProfile();
+
+        if (!profile.hasElevationData()) {
+            return y1;
+        }
+
+        double diff = profile.getHeightDifference();
+
+        return y1 - (int) Math.round(((elevation - profile.getMinHeight()) / diff * plotArea.height));
+    }
+
+    /**
+     * Draws the elevation profile
+     *
+     * @param g
+     */
+    private void drawProfile(Graphics g) {
+        IElevationProfile profile = model.getCurrentProfile();
+
+        int nwp = profile.getNumberOfWayPoints();
+        int n = Math.min(plotArea.width, nwp);
+
+        if (n == 0) return; // nothing to draw
+        // compute step size in panel (add 1 to make sure that
+        // the complete range fits into panel
+        step = (nwp / n) + 1;
+
+        int yBottom = getPlotBottom();
+        Color oldC = g.getColor();
+
+        for (int i = 0, ip = 0; i < n && ip < nwp; i++, ip += step) {
+            WayPoint wpt = profile.getWayPoints().get(ip);
+            int eleVal = (int) ElevationHelper.getElevation(wpt);
+            Color c = renderer.getColorForWaypoint(profile, wpt,
+                    ElevationWayPointKind.Plain);
+
+            // draw cursor
+            if (i == this.selectedIndex) {
+                g.setColor(Color.BLACK);
+                drawAlignedString(ElevationHelper.getElevationText(eleVal),
+                        (getPlotRight() + getPlotLeft()) / 2,
+                        getPlotBottom() + 6,
+                        TextAlignment.Centered,
+                        g);
+
+                c = renderer.getColorForWaypoint(profile, wpt, ElevationWayPointKind.Highlighted);
+            }
+
+            int yEle = getYForEelevation(eleVal);
+            int x = getPlotLeft() + i;
+
+            g.setColor(c);
+            g.drawLine(x, yBottom, x, yEle);
+            g.setColor(ElevationColors.EPLightBlue);
+        }
+
+        g.setColor(oldC);
+    }
+
+    @Override
+    protected void paintBorder(Graphics g) {
+        super.paintBorder(g);
+
+        Border loweredbevel = BorderFactory.createLoweredBevelBorder();
+        this.setBorder(loweredbevel);
+    }
+
+    /**
+     * Determines the size of the plot area depending on the panel size.
+     */
+    private void createOrUpdatePlotArea() {
+        Dimension caSize = getSize();
+
+        if (plotArea == null) {
+            plotArea = new Rectangle(0, 0, caSize.width, caSize.height);
+        } else {
+            plotArea.width = caSize.width;
+            plotArea.height = caSize.height;
+        }
+
+        plotArea.setLocation(0, 0);
+        plotArea.grow(-10, -15);
+    }
+
+    @Override
+    public void componentHidden(ComponentEvent arg0) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void componentMoved(ComponentEvent arg0) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void componentResized(ComponentEvent arg0) {
+        createOrUpdatePlotArea();
+    }
+
+    @Override
+    public void componentShown(ComponentEvent arg0) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent arg0) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent arg0) {
+        if (isPainting || arg0.isControlDown() || arg0.isAltDown() || arg0.isShiftDown()) arg0.consume();
+
+        int x = arg0.getX();
+        int l = this.getX();
+        int pl = this.getPlotLeft();
+        int newIdx = x - l - pl;
+
+        if (newIdx != this.selectedIndex && newIdx >= 0) {
+            this.selectedIndex = newIdx;
+            this.repaint();
+            fireSelectionChanged(getSelectedWayPoint());
+        }
+    }
+
+    @Override
+    public String getToolTipText() {
+        WayPoint wpt = getSelectedWayPoint();
+        if (wpt != null) {
+            return  String.format("%s: %s", ElevationHelper.getTimeText(wpt), ElevationHelper.getElevationText(wpt));
+        }
+
+        return super.getToolTipText();
+    }
 }
