X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=tim%2Fprune%2Fgui%2Fmap%2FMapTileManager.java;h=ed8849bd469118f5314322adbe77c1ba097523f4;hb=326f489e36aa7f235bc19409a57bf4955cd50f24;hp=829f824ffa09d06f6e37e2d3bd64e5bd7121725c;hpb=f1b92378a792131ac8fb33a869405851d5b2d1f7;p=GpsPrune.git diff --git a/tim/prune/gui/map/MapTileManager.java b/tim/prune/gui/map/MapTileManager.java index 829f824..ed8849b 100644 --- a/tim/prune/gui/map/MapTileManager.java +++ b/tim/prune/gui/map/MapTileManager.java @@ -1,45 +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; - /** Currently blocked zoom level, to prevent looping for non-existent images */ - private int _blockedZoom = 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; - // Adjust the index of the selected map source - adjustSelectedMap(); - resetConfig(); + _consumer = inConsumer; } /** @@ -50,9 +49,7 @@ public class MapTileManager implements ImageObserver */ public void centreMap(int inZoom, int inTileX, int inTileY) { - _zoom = inZoom; - // Calculate number of tiles = 2^^zoom - _numTileIndices = 1 << _zoom; + setZoom(inZoom); // Pass params onto all memory cachers if (_tempCaches != null) { for (int i=0; i<_tempCaches.length; i++) { @@ -61,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 */ @@ -71,6 +76,21 @@ 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 */ @@ -94,35 +114,22 @@ public class MapTileManager implements ImageObserver } /** - * Reset the map source configuration, apparently it has changed + * @param inSourceNum selected map source index */ - public void resetConfig() + public void setMapSource(int inSourceNum) { - int sourceNum = Config.getConfigInt(Config.KEY_MAPSOURCE_INDEX); - _mapSource = MapSourceLibrary.getSource(sourceNum); - if (_mapSource == null) {_mapSource = MapSourceLibrary.getSource(0);} - clearMemoryCaches(); - _numLayers = _mapSource.getNumLayers(); + setMapSource(MapSourceLibrary.getSource(inSourceNum)); } /** - * Adjust the index of the selected map - * (only required if config was loaded from a previous version of GpsPrune) + * @param inMapSource selected map source */ - private void adjustSelectedMap() + public void setMapSource(MapSource inMapSource) { - int sourceNum = Config.getConfigInt(Config.KEY_MAPSOURCE_INDEX); - int prevNumFixed = Config.getConfigInt(Config.KEY_NUM_FIXED_MAPS); - // Number of fixed maps not specified in version <=13, default to 6 - if (prevNumFixed == 0) prevNumFixed = 6; - int currNumFixed = MapSourceLibrary.getNumFixedSources(); - // Only need to do something if the number has changed - if (currNumFixed != prevNumFixed && (sourceNum >= prevNumFixed || sourceNum >= currNumFixed)) - { - sourceNum += (currNumFixed - prevNumFixed); - Config.setConfigInt(Config.KEY_MAPSOURCE_INDEX, sourceNum); - } - Config.setConfigInt(Config.KEY_NUM_FIXED_MAPS, currNumFixed); + _mapSource = inMapSource; + if (_mapSource == null) {_mapSource = MapSourceLibrary.getSource(0);} + clearMemoryCaches(); + _numLayers = _mapSource.getNumLayers(); } /** @@ -134,21 +141,29 @@ public class MapTileManager implements ImageObserver } /** + * Get a tile from the currently selected map source * @param inLayer layer number, starting from 0 * @param inX x index of tile * @param inY y index of tile + * @param inDownloadIfNecessary true to download the file if it's not available * @return selected tile if already loaded, or null otherwise */ - public Image getTile(int inLayer, int inX, int inY) + public Image getTile(int inLayer, int inX, int inY, boolean inDownloadIfNecessary) { - // Check tile boundaries - if (inX < 0 || inX >= _numTileIndices || inY < 0 || inY >= _numTileIndices) return null; + if (inY < 0 || inY >= _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) @@ -160,19 +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 && _blockedZoom != _zoom) + if (onlineMode && _downloadTiles && inDownloadIfNecessary) { - _blockedZoom = 0; // reset to try again 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)) { @@ -181,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 @@ -206,12 +223,34 @@ public class MapTileManager implements ImageObserver { boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0; boolean error = (infoflags & ImageObserver.ERROR) > 0; - if (error) { - _blockedZoom = _zoom; - } 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); + } + } }