X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=tim%2Fprune%2Fgui%2Fmap%2FMapTileManager.java;h=ed8849bd469118f5314322adbe77c1ba097523f4;hb=326f489e36aa7f235bc19409a57bf4955cd50f24;hp=f7a281b1022ca8059a02e4fe9aef004431b464fc;hpb=649c5da6ee1bbc590699e11a92316ece2ea8512d;p=GpsPrune.git diff --git a/tim/prune/gui/map/MapTileManager.java b/tim/prune/gui/map/MapTileManager.java index f7a281b..ed8849b 100644 --- a/tim/prune/gui/map/MapTileManager.java +++ b/tim/prune/gui/map/MapTileManager.java @@ -1,39 +1,44 @@ 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; + /** Consumer object to inform when tiles received */ + private TileConsumer _consumer = null; /** Current map source */ private MapSource _mapSource = null; /** Array of tile caches, one per layer */ private MemTileCacher[] _tempCaches = null; + /** Flag for whether to download any tiles or just pull from disk */ + private boolean _downloadTiles = true; + /** Flag for whether to return incomplete images or just pass to tile cache until they're done */ + private boolean _returnIncompleteImages = false; /** Number of layers */ private int _numLayers = -1; /** Current zoom level */ private int _zoom = 0; + /** Number of tiles in each direction for this zoom level */ + private int _numTileIndices = 1; /** * Constructor - * @param inParent parent canvas to be informed of updates + * @param inConsumer consumer object to be notified */ - public MapTileManager(MapCanvas inParent) + public MapTileManager(TileConsumer inConsumer) { - _parent = inParent; - resetConfig(); + _consumer = inConsumer; } /** @@ -44,7 +49,7 @@ public class MapTileManager implements ImageObserver */ public void centreMap(int inZoom, int inTileX, int inTileY) { - _zoom = inZoom; + setZoom(inZoom); // Pass params onto all memory cachers if (_tempCaches != null) { for (int i=0; i<_tempCaches.length; i++) { @@ -53,6 +58,14 @@ public class MapTileManager implements ImageObserver } } + /** @param inZoom zoom level to set */ + public void setZoom(int inZoom) + { + _zoom = inZoom; + // Calculate number of tiles = 2^^zoom + _numTileIndices = 1 << _zoom; + } + /** * @return true if zoom is too high for tiles */ @@ -63,14 +76,30 @@ public class MapTileManager implements ImageObserver return (_zoom > maxZoom); } + /** + * Enable or disable tile downloading + * @param inEnabled true to enable downloading, false to just get tiles from disk + */ + public void enableTileDownloading(boolean inEnabled) + { + _downloadTiles = inEnabled; + } + + /** Configure to return incomplete images instead of going via caches (and another call) */ + public void setReturnIncompleteImages() + { + _returnIncompleteImages = true; + } + /** * 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 + if (_tempCaches == null || _tempCaches.length != numLayers) + { + // Cachers don't match, so need to create the right number of them _tempCaches = new MemTileCacher[numLayers]; for (int i=0; i= _numTileIndices) return null; + // Wrap tile indices which are too big or too small + inX = ((inX % _numTileIndices) + _numTileIndices) % _numTileIndices; + // 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; + Image tile = null; + MemTileCacher tempCache = null; + if (_tempCaches != null) + { + tempCache = _tempCaches[inLayer]; // Should probably guard array indexes here + 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) @@ -128,18 +175,23 @@ public class MapTileManager implements ImageObserver tile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), onlineMode); if (tile != null) { + if (_returnIncompleteImages) {return tile;} // Pass tile to memory cache - tempCache.setTile(tile, inX, inY); + if (tempCache != null) { + tempCache.setTile(tile, inX, inY, _zoom); + } if (tile.getWidth(this) > 0) {return tile;} return null; } + // else System.out.println("DTC gave null tile for " + _zoom + ", " + inX + ", " + inY); } // Tile wasn't in memory or on disk, so if online let's get it - if (onlineMode) + if (onlineMode && _downloadTiles && inDownloadIfNecessary) { try { URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY)); + // System.out.println("Going to fetch: " + tileUrl); if (useDisk && DiskTileCacher.saveTile(tileUrl, diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this)) { @@ -148,10 +200,8 @@ public class MapTileManager implements ImageObserver 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;} + // In order to set the http user agent, need to use a TileDownloader instead + TileDownloader.triggerLoad(this, tileUrl, inLayer, inX, inY, _zoom); } } catch (MalformedURLException urle) {} // ignore @@ -174,8 +224,33 @@ public class MapTileManager implements ImageObserver boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0; boolean error = (infoflags & ImageObserver.ERROR) > 0; if (loaded || error) { - _parent.tilesUpdated(loaded); + _consumer.tilesUpdated(loaded); } return !loaded; } + + /** + * Callback method from TileDownloader to let us know that an image has been loaded + * @param inTile Loaded Image object + * @param inLayer layer index from 0 + * @param inX x coordinate of tile + * @param inY y coordinate of tile + * @param inZoom zoom level of loaded image + */ + public void notifyImageLoaded(Image inTile, int inLayer, int inX, int inY, int inZoom) + { + if (inTile != null && _tempCaches != null) + { + MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here + if (tempCache.getTile(inX, inY) == null) + { + // Check with cache that the zoom level is still valid + tempCache.setTile(inTile, inX, inY, inZoom); + inTile.getWidth(this); // trigger imageUpdate when image is ready + } + } + else if (inTile != null) { + inTile.getWidth(this); + } + } }