]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/gui/map/MapTileManager.java
Version 10, May 2010
[GpsPrune.git] / tim / prune / gui / map / MapTileManager.java
diff --git a/tim/prune/gui/map/MapTileManager.java b/tim/prune/gui/map/MapTileManager.java
new file mode 100644 (file)
index 0000000..9f1fbfe
--- /dev/null
@@ -0,0 +1,178 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.ImageObserver;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import tim.prune.config.Config;
+
+/**
+ * Class responsible for managing the map tiles,
+ * including invoking the correct memory cacher(s) and/or disk cacher(s)
+ */
+public class MapTileManager implements ImageObserver
+{
+       /** Parent object to inform when tiles received */
+       private MapCanvas _parent = null;
+       /** Current map source */
+       private MapSource _mapSource = null;
+       /** Array of tile caches, one per layer */
+       private MemTileCacher[] _tempCaches = null;
+       /** Number of layers */
+       private int _numLayers = -1;
+       /** Current zoom level */
+       private int _zoom = 0;
+
+
+       /**
+        * Constructor
+        * @param inParent parent canvas to be informed of updates
+        */
+       public MapTileManager(MapCanvas inParent)
+       {
+               _parent = inParent;
+               resetConfig();
+       }
+
+       /**
+        * Recentre the map
+        * @param inZoom zoom level
+        * @param inTileX x coord of central tile
+        * @param inTileY y coord of central tile
+        */
+       public void centreMap(int inZoom, int inTileX, int inTileY)
+       {
+               _zoom = inZoom;
+               // Pass params onto all memory cachers
+               if (_tempCaches != null) {
+                       for (int i=0; i<_tempCaches.length; i++) {
+                               _tempCaches[i].centreMap(inZoom, inTileX, inTileY);
+                       }
+               }
+       }
+
+       /**
+        * @return true if zoom is too high for tiles
+        */
+       public boolean isOverzoomed()
+       {
+               // Ask current map source what maximum zoom is
+               int maxZoom = (_mapSource == null?0:_mapSource.getMaxZoomLevel());
+               return (_zoom > maxZoom);
+       }
+
+       /**
+        * Clear all the memory caches due to changed config / zoom
+        */
+       public void clearMemoryCaches()
+       {
+               int numLayers = _mapSource.getNumLayers();
+               if (_tempCaches == null || _tempCaches.length != numLayers) {
+                       // Ccahers don't match, so need to create the right number of them
+                       _tempCaches = new MemTileCacher[numLayers];
+                       for (int i=0; i<numLayers; i++) {
+                               _tempCaches[i] = new MemTileCacher();
+                       }
+               }
+               else {
+                       // Cachers already there, just need to be cleared
+                       for (int i=0; i<numLayers; i++) {
+                               _tempCaches[i].clearAll();
+                       }
+               }
+       }
+
+       /**
+        * Reset the map source configuration, apparently it has changed
+        */
+       public void resetConfig()
+       {
+               int sourceNum = Config.getConfigInt(Config.KEY_MAPSOURCE_INDEX);
+               _mapSource = MapSourceLibrary.getSource(sourceNum);
+               if (_mapSource == null) {_mapSource = MapSourceLibrary.getSource(0);}
+               clearMemoryCaches();
+               _numLayers = _mapSource.getNumLayers();
+       }
+
+       /**
+        * @return the number of layers in the map
+        */
+       public int getNumLayers()
+       {
+               return _numLayers;
+       }
+
+       /**
+        * @param inLayer layer number, starting from 0
+        * @param inX x index of tile
+        * @param inY y index of tile
+        * @return selected tile if already loaded, or null otherwise
+        */
+       public Image getTile(int inLayer, int inX, int inY)
+       {
+               // Check first in memory cache for tile
+               MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here
+               Image tile = tempCache.getTile(inX, inY);
+               if (tile != null) {
+                       return tile;
+               }
+
+               // Tile wasn't in memory, but maybe it's in disk cache (if there is one)
+               String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
+               boolean useDisk = (diskCachePath != null);
+               boolean onlineMode = Config.getConfigBoolean(Config.KEY_ONLINE_MODE);
+               if (useDisk)
+               {
+                       tile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), onlineMode);
+                       if (tile != null) {
+                               // Pass tile to memory cache
+                               tempCache.setTile(tile, inX, inY);
+                               if (tile.getWidth(this) > 0) {return tile;}
+                               return null;
+                       }
+               }
+               // Tile wasn't in memory or on disk, so if online let's get it
+               if (onlineMode)
+               {
+                       try
+                       {
+                               URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
+                               if (useDisk) {
+                                       // Copy image directly from URL stream to disk cache
+                                       DiskTileCacher.saveTile(tileUrl, diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this);
+                               }
+                               else {
+                                       // Load image asynchronously, using observer
+                                       tile = Toolkit.getDefaultToolkit().createImage(tileUrl);
+                                       // Pass to memory cache
+                                       _tempCaches[inLayer].setTile(tile, inX, inY);
+                                       if (tile.getWidth(this) > 0) {return tile;}
+                               }
+                       }
+                       catch (MalformedURLException urle) {} // ignore
+               }
+               return null;
+       }
+
+       /**
+        * Method called by image loader to inform of updates to the tiles
+        * @param img the image
+        * @param infoflags flags describing how much of the image is known
+        * @param x ignored
+        * @param y ignored
+        * @param width ignored
+        * @param height ignored
+        * @return false to carry on loading, true to stop
+        */
+       public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
+       {
+               boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0;
+               boolean error = (infoflags & ImageObserver.ERROR) > 0;
+               if (loaded || error) {
+                       _parent.tilesUpdated(loaded);
+               }
+               return !loaded;
+       }
+}