[jmapviewer] 03/06: Imported Upstream version 1.05+dfsg

Bas Couwenberg sebastic at xs4all.nl
Mon Dec 29 21:06:06 UTC 2014


This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch master
in repository jmapviewer.

commit e97508c9202e16540cde965fa75b4ca31697c74c
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Mon Dec 29 21:37:04 2014 +0100

    Imported Upstream version 1.05+dfsg
---
 src/org/openstreetmap/gui/jmapviewer/Demo.java     |  16 +-
 .../gui/jmapviewer/FeatureAdapter.java             |  21 +++
 .../openstreetmap/gui/jmapviewer/JMapViewer.java   | 174 +++++++++++---------
 .../gui/jmapviewer/MemoryTileCache.java            |   7 +-
 .../gui/jmapviewer/OsmFileCacheTileLoader.java     | 178 +++++++++++----------
 .../gui/jmapviewer/OsmTileLoader.java              |   6 +-
 .../gui/jmapviewer/TMSFileCacheTileLoader.java     |  76 +++++++++
 src/org/openstreetmap/gui/jmapviewer/Tile.java     |  55 ++++---
 .../gui/jmapviewer/TileController.java             |   9 +-
 .../gui/jmapviewer/interfaces/TileCache.java       |   5 +
 .../jmapviewer/interfaces/TileLoaderListener.java  |  11 +-
 .../gui/jmapviewer/interfaces/TileSource.java      |  13 +-
 .../tilesources/AbstractMapQuestTileSource.java    |   4 +-
 .../tilesources/AbstractOsmTileSource.java         |   6 +-
 .../tilesources/AbstractTMSTileSource.java         |   9 +-
 .../tilesources/BingAerialTileSource.java          |   9 +-
 .../tilesources/MapQuestOpenAerialTileSource.java  |   2 +-
 .../tilesources/MapQuestOsmTileSource.java         |   2 +-
 .../gui/jmapviewer/tilesources/OsmTileSource.java  |   4 +-
 .../jmapviewer/tilesources/ScanexTileSource.java   |   4 +-
 .../gui/jmapviewer/tilesources/TMSTileSource.java  |   9 +-
 .../tilesources/TemplatedTMSTileSource.java        |   8 +-
 22 files changed, 390 insertions(+), 238 deletions(-)

diff --git a/src/org/openstreetmap/gui/jmapviewer/Demo.java b/src/org/openstreetmap/gui/jmapviewer/Demo.java
index d6ae3e8..57ee480 100644
--- a/src/org/openstreetmap/gui/jmapviewer/Demo.java
+++ b/src/org/openstreetmap/gui/jmapviewer/Demo.java
@@ -57,13 +57,9 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
         treeMap = new JMapViewerTree("Zones");
 
         // Listen to the map viewer for user operations so components will
-        // recieve events and update
+        // receive events and update
         map().addJMVListener(this);
 
-        // final JMapViewer map = new JMapViewer(new MemoryTileCache(),4);
-        // map.setTileLoader(new OsmFileCacheTileLoader(map));
-        // new DefaultMapController(map);
-
         setLayout(new BorderLayout());
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setExtendedState(JFrame.MAXIMIZED_BOTH);
@@ -93,8 +89,12 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
                 map().setDisplayToFitMapMarkers();
             }
         });
