Since draw is the only tile operation that we defer, the tile queue can be an array of tiles and queue handling can be simplified. We now use the beforedraw event to defer drawing, and remove all occurrences of a tile from the tile queue when we draw it. Instead of layers that want to defer tile drawing having to override the tile's draw method, layers can now abort drawing by returning false from a beforedraw listener, and later call draw(true) to draw the tile directly, without clearing it first.
254 lines
7.4 KiB
JavaScript
254 lines
7.4 KiB
JavaScript
/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
|
|
* full list of contributors). Published under the Clear BSD license.
|
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the
|
|
* full text of the license. */
|
|
|
|
|
|
/**
|
|
* @requires OpenLayers/BaseTypes/Class.js
|
|
* @requires OpenLayers/Util.js
|
|
*/
|
|
|
|
/**
|
|
* Class: OpenLayers.Tile
|
|
* This is a class designed to designate a single tile, however
|
|
* it is explicitly designed to do relatively little. Tiles store
|
|
* information about themselves -- such as the URL that they are related
|
|
* to, and their size - but do not add themselves to the layer div
|
|
* automatically, for example. Create a new tile with the
|
|
* <OpenLayers.Tile> constructor, or a subclass.
|
|
*
|
|
* TBD 3.0 - remove reference to url in above paragraph
|
|
*
|
|
*/
|
|
OpenLayers.Tile = OpenLayers.Class({
|
|
|
|
/**
|
|
* Supported event types:
|
|
* - *beforedraw* Triggered before the tile is drawn. Used to defer
|
|
* drawing to an animation queue. To defer drawing, listeners need
|
|
* to return false, which will abort drawing. The queue handler needs
|
|
* to call <draw>(true) to actually draw the tile.
|
|
* - *loadstart* Triggered when tile loading starts.
|
|
* - *loadend* Triggered when tile loading ends.
|
|
* - *reload* Triggered when an already loading tile is reloaded.
|
|
* - *unload* Triggered before a tile is unloaded.
|
|
*/
|
|
|
|
/**
|
|
* APIProperty: events
|
|
* {<OpenLayers.Events>} An events object that handles all
|
|
* events on the tile.
|
|
*/
|
|
events: null,
|
|
|
|
/**
|
|
* Property: id
|
|
* {String} null
|
|
*/
|
|
id: null,
|
|
|
|
/**
|
|
* Property: layer
|
|
* {<OpenLayers.Layer>} layer the tile is attached to
|
|
*/
|
|
layer: null,
|
|
|
|
/**
|
|
* Property: url
|
|
* {String} url of the request.
|
|
*
|
|
* TBD 3.0
|
|
* Deprecated. The base tile class does not need an url. This should be
|
|
* handled in subclasses. Does not belong here.
|
|
*/
|
|
url: null,
|
|
|
|
/**
|
|
* APIProperty: bounds
|
|
* {<OpenLayers.Bounds>} null
|
|
*/
|
|
bounds: null,
|
|
|
|
/**
|
|
* Property: size
|
|
* {<OpenLayers.Size>} null
|
|
*/
|
|
size: null,
|
|
|
|
/**
|
|
* Property: position
|
|
* {<OpenLayers.Pixel>} Top Left pixel of the tile
|
|
*/
|
|
position: null,
|
|
|
|
/**
|
|
* Property: isLoading
|
|
* {Boolean} Is the tile loading?
|
|
*/
|
|
isLoading: false,
|
|
|
|
/** TBD 3.0 -- remove 'url' from the list of parameters to the constructor.
|
|
* there is no need for the base tile class to have a url.
|
|
*
|
|
* Constructor: OpenLayers.Tile
|
|
* Constructor for a new <OpenLayers.Tile> instance.
|
|
*
|
|
* Parameters:
|
|
* layer - {<OpenLayers.Layer>} layer that the tile will go in.
|
|
* position - {<OpenLayers.Pixel>}
|
|
* bounds - {<OpenLayers.Bounds>}
|
|
* url - {<String>}
|
|
* size - {<OpenLayers.Size>}
|
|
* options - {Object}
|
|
*/
|
|
initialize: function(layer, position, bounds, url, size, options) {
|
|
this.layer = layer;
|
|
this.position = position.clone();
|
|
this.setBounds(bounds);
|
|
this.url = url;
|
|
if (size) {
|
|
this.size = size.clone();
|
|
}
|
|
|
|
//give the tile a unique id based on its BBOX.
|
|
this.id = OpenLayers.Util.createUniqueID("Tile_");
|
|
|
|
this.events = new OpenLayers.Events(this);
|
|
|
|
OpenLayers.Util.extend(this, options);
|
|
},
|
|
|
|
/**
|
|
* Method: unload
|
|
* Call immediately before destroying if you are listening to tile
|
|
* events, so that counters are properly handled if tile is still
|
|
* loading at destroy-time. Will only fire an event if the tile is
|
|
* still loading.
|
|
*/
|
|
unload: function() {
|
|
if (this.isLoading) {
|
|
this.isLoading = false;
|
|
this.events.triggerEvent("unload");
|
|
}
|
|
},
|
|
|
|
/**
|
|
* APIMethod: destroy
|
|
* Nullify references to prevent circular references and memory leaks.
|
|
*/
|
|
destroy:function() {
|
|
this.layer = null;
|
|
this.bounds = null;
|
|
this.size = null;
|
|
this.position = null;
|
|
|
|
this.events.destroy();
|
|
this.events = null;
|
|
},
|
|
|
|
/**
|
|
* Method: draw
|
|
* Clear whatever is currently in the tile, then return whether or not
|
|
* it should actually be re-drawn. This is an example implementation
|
|
* that can be overridden by subclasses. The minimum thing to do here
|
|
* is to call <clear> and return the result from <shouldDraw>.
|
|
*
|
|
* Parameters:
|
|
* deferred - {Boolean} When drawing was aborted by returning false from a
|
|
* *beforedraw* listener, the queue manager needs to pass true, so the
|
|
* tile will not be cleared and immediately be drawn. Otherwise, the
|
|
* tile will be cleared and a *beforedraw* event will be fired.
|
|
*
|
|
* Returns:
|
|
* {Boolean} Whether or not the tile should actually be drawn.
|
|
*/
|
|
draw: function(deferred) {
|
|
if (!deferred) {
|
|
//clear tile's contents and mark as not drawn
|
|
this.clear();
|
|
}
|
|
var draw = this.shouldDraw();
|
|
if (draw && !deferred) {
|
|
draw = this.events.triggerEvent("beforedraw") !== false;
|
|
}
|
|
return draw;
|
|
},
|
|
|
|
/**
|
|
* Method: shouldDraw
|
|
* Return whether or not the tile should actually be (re-)drawn. The only
|
|
* case where we *wouldn't* want to draw the tile is if the tile is outside
|
|
* its layer's maxExtent
|
|
*
|
|
* Returns:
|
|
* {Boolean} Whether or not the tile should actually be drawn.
|
|
*/
|
|
shouldDraw: function() {
|
|
var withinMaxExtent = false,
|
|
maxExtent = this.layer.maxExtent;
|
|
if (maxExtent) {
|
|
var map = this.layer.map;
|
|
var worldBounds = map.baseLayer.wrapDateLine && map.getMaxExtent();
|
|
if (this.bounds.intersectsBounds(maxExtent, {inclusive: false, worldBounds: worldBounds})) {
|
|
withinMaxExtent = true;
|
|
}
|
|
}
|
|
|
|
return withinMaxExtent || this.layer.displayOutsideMaxExtent;
|
|
},
|
|
|
|
/**
|
|
* Method: setBounds
|
|
* Sets the bounds on this instance
|
|
*
|
|
* Parameters:
|
|
* bounds {<OpenLayers.Bounds>}
|
|
*/
|
|
setBounds: function(bounds) {
|
|
bounds = bounds.clone();
|
|
if (this.layer.map.baseLayer.wrapDateLine) {
|
|
var worldExtent = this.layer.map.getMaxExtent(),
|
|
tolerance = this.layer.map.getResolution();
|
|
bounds = bounds.wrapDateLine(worldExtent, {
|
|
leftTolerance: tolerance,
|
|
rightTolerance: tolerance
|
|
});
|
|
}
|
|
this.bounds = bounds;
|
|
},
|
|
|
|
/**
|
|
* Method: moveTo
|
|
* Reposition the tile.
|
|
*
|
|
* Parameters:
|
|
* bounds - {<OpenLayers.Bounds>}
|
|
* position - {<OpenLayers.Pixel>}
|
|
* redraw - {Boolean} Call draw method on tile after moving.
|
|
* Default is true
|
|
*/
|
|
moveTo: function (bounds, position, redraw) {
|
|
if (redraw == null) {
|
|
redraw = true;
|
|
}
|
|
|
|
this.setBounds(bounds);
|
|
this.position = position.clone();
|
|
if (redraw) {
|
|
this.draw();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: clear
|
|
* Clear the tile of any bounds/position-related data so that it can
|
|
* be reused in a new location.
|
|
*/
|
|
clear: function(draw) {
|
|
// to be extended by subclasses
|
|
},
|
|
|
|
CLASS_NAME: "OpenLayers.Tile"
|
|
});
|