+++ /dev/null
-package tim.prune.gui.map;
-
-import java.awt.Image;
-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
-{
- /** 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 inConsumer consumer object to be notified
- */
- public MapTileManager(TileConsumer inConsumer)
- {
- _consumer = inConsumer;
- }
-
- /**
- * 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)
- {
- setZoom(inZoom);
- // Pass params onto all memory cachers
- if (_tempCaches != null) {
- for (int i=0; i<_tempCaches.length; i++) {
- _tempCaches[i].centreMap(inZoom, inTileX, inTileY);
- }
- }
- }
-
- /** @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
- */
- public boolean isOverzoomed()
- {
- // Ask current map source what maximum zoom is
- int maxZoom = (_mapSource == null?0:_mapSource.getMaxZoomLevel());
- 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)
- {
- // Cachers 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();
- }
- }
- }
-
- /**
- * @param inSourceNum selected map source index
- */
- public void setMapSource(int inSourceNum)
- {
- setMapSource(MapSourceLibrary.getSource(inSourceNum));
- }
-
- /**
- * @param inMapSource selected map source
- */
- public void setMapSource(MapSource inMapSource)
- {
- _mapSource = inMapSource;
- if (_mapSource == null) {_mapSource = MapSourceLibrary.getSource(0);}
- clearMemoryCaches();
- _numLayers = _mapSource.getNumLayers();
- }
-
- /**
- * @return the number of layers in the map
- */
- public int getNumLayers()
- {
- return _numLayers;
- }
-
- /**
- * 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, boolean inDownloadIfNecessary)
- {
- 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
- Image tileImage = null;
- MemTileCacher tempCache = null;
- if (_tempCaches != null)
- {
- tempCache = _tempCaches[inLayer]; // Should probably guard array indexes here
- tileImage = tempCache.getTile(inX, inY);
- if (tileImage != null) {
- return tileImage;
- }
- }
-
- // 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);
- MapTile mapTile = null;
- if (useDisk)
- {
- // Get the map tile from cache
- mapTile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY));
- if (mapTile != null && mapTile.getImage() != null)
- {
- tileImage = mapTile.getImage();
- if (_returnIncompleteImages) {return tileImage;}
- // Pass tile to memory cache
- if (tempCache != null) {
- tempCache.setTile(tileImage, inX, inY, _zoom);
- }
- tileImage.getWidth(this); // trigger the load from file
- }
- }
- // Maybe we've got an image now, maybe it's expired
- final boolean shouldDownload = (tileImage == null || mapTile == null || mapTile.isExpired());
-
- // If we're online then try to download the tile
- if (onlineMode && _downloadTiles && inDownloadIfNecessary && shouldDownload)
- {
- try
- {
- URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
- //System.out.println("Trying to fetch: " + tileUrl);
- if (useDisk)
- {
- DiskTileCacher.saveTile(tileUrl, diskCachePath,
- _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this);
- // Image will now be copied directly from URL stream to disk cache
- }
- else
- {
- // Load image asynchronously, using observer
- // 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
- }
- return tileImage;
- }
-
- /**
- * 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) {
- _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);
- }
- }
-}