New TileManager
This removes all tile queueing/loading specific code from Layer.Grid and creates a new class that manages tile loading and caching.
This commit is contained in:
@@ -113,14 +113,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
*/
|
||||
numLoadingTiles: 0,
|
||||
|
||||
/**
|
||||
* APIProperty: tileLoadingDelay
|
||||
* {Integer} Number of milliseconds before we shift and load
|
||||
* tiles when panning. Ignored if <OpenLayers.Animation.isNative> is
|
||||
* true. Default is 85.
|
||||
*/
|
||||
tileLoadingDelay: 85,
|
||||
|
||||
/**
|
||||
* Property: serverResolutions
|
||||
* {Array(Number}} This property is documented in subclasses as
|
||||
@@ -128,32 +120,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
*/
|
||||
serverResolutions: null,
|
||||
|
||||
/**
|
||||
* Property: moveTimerId
|
||||
* {Number} The id of the <deferMoveGriddedTiles> timer.
|
||||
*/
|
||||
moveTimerId: null,
|
||||
|
||||
/**
|
||||
* Property: deferMoveGriddedTiles
|
||||
* {Function} A function that defers execution of <moveGriddedTiles> by
|
||||
* <tileLoadingDelay>. If <OpenLayers.Animation.isNative> is true, this
|
||||
* is null and unused.
|
||||
*/
|
||||
deferMoveGriddedTiles: null,
|
||||
|
||||
/**
|
||||
* Property: tileQueueId
|
||||
* {Number} The id of the <drawTilesFromQueue> animation.
|
||||
*/
|
||||
tileQueueId: null,
|
||||
|
||||
/**
|
||||
* Property: tileQueue
|
||||
* {Array(<OpenLayers.Tile>)} Tiles queued for drawing.
|
||||
*/
|
||||
tileQueue: null,
|
||||
|
||||
/**
|
||||
* Property: loading
|
||||
* {Boolean} Indicates if tiles are being loaded.
|
||||
@@ -241,26 +207,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
*/
|
||||
className: null,
|
||||
|
||||
/**
|
||||
* Property: tileCache
|
||||
* {Object} Cached image elements, keyed by URL.
|
||||
*/
|
||||
tileCache: null,
|
||||
|
||||
/**
|
||||
* Property: tileCacheIndex
|
||||
* {Array<String>} URLs of cached tiles; first entry is least recently
|
||||
* used.
|
||||
*/
|
||||
tileCacheIndex: null,
|
||||
|
||||
/**
|
||||
* APIProperty: tileCacheSize
|
||||
* {Number} Number of image elements to keep referenced for fast reuse.
|
||||
* Default is 128 per layer.
|
||||
*/
|
||||
tileCacheSize: 128,
|
||||
|
||||
/**
|
||||
* Register a listener for a particular event with the following syntax:
|
||||
* (code)
|
||||
@@ -275,6 +221,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* element - {DOMElement} A reference to layer.events.element.
|
||||
*
|
||||
* Supported event types:
|
||||
* addtile - Triggered when a tile is added to this layer. Listeners receive
|
||||
* an object as first argument, which has a tile property that
|
||||
* references the tile that has been added.
|
||||
* tileloadstart - Triggered when a tile starts loading. Listeners receive
|
||||
* an object as first argument, which has a tile property that
|
||||
* references the tile that starts loading.
|
||||
@@ -289,6 +238,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* still hidden) if a tile failed to load. Listeners receive an object
|
||||
* as first argument, which has a tile property that references the
|
||||
* tile that could not be loaded.
|
||||
* retile - Triggered when the layer recreates its tile grid.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -342,13 +292,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
'olLayerGrid';
|
||||
}
|
||||
|
||||
if (!OpenLayers.Animation.isNative) {
|
||||
this.deferMoveGriddedTiles = OpenLayers.Function.bind(function() {
|
||||
this.moveGriddedTiles(true);
|
||||
this.moveTimerId = null;
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1;
|
||||
},
|
||||
|
||||
@@ -375,7 +318,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
window.clearTimeout(this.moveTimerId);
|
||||
this.moveTimerId = null;
|
||||
}
|
||||
this.clearTileQueue();
|
||||
if(this.backBufferTimerId !== null) {
|
||||
window.clearTimeout(this.backBufferTimerId);
|
||||
this.backBufferTimerId = null;
|
||||
@@ -392,7 +334,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
|
||||
this.grid = null;
|
||||
this.tileSize = null;
|
||||
this.tileCache = null;
|
||||
OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments);
|
||||
},
|
||||
|
||||
@@ -402,7 +343,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* destroy() on each of them to kill circular references
|
||||
*/
|
||||
clearGrid:function() {
|
||||
this.clearTileQueue();
|
||||
if (this.grid) {
|
||||
for(var iRow=0, len=this.grid.length; iRow<len; iRow++) {
|
||||
var row = this.grid[iRow];
|
||||
@@ -450,8 +390,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
// same for backbuffer and tile queue
|
||||
obj.backBuffer = null;
|
||||
obj.backBufferTimerId = null;
|
||||
obj.tileQueue = [];
|
||||
obj.tileQueueId = null;
|
||||
obj.loading = false;
|
||||
obj.moveTimerId = null;
|
||||
|
||||
@@ -599,92 +537,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: queueTileDraw
|
||||
* Adds a tile to the animation queue that will draw it.
|
||||
*
|
||||
* Parameters:
|
||||
* evt - {Object} Listener argument of the tile's beforedraw event
|
||||
*/
|
||||
queueTileDraw: function(evt) {
|
||||
var tile = evt.object;
|
||||
var queued = false;
|
||||
if (this.async || !this.url ||
|
||||
!this.tileCache[this.getURL(tile.bounds)]) {
|
||||
// queue only if not in tileCache already
|
||||
if (!~OpenLayers.Util.indexOf(this.tileQueue, tile)) {
|
||||
// add to queue only if not in queue already
|
||||
this.tileQueue.push(tile);
|
||||
}
|
||||
queued = true;
|
||||
if (!this.tileQueueId) {
|
||||
this.tileQueueId = OpenLayers.Animation.start(
|
||||
OpenLayers.Function.bind(this.drawTilesFromQueue, this),
|
||||
null, this.div
|
||||
);
|
||||
}
|
||||
}
|
||||
return !queued;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawTilesFromQueue
|
||||
* Draws tiles from the tileQueue, and unqueues the tiles
|
||||
*/
|
||||
drawTilesFromQueue: function() {
|
||||
var numUrls = OpenLayers.Util.isArray(this.url) ? this.url.length : 1;
|
||||
//TODO instead of using 2 * urls, we could keep track of the hosts used
|
||||
// by all grid layers, and use a number that just saturates the number
|
||||
// of parallel requests the browser can send
|
||||
while (this.numLoadingTiles < 2 * numUrls) {
|
||||
if (this.tileQueue.length === 0) {
|
||||
this.clearTileQueue();
|
||||
break;
|
||||
}
|
||||
this.tileQueue.shift().draw(true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: manageTileCache
|
||||
* Adds, updates, removes and fetches cache entries.
|
||||
*
|
||||
* Parameters:
|
||||
* evt - {Object} Listener argument of the tile's loadstart event
|
||||
*/
|
||||
manageTileCache: function(evt) {
|
||||
var tile = evt.object;
|
||||
if (this.tileCache[tile.url]) {
|
||||
tile.imgDiv = this.tileCache[tile.url];
|
||||
OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
|
||||
this.tileCacheIndex.push(tile.url);
|
||||
tile.positionTile();
|
||||
this.div.appendChild(tile.imgDiv);
|
||||
} else {
|
||||
tile.events.register('loadend', this, function loadend() {
|
||||
tile.events.unregister('loadend', this, loadend);
|
||||
if (!this.tileCache[tile.url]) {
|
||||
if (this.tileCacheIndex.length >= this.tileCacheSize) {
|
||||
delete this.tileCache[this.tileCacheIndex[0]];
|
||||
this.tileCacheIndex.shift();
|
||||
}
|
||||
this.tileCache[tile.url] = tile.imgDiv;
|
||||
this.tileCacheIndex.push(tile.url);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: clearTileQueue
|
||||
* Clears the animation queue
|
||||
*/
|
||||
clearTileQueue: function() {
|
||||
window.clearInterval(this.tileQueueId);
|
||||
this.tileQueueId = null;
|
||||
this.tileQueue = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: destroyTile
|
||||
*
|
||||
@@ -843,10 +695,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
this.div.removeChild(this.backBuffer);
|
||||
this.backBuffer = null;
|
||||
this.backBufferResolution = null;
|
||||
if(this.backBufferTimerId !== null) {
|
||||
window.clearTimeout(this.backBufferTimerId);
|
||||
this.backBufferTimerId = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -914,7 +762,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* bounds - {<OpenLayers.Bounds>}
|
||||
*/
|
||||
initSingleTile: function(bounds) {
|
||||
this.clearTileQueue();
|
||||
this.events.triggerEvent("retile");
|
||||
|
||||
//determine new tile bounds
|
||||
var center = bounds.getCenterLonLat();
|
||||
@@ -1047,7 +895,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* bounds - {<OpenLayers.Bounds>}
|
||||
*/
|
||||
initGriddedTiles:function(bounds) {
|
||||
this.clearTileQueue();
|
||||
this.events.triggerEvent("retile");
|
||||
|
||||
// work out mininum number of rows and columns; this is the number of
|
||||
// tiles required to cover the viewport plus at least one for panning
|
||||
@@ -1126,8 +974,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
//shave off exceess rows and colums
|
||||
this.removeExcessTiles(rowidx, colidx);
|
||||
|
||||
var resolution = this.getServerResolution(),
|
||||
immediately = resolution === this.gridResolution;
|
||||
var resolution = this.getServerResolution();
|
||||
// store the resolution of the grid
|
||||
this.gridResolution = resolution;
|
||||
|
||||
@@ -1136,7 +983,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
return a.distance - b.distance;
|
||||
});
|
||||
for (var i=0, ii=tileData.length; i<ii; ++i) {
|
||||
tileData[i].tile.draw(immediately);
|
||||
tileData[i].tile.draw();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1167,11 +1014,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
var tile = new this.tileClass(
|
||||
this, position, bounds, null, this.tileSize, this.tileOptions
|
||||
);
|
||||
tile.events.on({
|
||||
beforedraw: this.queueTileDraw,
|
||||
loadstart: this.manageTileCache,
|
||||
scope: this
|
||||
});
|
||||
this.events.triggerEvent("addtile", {tile: tile});
|
||||
return tile;
|
||||
},
|
||||
|
||||
@@ -1202,7 +1045,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
aborted: evt.type === "unload"
|
||||
});
|
||||
//if that was the last tile, then trigger a 'loadend' on the layer
|
||||
if (this.tileQueue.length === 0 && this.numLoadingTiles === 0) {
|
||||
if (this.numLoadingTiles === 0) {
|
||||
this.loading = false;
|
||||
this.events.triggerEvent("loadend");
|
||||
if(this.backBuffer) {
|
||||
@@ -1255,21 +1098,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
|
||||
/**
|
||||
* Method: moveGriddedTiles
|
||||
*
|
||||
* Parameter:
|
||||
* deferred - {Boolean} true if this is a deferred call that should not
|
||||
* be delayed.
|
||||
*/
|
||||
moveGriddedTiles: function(deferred) {
|
||||
if (!deferred && !OpenLayers.Animation.isNative) {
|
||||
if (this.moveTimerId != null) {
|
||||
window.clearTimeout(this.moveTimerId);
|
||||
}
|
||||
this.moveTimerId = window.setTimeout(
|
||||
this.deferMoveGriddedTiles, this.tileLoadingDelay
|
||||
);
|
||||
return;
|
||||
}
|
||||
moveGriddedTiles: function() {
|
||||
var buffer = this.buffer + 1;
|
||||
while(true) {
|
||||
var tlTile = this.grid[0][0];
|
||||
|
||||
Reference in New Issue
Block a user