-        JComboBox<TileSource> tileSourceSelector = new JComboBox<>(new TileSource[] { new OsmTileSource.Mapnik(),
-                new OsmTileSource.CycleMap(), new BingAerialTileSource(), new MapQuestOsmTileSource(), new MapQuestOpenAerialTileSource() });
+        JComboBox<TileSource> tileSourceSelector = new JComboBox<>(new TileSource[] {
+                new OsmTileSource.Mapnik(),
+                new OsmTileSource.CycleMap(),
+                new BingAerialTileSource(),
+                new MapQuestOsmTileSource(),
+                new MapQuestOpenAerialTileSource() });
         tileSourceSelector.addItemListener(new ItemListener() {
             public void itemStateChanged(ItemEvent e) {
                 map().setTileSource((TileSource) e.getItem());
@@ -148,7 +148,7 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
         });
         panelBottom.add(showTileGrid);
         final JCheckBox showZoomControls = new JCheckBox("Show zoom controls");
-        showZoomControls.setSelected(map().getZoomContolsVisible());
+        showZoomControls.setSelected(map().getZoomControlsVisible());
         showZoomControls.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                 map().setZoomContolsVisible(showZoomControls.isSelected());
diff --git a/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java b/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
index 24245f9..c048e44 100644
--- a/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
+++ b/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
@@ -6,6 +6,7 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.text.MessageFormat;
+import java.util.logging.Logger;
 
 public class FeatureAdapter {
 
@@ -18,8 +19,13 @@ public class FeatureAdapter {
         // TODO: more i18n functions
     }
 
+    public static interface LoggingAdapter {
+        Logger getLogger(String name);
+    }
+
     private static BrowserAdapter browserAdapter = new DefaultBrowserAdapter();
     private static TranslationAdapter translationAdapter = new DefaultTranslationAdapter();
+    private static LoggingAdapter loggingAdapter = new DefaultLoggingAdapter();
 
     public static void registerBrowserAdapter(BrowserAdapter browserAdapter) {
         FeatureAdapter.browserAdapter = browserAdapter;
@@ -29,6 +35,10 @@ public class FeatureAdapter {
         FeatureAdapter.translationAdapter = translationAdapter;
     }
 
+    public static void registerLoggingAdapter(LoggingAdapter loggingAdapter) {
+        FeatureAdapter.loggingAdapter = loggingAdapter;
+    }
+
     public static void openLink(String url) {
         browserAdapter.openLink(url);
     }
@@ -36,6 +46,10 @@ public class FeatureAdapter {
     public static String tr(String text, Object... objects) {
         return translationAdapter.tr(text, objects);
     }
+    
+    public static Logger getLogger(String name) {
+        return loggingAdapter.getLogger(name);
+    }
 
     public static class DefaultBrowserAdapter implements BrowserAdapter {
         @Override
@@ -60,4 +74,11 @@ public class FeatureAdapter {
             return MessageFormat.format(text, objects);
         }
     }
+
+    public static class DefaultLoggingAdapter implements LoggingAdapter {
+        @Override
+        public Logger getLogger(String name) {
+            return Logger.getLogger(name);
+        }
+    }
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java b/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
index f1ddc06..6ccbe2e 100644
--- a/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
+++ b/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
@@ -9,6 +9,7 @@ import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -84,6 +85,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         HORIZONTAL,
         VERTICAL
     }
+
     protected ZOOM_BUTTON_STYLE zoomButtonStyle;
 
     protected TileSource tileSource;
@@ -93,24 +95,27 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     /**
      * Creates a standard {@link JMapViewer} instance that can be controlled via
      * mouse: hold right mouse button for moving, double click left mouse button
-     * or use mouse wheel for zooming. Loaded tiles are stored the
+     * or use mouse wheel for zooming. Loaded tiles are stored in a
      * {@link MemoryTileCache} and the tile loader uses 4 parallel threads for
      * retrieving the tiles.
      */
-    @SuppressWarnings("unused")
     public JMapViewer() {
         this(new MemoryTileCache(), 8);
         new DefaultMapController(this);
     }
 
+    /**
+     * Creates a new {@link JMapViewer} instance.
+     * @param tileCache The cache where to store tiles
+     * @param downloadThreadCount The number of parallel threads for retrieving the tiles
+     */
     public JMapViewer(TileCache tileCache, int downloadThreadCount) {
-        super();
         JobDispatcher.setMaxWorkers(downloadThreadCount);
         tileSource = new OsmTileSource.Mapnik();
         tileController = new TileController(tileSource, tileCache, this);
-        mapMarkerList = new LinkedList<>();
-        mapPolygonList = new LinkedList<>();
-        mapRectangleList = new LinkedList<>();
+        mapMarkerList = Collections.synchronizedList(new LinkedList<MapMarker>());
+        mapPolygonList = Collections.synchronizedList(new LinkedList<MapPolygon>());
+        mapRectangleList = Collections.synchronizedList(new LinkedList<MapRectangle>());
         mapMarkersVisible = true;
         mapRectanglesVisible = true;
         mapPolygonsVisible = true;
@@ -120,13 +125,10 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         setMinimumSize(new Dimension(tileSource.getTileSize(), tileSource.getTileSize()));
         setPreferredSize(new Dimension(400, 400));
         setDisplayPosition(new Coordinate(50, 9), 3);
-        //setToolTipText("");
     }
 
     @Override
     public String getToolTipText(MouseEvent event) {
-        //        Point screenPoint = event.getLocationOnScreen();
-        //        Coordinate c = getPosition(screenPoint);
         return super.getToolTipText(event);
     }
 
@@ -242,8 +244,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     }
 
     /**
-     * Sets the displayed map pane and zoom level so that all chosen map elements are
-     * visible.
+     * Sets the displayed map pane and zoom level so that all chosen map elements are visible.
      */
     public void setDisplayToFitMapElements(boolean markers, boolean rectangles, boolean polygons) {
         int nbElemToCheck = 0;
@@ -263,39 +264,45 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         int mapZoomMax = tileController.getTileSource().getMaxZoom();
 
         if (markers) {
-            for (MapMarker marker : mapMarkerList) {
-                if(marker.isVisible()){
-                    int x = tileSource.LonToX(marker.getLon(), mapZoomMax);
-                    int y = tileSource.LatToY(marker.getLat(), mapZoomMax);
-                    x_max = Math.max(x_max, x);
-                    y_max = Math.max(y_max, y);
-                    x_min = Math.min(x_min, x);
-                    y_min = Math.min(y_min, y);
+            synchronized (mapMarkerList) {
+                for (MapMarker marker : mapMarkerList) {
+                    if (marker.isVisible()) {
+                        int x = tileSource.LonToX(marker.getLon(), mapZoomMax);
+                        int y = tileSource.LatToY(marker.getLat(), mapZoomMax);
+                        x_max = Math.max(x_max, x);
+                        y_max = Math.max(y_max, y);
+                        x_min = Math.min(x_min, x);
+                        y_min = Math.min(y_min, y);
+                    }
                 }
             }
         }
 
         if (rectangles) {
-            for (MapRectangle rectangle : mapRectangleList) {
-                if(rectangle.isVisible()){
-                    x_max = Math.max(x_max, tileSource.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
-                    y_max = Math.max(y_max, tileSource.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
-                    x_min = Math.min(x_min, tileSource.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
-                    y_min = Math.min(y_min, tileSource.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
+            synchronized (mapRectangleList) {
+                for (MapRectangle rectangle : mapRectangleList) {
+                    if (rectangle.isVisible()) {
+                        x_max = Math.max(x_max, tileSource.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
+                        y_max = Math.max(y_max, tileSource.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
+                        x_min = Math.min(x_min, tileSource.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
+                        y_min = Math.min(y_min, tileSource.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
+                    }
                 }
             }
         }
 
         if (polygons) {
-            for (MapPolygon polygon : mapPolygonList) {
-                if(polygon.isVisible()){
-                    for (ICoordinate c : polygon.getPoints()) {
-                        int x = tileSource.LonToX(c.getLon(), mapZoomMax);
-                        int y = tileSource.LatToY(c.getLat(), mapZoomMax);
-                        x_max = Math.max(x_max, x);
-                        y_max = Math.max(y_max, y);
-                        x_min = Math.min(x_min, x);
-                        y_min = Math.min(y_min, y);
+            synchronized (mapPolygonList) {
+                for (MapPolygon polygon : mapPolygonList) {
+                    if (polygon.isVisible()) {
+                        for (ICoordinate c : polygon.getPoints()) {
+                            int x = tileSource.LonToX(c.getLon(), mapZoomMax);
+                            int y = tileSource.LatToY(c.getLat(), mapZoomMax);
+                            x_max = Math.max(x_max, x);
+                            y_max = Math.max(y_max, y);
+                            x_min = Math.min(x_min, x);
+                            y_min = Math.min(y_min, y);
+                        }
                     }
                 }
             }
@@ -319,26 +326,22 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         setDisplayPosition(x, y, newZoom);
     }
 
-
     /**
-     * Sets the displayed map pane and zoom level so that all map markers are
-     * visible.
+     * Sets the displayed map pane and zoom level so that all map markers are visible.
      */
     public void setDisplayToFitMapMarkers() {
         setDisplayToFitMapElements(true, false, false);
     }
 
     /**
-     * Sets the displayed map pane and zoom level so that all map rectangles are
-     * visible.
+     * Sets the displayed map pane and zoom level so that all map rectangles are visible.
      */
     public void setDisplayToFitMapRectangles() {
         setDisplayToFitMapElements(false, true, false);
     }
 
     /**
-     * Sets the displayed map pane and zoom level so that all map polygons are
-     * visible.
+     * Sets the displayed map pane and zoom level so that all map polygons are visible.
      */
     public void setDisplayToFitMapPolygons() {
         setDisplayToFitMapElements(false, false, true);
@@ -429,7 +432,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * @return Integer the radius in pixels
      */
     public Integer getLatOffset(double lat, double offset, boolean checkOutside) {
-        int y = tileSource.LatToY(lat+offset, zoom);
+        int y = tileSource.LatToY(lat + offset, zoom);
         y -= center.y - getHeight() / 2;
         if (checkOutside) {
             if (y < 0 || y > getHeight())
@@ -456,13 +459,14 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * @return Integer the radius in pixels
      */
     public Integer getRadius(MapMarker marker, Point p) {
-        if(marker.getMarkerStyle() == MapMarker.STYLE.FIXED)
-            return (int)marker.getRadius();
-        else if(p!=null){
+        if (marker.getMarkerStyle() == MapMarker.STYLE.FIXED)
+            return (int) marker.getRadius();
+        else if (p != null) {
             Integer radius = getLatOffset(marker.getLat(), marker.getRadius(), false);
-            radius = radius==null?null:p.y-radius.intValue();
+            radius = radius == null ? null : p.y - radius.intValue();
             return radius;
-        }else return null;
+        } else
+            return null;
     }
 
     /**
@@ -499,18 +503,18 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * @author Jason Huntley
      */
     public double getMeterPerPixel() {
-        Point origin=new Point(5,5);
-        Point center=new Point(getWidth()/2, getHeight()/2);
+        Point origin = new Point(5, 5);
+        Point center = new Point(getWidth() / 2, getHeight() / 2);
 
-        double pDistance=center.distance(origin);
+        double pDistance = center.distance(origin);
 
-        Coordinate originCoord=getPosition(origin);
-        Coordinate centerCoord=getPosition(center);
+        Coordinate originCoord = getPosition(origin);
+        Coordinate centerCoord = getPosition(center);
 
         double mDistance = tileSource.getDistance(originCoord.getLat(), originCoord.getLon(),
                 centerCoord.getLat(), centerCoord.getLon());
 
-        return mDistance/pDistance;
+        return mDistance / pDistance;
     }
 
     @Override
@@ -613,20 +617,29 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         }
 
         if (mapPolygonsVisible && mapPolygonList != null) {
-            for (MapPolygon polygon : mapPolygonList) {
-                if(polygon.isVisible()) paintPolygon(g, polygon);
+            synchronized (mapPolygonList) {
+                for (MapPolygon polygon : mapPolygonList) {
+                    if (polygon.isVisible())
+                        paintPolygon(g, polygon);
+                }
             }
         }
 
         if (mapRectanglesVisible && mapRectangleList != null) {
-            for (MapRectangle rectangle : mapRectangleList) {
-                if(rectangle.isVisible()) paintRectangle(g, rectangle);
+            synchronized (mapRectangleList) {
+                for (MapRectangle rectangle : mapRectangleList) {
+                    if (rectangle.isVisible())
+                        paintRectangle(g, rectangle);
+                }
             }
         }
 
         if (mapMarkersVisible && mapMarkerList != null) {
-            for (MapMarker marker : mapMarkerList) {
-                if(marker.isVisible())paintMarker(g, marker);
+            synchronized (mapMarkerList) {
+                for (MapMarker marker : mapMarkerList) {
+                    if (marker.isVisible())
+                        paintMarker(g, marker);
+                }
             }
         }
 
@@ -637,7 +650,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * Paint a single marker.
      */
     protected void paintMarker(Graphics g, MapMarker marker) {
-        Point p = getMapPosition(marker.getLat(), marker.getLon(), marker.getMarkerStyle()==MapMarker.STYLE.FIXED);
+        Point p = getMapPosition(marker.getLat(), marker.getLon(), marker.getMarkerStyle() == MapMarker.STYLE.FIXED);
         Integer radius = getRadius(marker, p);
         if (scrollWrapEnabled) {
             int tilesize = tileSource.getTileSize();
@@ -780,6 +793,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
 
     /**
      * Increases the current zoom level by one
+     * @param mapPoint point to choose as center for new zoom level
      */
     public void zoomIn(Point mapPoint) {
         setZoom(zoom + 1, mapPoint);
@@ -947,7 +961,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         zoomOutButton.setVisible(visible);
     }
 
-    public boolean getZoomContolsVisible() {
+    public boolean getZoomControlsVisible() {
         return zoomSlider.isVisible();
     }
 
@@ -955,7 +969,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         if (tileSource.getMaxZoom() > MAX_ZOOM)
             throw new RuntimeException("Maximum zoom level too high");
         if (tileSource.getMinZoom() < MIN_ZOOM)
-            throw new RuntimeException("Minumim zoom level too low");
+            throw new RuntimeException("Minimum zoom level too low");
         Coordinate position = getPosition();
         this.tileSource = tileSource;
         tileController.setTileSource(tileSource);
@@ -1025,21 +1039,21 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
             return;
         }
         switch (style) {
-            case HORIZONTAL:
-                zoomSlider.setBounds(10, 10, 30, 150);
-                zoomInButton.setBounds(4, 155, 18, 18);
-                zoomOutButton.setBounds(26, 155, 18, 18);
-                break;
-            case VERTICAL:
-                zoomSlider.setBounds(10, 27, 30, 150);
-                zoomInButton.setBounds(14, 8, 20, 20);
-                zoomOutButton.setBounds(14, 176, 20, 20);
-                break;
-            default:
-                zoomSlider.setBounds(10, 10, 30, 150);
-                zoomInButton.setBounds(4, 155, 18, 18);
-                zoomOutButton.setBounds(26, 155, 18, 18);
-                break;
+        case HORIZONTAL:
+            zoomSlider.setBounds(10, 10, 30, 150);
+            zoomInButton.setBounds(4, 155, 18, 18);
+            zoomOutButton.setBounds(26, 155, 18, 18);
+            break;
+        case VERTICAL:
+            zoomSlider.setBounds(10, 27, 30, 150);
+            zoomInButton.setBounds(14, 8, 20, 20);
+            zoomOutButton.setBounds(14, 176, 20, 20);
+            break;
+        default:
+            zoomSlider.setBounds(10, 10, 30, 150);
+            zoomInButton.setBounds(4, 155, 18, 18);
+            zoomOutButton.setBounds(26, 155, 18, 18);
+            break;
         }
         repaint();
     }
@@ -1087,9 +1101,9 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      */
     void fireJMVEvent(JMVCommandEvent evt) {
         Object[] listeners = evtListenerList.getListenerList();
-        for (int i=0; i<listeners.length; i+=2) {
-            if (listeners[i]==JMapViewerEventListener.class) {
-                ((JMapViewerEventListener)listeners[i+1]).processCommand(evt);
+        for (int i = 0; i < listeners.length; i += 2) {
+            if (listeners[i] == JMapViewerEventListener.class) {
+                ((JMapViewerEventListener) listeners[i + 1]).processCommand(evt);
             }
         }
     }
diff --git a/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java b/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
index ccf61b2..220df59 100644
--- a/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
+++ b/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
@@ -31,6 +31,9 @@ public class MemoryTileCache implements TileCache {
      */
     protected final CacheLinkedListElement lruTiles;
 
+    /**
+     * Constructs a new {@code MemoryTileCache}.
+     */
     public MemoryTileCache() {
         hash = new HashMap<>(cacheSize);
         lruTiles = new CacheLinkedListElement();
@@ -80,9 +83,7 @@ public class MemoryTileCache implements TileCache {
         return new CacheEntry(tile);
     }
 
-    /**
-     * Clears the cache deleting all tiles from memory
-     */
+    @Override
     public synchronized void clear() {
         hash.clear();
         lruTiles.clear();
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
index c88c207..08212ef 100644
--- a/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
+++ b/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
@@ -42,10 +42,9 @@ import org.openstreetmap.gui.jmapviewer.interfaces.TileSource.TileUpdate;
  */
 public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileLoader {
 
-    private static final Logger log = Logger.getLogger(OsmFileCacheTileLoader.class.getName());
+    private static final Logger log = FeatureAdapter.getLogger(OsmFileCacheTileLoader.class.getName());
 
-    private static final String ETAG_FILE_EXT = ".etag";
-    private static final String TAGS_FILE_EXT = ".tags";
+    protected static final String TAGS_FILE_EXT = "tags";
 
     private static final Charset TAGS_CHARSET = Charset.forName("UTF-8");
 
@@ -56,8 +55,8 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
 
     protected final Map<TileSource, File> sourceCacheDirMap;
 
-    protected long maxCacheFileAge = FILE_AGE_ONE_WEEK;
-    protected long recheckAfter = FILE_AGE_ONE_DAY;
+    protected long maxCacheFileAge = Long.MAX_VALUE;  // max. age not limited
+    protected long recheckAfter = FILE_AGE_ONE_WEEK;
 
     public static File getDefaultCacheDir() throws SecurityException {
         String tempDir = null;
@@ -133,8 +132,8 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
         Tile tile;
         File tileCacheDir;
         File tileFile = null;
-        long fileAge = 0;
-        boolean fileTilePainted = false;
+        Long fileMtime = null;
+        Long now = null; // current time in milliseconds (keep consistent value for the whole run)
 
         public FileLoadJob(Tile tile) {
             this.tile = tile;
@@ -154,44 +153,61 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
                 tile.error = false;
                 tile.loading = true;
             }
+            now = System.currentTimeMillis();
             tileCacheDir = getSourceCacheDir(tile.getSource());
-            if (loadTileFromFile()) {
+
+            if (loadTileFromFile(recheckAfter)) {
+                log.log(Level.FINE, "TMS - found in tile cache: {0}", tile);
+                tile.setLoaded(true);
+                listener.tileLoadingFinished(tile, true);
                 return;
             }
-            if (fileTilePainted) {
-                TileJob job = new TileJob() {
+            TileJob job = new TileJob() {
 
-                    @Override
-                    public void run() {
-                        loadOrUpdateTile();
-                    }
-                    @Override
-                    public Tile getTile() {
-                        return tile;
+                @Override
+                public void run() {
+                    if (loadOrUpdateTile()) {
+                        tile.setLoaded(true);
+                        listener.tileLoadingFinished(tile, true);
+                    } else {
+                        // failed to download - use old cache file if available
+                        if (loadTileFromFile(maxCacheFileAge)) {
+                            tile.setLoaded(true);
+                            tile.error = false;
+                            listener.tileLoadingFinished(tile, true);
+                            log.log(Level.FINE, "TMS - found stale tile in cache: {0}", tile);
+                        } else {
+                            // failed completely
+                            tile.setLoaded(true);
+                            listener.tileLoadingFinished(tile, false);
+                        }
                     }
-                };
-                JobDispatcher.getInstance().addJob(job);
-            } else {
-                loadOrUpdateTile();
-            }
+                }
+                @Override
+                public Tile getTile() {
+                    return tile;
+                }
+            };
+            JobDispatcher.getInstance().addJob(job);
         }
 
-        protected void loadOrUpdateTile() {
+        protected boolean loadOrUpdateTile() {
             try {
                 URLConnection urlConn = loadTileFromOsm(tile);
-                if (tileFile != null) {
+                if (fileMtime != null && now - fileMtime <= maxCacheFileAge) {
                     switch (tile.getSource().getTileUpdate()) {
                     case IfModifiedSince:
-                        urlConn.setIfModifiedSince(fileAge);
+                        urlConn.setIfModifiedSince(fileMtime);
                         break;
                     case LastModified:
-                        if (!isOsmTileNewer(fileAge)) {
-                            log.finest("LastModified test: local version is up to date: " + tile);
-                            tile.setLoaded(true);
-                            tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge + recheckAfter);
-                            return;
+                        if (!isOsmTileNewer(fileMtime)) {
+                            log.log(Level.FINE, "TMS - LastModified test: local version is up to date: {0}", tile);
+                            tileFile.setLastModified(now);
+                            return true;
                         }
                         break;
+                    default:
+                        break;
                     }
                 }
                 if (tile.getSource().getTileUpdate() == TileUpdate.ETag || tile.getSource().getTileUpdate() == TileUpdate.IfNoneMatch) {
@@ -203,11 +219,12 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
                             break;
                         case ETag:
                             if (hasOsmTileETag(fileETag)) {
-                                tile.setLoaded(true);
-                                tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge
-                                        + recheckAfter);
-                                return;
+                                log.log(Level.FINE, "TMS - ETag test: local version is up to date: {0}", tile);
+                                tileFile.setLastModified(now);
+                                return true;
                             }
+                        default:
+                            break;
                         }
                     }
                     tile.putValue("etag", urlConn.getHeaderField("ETag"));
@@ -215,10 +232,20 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
                 if (urlConn instanceof HttpURLConnection && ((HttpURLConnection)urlConn).getResponseCode() == 304) {
                     // If we are isModifiedSince or If-None-Match has been set
                     // and the server answers with a HTTP 304 = "Not Modified"
-                    log.finest("ETag test: local version is up to date: " + tile);
-                    tile.setLoaded(true);
-                    tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge + recheckAfter);
-                    return;
+                    switch (tile.getSource().getTileUpdate()) {
+                    case IfModifiedSince:
+                        log.log(Level.FINE, "TMS - IfModifiedSince test: local version is up to date: {0}", tile);
+                        break;
+                    case IfNoneMatch:
+                        log.log(Level.FINE, "TMS - IfNoneMatch test: local version is up to date: {0}", tile);
+                        break;
+                    default:
+                        break;
+                    }
+                    if (loadTileFromFile(maxCacheFileAge)) {
+                        tileFile.setLastModified(now);
+                        return true;
+                    }
                 }
 
                 loadTileMetadata(tile, urlConn);
@@ -226,10 +253,11 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
 
                 if ("no-tile".equals(tile.getValue("tile-info")))
                 {
+                    log.log(Level.FINE, "TMS - No tile: tile-info=no-tile: {0}", tile);
                     tile.setError("No tile at this zoom level");
-                    listener.tileLoadingFinished(tile, true);
+                    return true;
                 } else {
-                    for(int i = 0; i < 5; ++i) {
+                    for (int i = 0; i < 5; ++i) {
                         if (urlConn instanceof HttpURLConnection && ((HttpURLConnection)urlConn).getResponseCode() == 503) {
                             Thread.sleep(5000+(new Random()).nextInt(5000));
                             continue;
@@ -237,41 +265,43 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
                         byte[] buffer = loadTileInBuffer(urlConn);
                         if (buffer != null) {
                             tile.loadImage(new ByteArrayInputStream(buffer));
-                            tile.setLoaded(true);
-                            listener.tileLoadingFinished(tile, true);
                             saveTileToFile(buffer);
-                            break;
+                            log.log(Level.FINE, "TMS - downloaded tile from server: {0}", tile.getUrl());
+                            return true;
                         }
                     }
                 }
             } catch (Exception e) {
                 tile.setError(e.getMessage());
-                listener.tileLoadingFinished(tile, false);
                 if (input == null) {
                     try {
-                        System.err.println("Failed loading " + tile.getUrl() +": " + e.getMessage());
+                        log.log(Level.WARNING, "TMS - Failed downloading {0}: {1}", new Object[]{tile.getUrl(), e.getMessage()});
+                        return false;
                     } catch(IOException i) {
                     }
                 }
-            } finally {
-                tile.loading = false;
-                tile.setLoaded(true);
             }
+            log.log(Level.WARNING, "TMS - Failed downloading tile: {0}", tile);
+            return false;
         }
 
-        protected boolean loadTileFromFile() {
+        protected boolean loadTileFromFile(long maxAge) {
             try {
                 tileFile = getTileFile();
                 if (!tileFile.exists())
                     return false;
-
                 loadTagsFromFile();
+
+                fileMtime = tileFile.lastModified();
+                if (now - fileMtime > maxAge)
+                    return false;
+
                 if ("no-tile".equals(tile.getValue("tile-info"))) {
                     tile.setError("No tile at this zoom level");
                     if (tileFile.exists()) {
                         tileFile.delete();
                     }
-                    tileFile = getTagsFile();
+                    tileFile = null;
                 } else {
                     try (FileInputStream fin = new FileInputStream(tileFile)) {
                         if (fin.available() == 0)
@@ -279,21 +309,13 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
                         tile.loadImage(fin);
                     }
                 }
+                return true;
 
-                fileAge = tileFile.lastModified();
-                boolean oldTile = System.currentTimeMillis() - fileAge > maxCacheFileAge;
-                if (!oldTile) {
-                    tile.setLoaded(true);
-                    listener.tileLoadingFinished(tile, true);
-                    fileTilePainted = true;
-                    return true;
-                }
-                listener.tileLoadingFinished(tile, true);
-                fileTilePainted = true;
             } catch (Exception e) {
+                log.log(Level.WARNING, "TMS - Error while loading image from tile cache: {0}; {1}", new Object[]{e.getMessage(), tile});
                 tileFile.delete();
                 tileFile = null;
-                fileAge = 0;
+                fileMtime = null;
             }
             return false;
         }
@@ -346,7 +368,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
             urlConn.setReadTimeout(30000); // 30 seconds read timeout
             // System.out.println("Tile age: " + new
             // Date(urlConn.getLastModified()) + " / "
-            // + new Date(fileAge));
+            // + new Date(fileMtime));
             long lastModified = urlConn.getLastModified();
             if (lastModified == 0)
                 return true; // no LastModified time returned
@@ -362,7 +384,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
             urlConn.setReadTimeout(30000); // 30 seconds read timeout
             // System.out.println("Tile age: " + new
             // Date(urlConn.getLastModified()) + " / "
-            // + new Date(fileAge));
+            // + new Date(fileMtime));
             String osmETag = urlConn.getHeaderField("ETag");
             if (osmETag == null)
                 return true;
@@ -375,18 +397,19 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
         }
 
         protected File getTagsFile() {
-            return new File(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile() + "_" + tile.getYtile()
+            return new File(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile() + "_" + tile.getYtile() + "."
                     + TAGS_FILE_EXT);
         }
 
         protected void saveTileToFile(byte[] rawData) {
+            File file = getTileFile();
+            file.getParentFile().mkdirs();
             try (
-                FileOutputStream f = new FileOutputStream(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile()
-                        + "_" + tile.getYtile() + "." + tile.getSource().getTileType())
+                FileOutputStream f = new FileOutputStream(file)
             ) {
                 f.write(rawData);
             } catch (Exception e) {
-                System.err.println("Failed to save tile content: " + e.getLocalizedMessage());
+                log.log(Level.SEVERE, "Failed to save tile content: {0}", e.getLocalizedMessage());
             }
         }
 
@@ -405,26 +428,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileL
             }
         }
 
-        /** Load backward-compatiblity .etag file and if it exists move it to new .tags file*/
-        private void loadOldETagfromFile() {
-            File etagFile = new File(tileCacheDir, tile.getZoom() + "_"
-                    + tile.getXtile() + "_" + tile.getYtile() + ETAG_FILE_EXT);
-            if (!etagFile.exists()) return;
-            try (FileInputStream f = new FileInputStream(etagFile)) {
-                byte[] buf = new byte[f.available()];
-                f.read(buf);
-                String etag = new String(buf, TAGS_CHARSET.name());
-                tile.putValue("etag", etag);
-                if (etagFile.delete()) {
-                    saveTagsToFile();
-                }
-            } catch (IOException e) {
-                System.err.println("Failed to load compatiblity etag: " + e.getLocalizedMessage());
-            }
-        }
-
         protected void loadTagsFromFile() {
-            loadOldETagfromFile();
             File tagsFile = getTagsFile();
             try (BufferedReader f = new BufferedReader(new InputStreamReader(new FileInputStream(tagsFile), TAGS_CHARSET))) {
                 for (String line = f.readLine(); line != null; line = f.readLine()) {
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
index 8bb0955..eee1fc8 100644
--- a/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
+++ b/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
@@ -70,8 +70,10 @@ public class OsmTileLoader implements TileLoader {
                     listener.tileLoadingFinished(tile, false);
                     if (input == null) {
                         try {
-                            System.err.println("Failed loading " + tile.getUrl() +": " + e.getMessage());
-                        } catch(IOException i) {
+                            System.err.println("Failed loading " + tile.getUrl() +": "
+                                    +e.getClass() + ": " + e.getMessage());
+                        } catch (IOException ioe) {
+                            ioe.printStackTrace();
                         }
                     }
                 } finally {
diff --git a/src/org/openstreetmap/gui/jmapviewer/TMSFileCacheTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/TMSFileCacheTileLoader.java
new file mode 100644
index 0000000..e60548e
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/TMSFileCacheTileLoader.java
@@ -0,0 +1,76 @@
+// License: GPL. For details, see Readme.txt file.
+package org.openstreetmap.gui.jmapviewer;
+
+import java.io.File;
+import java.io.IOException;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
+
+/**
+ * Reworked version of the OsmFileCacheTileLoader.
+ *
+ * When class OsmFileCacheTileLoader is no longer needed, it can be integrated
+ * here and removed.
+ */
+public class TMSFileCacheTileLoader extends OsmFileCacheTileLoader {
+
+    public TMSFileCacheTileLoader(TileLoaderListener map, File cacheDir) throws IOException {
+        super(map, cacheDir);
+    }
+
+    @Override
+    public TileJob createTileLoaderJob(final Tile tile) {
+        return new TMSFileLoadJob(tile);
+    }
+
+    protected class TMSFileLoadJob extends FileLoadJob {
+
+        public TMSFileLoadJob(Tile tile) {
+            super(tile);
+        }
+
+        @Override
+        protected File getTileFile() {
+            return getDataFile(tile.getSource().getTileType());
+        }
+
+        @Override
+        protected File getTagsFile() {
+            return getDataFile(TAGS_FILE_EXT);
+        }
+
+        protected File getDataFile(String ext) {
+            int nDigits = (int) Math.ceil(Math.log10(1 << tile.getZoom()));
+            String x = String.format("%0" + nDigits + "d", tile.getXtile());
+            String y = String.format("%0" + nDigits + "d", tile.getYtile());
+            File path = new File(tileCacheDir, "z" + tile.getZoom());
+            for (int i=0; i<nDigits; i++) {
+                String component = "x" + x.substring(i, i+1) + "y" + y.substring(i, i+1);
+                if (i == nDigits -1 ) {
+                    component += "." + ext;
+                }
+                path = new File(path, component);
+            }
+            return path;
+        }
+    }
+
+    @Override
+    protected File getSourceCacheDir(TileSource source) {
+        File dir = sourceCacheDirMap.get(source);
+        if (dir == null) {
+            String id = source.getId();
+            if (id != null) {
+                dir = new File(cacheDirBase, id);
+            } else {
+                dir = new File(cacheDirBase, source.getName().replaceAll("[\\\\/:*?\"<>|]", "_"));
+            }
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+        }
+        return dir;
+    }
+
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/Tile.java b/src/org/openstreetmap/gui/jmapviewer/Tile.java
index 9e56e71..82ab19e 100644
--- a/src/org/openstreetmap/gui/jmapviewer/Tile.java
+++ b/src/org/openstreetmap/gui/jmapviewer/Tile.java
@@ -24,18 +24,21 @@ import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 public class Tile {
 
     /**
-     * Hourglass image that is displayed until a map tile has been loaded
+     * Hourglass image that is displayed until a map tile has been loaded, except for overlay sources
      */
     public static BufferedImage LOADING_IMAGE;
+
+    /**
+     * Red cross image that is displayed after a loading error, except for overlay sources
+     */
     public static BufferedImage ERROR_IMAGE;
 
     static {
         try {
             LOADING_IMAGE = ImageIO.read(JMapViewer.class.getResourceAsStream("images/hourglass.png"));
             ERROR_IMAGE = ImageIO.read(JMapViewer.class.getResourceAsStream("images/error.png"));
-        } catch (Exception e1) {
-            LOADING_IMAGE = null;
-            ERROR_IMAGE = null;
+        } catch (Exception ex) {
+            ex.printStackTrace();
         }
     }
 
@@ -56,24 +59,31 @@ public class Tile {
     /**
      * Creates a tile with empty image.
      *
-     * @param source
-     * @param xtile
-     * @param ytile
-     * @param zoom
+     * @param source Tile source
+     * @param xtile X coordinate
+     * @param ytile Y coordinate
+     * @param zoom Zoom level
      */
     public Tile(TileSource source, int xtile, int ytile, int zoom) {
-        super();
+        this(source, xtile, ytile, zoom, LOADING_IMAGE);
+    }
+
+    /**
+     * Creates a tile with specified image.
+     *
+     * @param source Tile source
+     * @param xtile X coordinate
+     * @param ytile Y coordinate
+     * @param zoom Zoom level
+     * @param image Image content
+     */
+    public Tile(TileSource source, int xtile, int ytile, int zoom, BufferedImage image) {
         this.source = source;
         this.xtile = xtile;
         this.ytile = ytile;
         this.zoom = zoom;
-        this.image = LOADING_IMAGE;
-        this.key = getTileKey(source, xtile, ytile, zoom);
-    }
-
-    public Tile(TileSource source, int xtile, int ytile, int zoom, BufferedImage image) {
-        this(source, xtile, ytile, zoom);
         this.image = image;
+        this.key = getTileKey(source, xtile, ytile, zoom);
     }
 
     /**
@@ -137,6 +147,7 @@ public class Tile {
     }
 
     /**
+     * Returns the X coordinate.
      * @return tile number on the x axis of this tile
      */
     public int getXtile() {
@@ -144,6 +155,7 @@ public class Tile {
     }
 
     /**
+     * Returns the Y coordinate.
      * @return tile number on the y axis of this tile
      */
     public int getYtile() {
@@ -151,6 +163,7 @@ public class Tile {
     }
 
     /**
+     * Returns the zoom level.
      * @return zoom level of this tile
      */
     public int getZoom() {
@@ -196,11 +209,9 @@ public class Tile {
      * Paints the tile-image on the {@link Graphics} <code>g</code> at the
      * position <code>x</code>/<code>y</code>.
      *
-     * @param g
-     * @param x
-     *            x-coordinate in <code>g</code>
-     * @param y
-     *            y-coordinate in <code>g</code>
+     * @param g the Graphics object
+     * @param x x-coordinate in <code>g</code>
+     * @param y y-coordinate in <code>g</code>
      */
     public void paint(Graphics g, int x, int y) {
         if (image == null)
@@ -285,8 +296,8 @@ public class Tile {
      * If value is null, the (possibly existing) key/value pair is removed from
      * the meta data.
      *
-     * @param key
-     * @param value
+     * @param key Key
+     * @param value Value
      */
     public void putValue(String key, String value) {
         if (value == null || value.isEmpty()) {
diff --git a/src/org/openstreetmap/gui/jmapviewer/TileController.java b/src/org/openstreetmap/gui/jmapviewer/TileController.java
index e16255a..d159ee1 100644
--- a/src/org/openstreetmap/gui/jmapviewer/TileController.java
+++ b/src/org/openstreetmap/gui/jmapviewer/TileController.java
@@ -6,7 +6,6 @@ import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
-import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;
 
 public class TileController {
     protected TileLoader tileLoader;
@@ -16,10 +15,10 @@ public class TileController {
     JobDispatcher jobDispatcher;
 
     public TileController(TileSource source, TileCache tileCache, TileLoaderListener listener) {
-        tileSource = new OsmTileSource.Mapnik();
-        tileLoader = new OsmTileLoader(listener);
+        this.tileSource = source;
+        this.tileLoader = new OsmTileLoader(listener);
         this.tileCache = tileCache;
-        jobDispatcher = JobDispatcher.getInstance();
+        this.jobDispatcher = JobDispatcher.getInstance();
     }
 
     /**
@@ -80,7 +79,7 @@ public class TileController {
     }
 
     /**
-     *
+     * Removes all jobs from the queue that are currently not being processed.
      */
     public void cancelOutstandingJobs() {
         jobDispatcher.cancelOutstandingJobs();
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java
index 0082987..cda5d67 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java
@@ -42,4 +42,9 @@ public interface TileCache {
      * @return the number of tiles hold by the cache
      */
     public int getTileCount();
+
+    /**
+     * Clears the cache deleting all tiles from memory.
+     */
+    public void clear();
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java
index 075ac9f..ecd566e 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java
@@ -9,15 +9,8 @@ public interface TileLoaderListener {
      * Will be called if a new {@link Tile} has been loaded successfully.
      * Loaded can mean downloaded or loaded from file cache.
      *
-     * @param tile
+     * @param tile The tile
+     * @param success {@code true} if the tile has been loaded successfully, {@code false} otherwise
      */
     public void tileLoadingFinished(Tile tile, boolean success);
-
-    /**
-     * Return the {@link TileCache} class containing {@link Tile}
-     * data for requested and loaded tiles
-     *
-     * @return tile information caching class
-     */
-    public TileCache getTileCache();
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
index 74a0284..b8680e8 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
@@ -62,14 +62,23 @@ public interface TileSource extends Attributed {
     TileUpdate getTileUpdate();
 
     /**
-     * A tile layer name has to be unique and has to consist only of characters
-     * valid for filenames.
+     * A tile layer name as displayed to the user.
      *
      * @return Name of the tile layer
      */
     String getName();
 
     /**
+     * A unique id for this tile source.
+     * 
+     * Unlike the name it has to be unique and has to consist only of characters
+     * valid for filenames.
+     * 
+     * @return the id
+     */
+    String getId();
+
+    /**
      * Constructs the tile url.
      *
      * @param zoom
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractMapQuestTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractMapQuestTileSource.java
index 4dbee39..5db7eca 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractMapQuestTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractMapQuestTileSource.java
@@ -30,8 +30,8 @@ public class AbstractMapQuestTileSource extends AbstractOsmTileSource {
     
     private int SERVER_NUM = 1;
 
-    public AbstractMapQuestTileSource(String name, String base_url) {
-        super(name, base_url);
+    public AbstractMapQuestTileSource(String name, String base_url, String id) {
+        super(name, base_url, id);
     }
 
     @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
index edf1729..ff8f58a 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
@@ -19,9 +19,11 @@ public abstract class AbstractOsmTileSource extends AbstractTMSTileSource {
      * Constructs a new OSM tile source
      * @param name Source name as displayed in GUI
      * @param base_url Source URL
+     * @param id unique id for the tile source; contains only characters that
+     * are safe for file names; can be null
      */
-    public AbstractOsmTileSource(String name, String base_url) {
-        super(name, base_url);
+    public AbstractOsmTileSource(String name, String base_url, String id) {
+        super(name, base_url, id);
     }
 
     public int getMaxZoom() {
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java
index 37b3c4a..e3cfd19 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java
@@ -9,13 +9,15 @@ public abstract class AbstractTMSTileSource extends AbstractTileSource {
 
     protected String name;
     protected String baseUrl;
+    protected String id;
 
-    public AbstractTMSTileSource(String name, String base_url) {
+    public AbstractTMSTileSource(String name, String base_url, String id) {
         this.name = name;
         this.baseUrl = base_url;
         if(baseUrl.endsWith("/")) {
             baseUrl = baseUrl.substring(0,baseUrl.length()-1);
         }
+        this.id = id;
     }
 
     @Override
@@ -24,6 +26,11 @@ public abstract class AbstractTMSTileSource extends AbstractTileSource {
     }
 
     @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
     public int getMaxZoom() {
         return 21;
     }
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java
index 7504b8a..f8723b6 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java
@@ -52,7 +52,14 @@ public class BingAerialTileSource extends AbstractTMSTileSource {
      * Constructs a new {@code BingAerialTileSource}.
      */
     public BingAerialTileSource() {
-        super("Bing Aerial Maps", "http://example.com/");
+        this("Bing");
+    }
+
+    /**
+     * Constructs a new {@code BingAerialTileSource}.
+     */
+    public BingAerialTileSource(String id) {
+        super("Bing Aerial Maps", "http://example.com/", id);
     }
 
     protected class Attribution {
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOpenAerialTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOpenAerialTileSource.java
index e48e88d..719b2e1 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOpenAerialTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOpenAerialTileSource.java
@@ -8,7 +8,7 @@ public class MapQuestOpenAerialTileSource extends AbstractMapQuestTileSource {
     private static final String PATTERN = "http://oatile%d.mqcdn.com/tiles/1.0.0/sat";
 
     public MapQuestOpenAerialTileSource() {
-        super("MapQuest Open Aerial", PATTERN);
+        super("MapQuest Open Aerial", PATTERN, "mapquest-oa");
     }
 
     @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
index 30f6288..010f9de 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
@@ -8,7 +8,7 @@ public class MapQuestOsmTileSource extends AbstractMapQuestTileSource {
     private static final String PATTERN = "http://otile%d.mqcdn.com/tiles/1.0.0/osm";
 
     public MapQuestOsmTileSource() {
-        super("MapQuest-OSM", PATTERN);
+        super("MapQuest-OSM", PATTERN, "mapquest-osm");
     }
     
     @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
index 3d4ab7f..1edaf5d 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
@@ -21,7 +21,7 @@ public class OsmTileSource {
          * Constructs a new {@code "Mapnik"} tile source.
          */
         public Mapnik() {
-            super("Mapnik", PATTERN);
+            super("Mapnik", PATTERN, "MAPNIK");
         }
 
         @Override
@@ -56,7 +56,7 @@ public class OsmTileSource {
          * Constructs a new {@code CycleMap} tile source.
          */
         public CycleMap() {
-            super("Cyclemap", PATTERN);
+            super("Cyclemap", PATTERN, "opencyclemap");
         }
 
         @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
index 934bd71..be7128a 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
@@ -45,8 +45,8 @@ public class ScanexTileSource extends TMSTileSource {
     /* IRS by default */
     private ScanexLayer Layer = ScanexLayer.IRS;
 
-    public ScanexTileSource(String name, String url, int maxZoom) {
-        super(name, url, maxZoom);
+    public ScanexTileSource(String name, String url, String id, int maxZoom) {
+        super(name, url, id, maxZoom);
 
         for (ScanexLayer layer : ScanexLayer.values()) {
             if (url.equalsIgnoreCase(layer.getName())) {
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java
index f22c0ac..23c792d 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java
@@ -6,13 +6,13 @@ public class TMSTileSource extends AbstractTMSTileSource {
     protected int maxZoom;
     protected int minZoom = 0;
 
-    public TMSTileSource(String name, String url, int maxZoom) {
-        super(name, url);
+    public TMSTileSource(String name, String url, String id, int maxZoom) {
+        super(name, url, id);
         this.maxZoom = maxZoom;
     }
 
-    public TMSTileSource(String name, String url, int minZoom, int maxZoom) {
-        super(name, url);
+    public TMSTileSource(String name, String url, String id, int minZoom, int maxZoom) {
+        super(name, url, id);
         this.minZoom = minZoom;
         this.maxZoom = maxZoom;
     }
@@ -27,6 +27,7 @@ public class TMSTileSource extends AbstractTMSTileSource {
         return (maxZoom == 0) ? super.getMaxZoom() : maxZoom;
     }
 
+    @Override
     public TileUpdate getTileUpdate() {
         return TileUpdate.IfNoneMatch;
     }
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java
index fea0e5a..a5d5c04 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java
@@ -26,13 +26,13 @@ public class TemplatedTMSTileSource extends TMSTileSource {
         PATTERN_SWITCH
     };
 
-    public TemplatedTMSTileSource(String name, String url, int maxZoom) {
-        super(name, url, maxZoom);
+    public TemplatedTMSTileSource(String name, String url, String id, int maxZoom) {
+        super(name, url, id, maxZoom);
         handleTemplate();
     }
 
-    public TemplatedTMSTileSource(String name, String url, int minZoom, int maxZoom) {
-        super(name, url, minZoom, maxZoom);
+    public TemplatedTMSTileSource(String name, String url, String id, int minZoom, int maxZoom) {
+        super(name, url, id, minZoom, maxZoom);
         handleTemplate();
     }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/jmapviewer.git



More information about the Pkg-grass-devel mailing list