World cleanup; viewer layer function deprecation

This commit is contained in:
Ian Gilman 2014-08-19 15:02:04 -07:00
parent 796588ace2
commit 33f0fa1e4b
2 changed files with 200 additions and 135 deletions

View File

@ -1032,59 +1032,54 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
},
/**
* Add a layer.
* Add a tiled image to the viewer.
* options.tileSource can be anything that {@link OpenSeadragon.Viewer#open}
* supports except arrays of images as layers cannot be sequences.
* supports except arrays of images.
* Note that you can specify options.width or options.height, but not both.
* The other dimension will be calculated according to the layer's aspect ratio.
* The other dimension will be calculated according to the item's aspect ratio.
* @function
* @param {Object} options
* @param {String|Object|Function} options.tileSource The TileSource of the layer.
* @param {Number} [options.opacity=1] The opacity of the layer.
* @param {Number} [options.level] The level of the layer. Added on top of
* all other layers if not specified.
* @param {String|Object|Function} options.tileSource - The TileSource of the item.
* @param {Number} [options.index] The index of the item. Added on top of
* all other items if not specified.
* @param {Number} [options.x=0] The X position for the image in world coordinates.
* @param {Number} [options.y=0] The Y position for the image in world coordinates.
* @param {Number} [options.width=1] The width for the image in world coordinates.
* @param {Number} [options.height] The height for the image in world coordinates.
* @returns {OpenSeadragon.Viewer} Chainable.
* @fires OpenSeadragon.Viewer.event:add-layer
* @fires OpenSeadragon.Viewer.event:add-layer-failed
* @fires OpenSeadragon.World.event:add-item
* @fires OpenSeadragon.Viewer.event:add-item-failed
*/
addLayer: function( options ) {
addTiledImage: function( options ) {
$.console.assert(options, "[Viewer.addTiledImage] options is required");
$.console.assert(options.tileSource, "[Viewer.addTiledImage] options.tileSource is required");
var _this = this,
tileSource = options.tileSource;
if ( !this.isOpen() ) {
throw new Error( "An image must be loaded before adding layers." );
}
if ( !tileSource ) {
throw new Error( "No tile source provided as new layer." );
}
if ( this.collectionMode ) {
throw new Error( "Layers not supported in collection mode." );
throw new Error( "An image must be loaded before adding additional images." );
}
function raiseAddLayerFailed( event ) {
function raiseAddItemFailed( event ) {
/**
* Raised when an error occurs while adding a layer.
* @event add-layer-failed
* Raised when an error occurs while adding a item.
* @event add-item-failed
* @memberOf OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
* @property {String} message
* @property {String} source
* @property {Object} options The options passed to the addLayer method.
* @property {Object} options The options passed to the addTiledImage method.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
_this.raiseEvent( 'add-layer-failed', event );
_this.raiseEvent( 'add-item-failed', event );
}
getTileSourceImplementation( this, tileSource, function( tileSource ) {
if ( tileSource instanceof Array ) {
raiseAddLayerFailed({
message: "Sequences can not be added as layers.",
raiseAddItemFailed({
message: "[Viewer.addTiledImage] Sequences can not be added.",
source: tileSource,
options: options
});
@ -1113,88 +1108,87 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
debugMode: _this.debugMode,
debugGridColor: _this.debugGridColor
});
_this.world.addItem( tiledImage );
_this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
if ( options.level !== undefined ) {
_this.world.setItemLevel( tiledImage, options.level );
}
THIS[ _this.hash ].forceRedraw = true;
/**
* Raised when a layer is successfully added.
* @event add-layer
* @memberOf OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
* @property {Object} options The options passed to the addLayer method.
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
_this.raiseEvent( 'add-layer', {
options: options,
drawer: tiledImage
_this.world.addItem( tiledImage, {
index: options.index
});
}, function( event ) {
event.options = options;
raiseAddLayerFailed(event);
raiseAddItemFailed(event);
} );
},
/**
* @function
* @private
*/
addLayer: function( options ) {
var self = this;
$.console.error( "[Viewer.addLayer] this function is deprecated; use Viewer.addTiledImage() instead." );
var addItemHandler = function(event) {
self.world.removeHandler("add-item", addItemHandler);
self.raiseEvent("add-layer", {
options: options,
drawer: event.item
});
};
var failureHandler = function(event) {
self.removeHandler("add-item-failed", failureHandler);
self.raiseEvent("add-layer-failed", event);
};
this.world.addHandler("add-item", addItemHandler);
this.addHandler("add-item-failed", failureHandler);
this.addTiledImage(options);
return this;
},
/**
* Get the layer at the specified level.
* @param {Number} level The layer to retrieve level.
* @returns {OpenSeadragon.Drawer} The layer at the specified level.
* @function
* @private
*/
getLayerAtLevel: function( level ) {
$.console.error( "[Viewer.getLayerAtLevel] this function is deprecated." );
return null;
$.console.error( "[Viewer.getLayerAtLevel] this function is deprecated; use World.getItemAt() instead." );
return this.world.getItemAt(level);
},
/**
* Get the level of the layer associated with the given drawer or -1 if not
* present.
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer.
* @returns {Number} The level of the layer or -1 if not present.
* @function
* @private
*/
getLevelOfLayer: function( drawer ) {
$.console.error( "[Viewer.getLevelOfLayer] this function is deprecated." );
return -1;
$.console.error( "[Viewer.getLevelOfLayer] this function is deprecated; use World.getIndexOfItem() instead." );
return this.world.getIndexOfItem(drawer);
},
/**
* Get the number of layers used.
* @returns {Number} The number of layers used.
* @function
* @private
*/
getLayersCount: function() {
$.console.error( "[Viewer.getLayersCount] this function is deprecated." );
return 0;
$.console.error( "[Viewer.getLayersCount] this function is deprecated; use World.getItemCount() instead." );
return this.world.getItemCount();
},
/**
* Change the level of a layer so that it appears over or under others.
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the changing
* level layer.
* @param {Number} level The new level
* @returns {OpenSeadragon.Viewer} Chainable.
* @fires OpenSeadragon.Viewer.event:layer-level-changed
* @function
* @private
*/
setLayerLevel: function( drawer, level ) {
$.console.error( "[Viewer.setLayerLevel] this function is deprecated." );
return this;
$.console.error( "[Viewer.setLayerLevel] this function is deprecated; use World.setItemIndex() instead." );
return this.world.setItemIndex(drawer, level);
},
/**
* Remove a layer. If there is only one layer, close the viewer.
* @function
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer
* to remove
* @returns {OpenSeadragon.Viewer} Chainable.
* @fires OpenSeadragon.Viewer.event:remove-layer
* @private
*/
removeLayer: function( drawer ) {
$.console.error( "[Viewer.removeLayer] this function is deprecated." );
return this;
$.console.error( "[Viewer.removeLayer] this function is deprecated; use World.removeItem() instead." );
return this.world.removeItem(drawer);
},
/**
@ -1896,6 +1890,16 @@ function openTileSource( viewer, source, options ) {
viewer: _this
});
_this.world.addHandler('add-item', function(event) {
_this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
THIS[ _this.hash ].forceRedraw = true;
});
_this.world.addHandler('remove-item', function(event) {
_this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
THIS[ _this.hash ].forceRedraw = true;
});
_this.drawer = new $.Drawer({
viewer: _this,
viewport: _this.viewport,
@ -1929,7 +1933,6 @@ function openTileSource( viewer, source, options ) {
});
_this.world.addItem( tiledImage );
_this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
_this.viewport.goHome( true );
// Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons

View File

@ -35,41 +35,77 @@
(function( $ ){
/**
* Keeps track of all of the tiled images in the scene.
*
* @class World
* @classdesc
*/
*
* @memberof OpenSeadragon
* @extends OpenSeadragon.EventSource
* @param {OpenSeadragon.Options} options - World options.
**/
$.World = function( options ) {
$.console.assert( options.viewer, "[World] options.viewer is required" );
$.EventSource.call( this );
this.viewer = options.viewer;
this._items = [];
this._figureSizes();
};
$.World.prototype = /** @lends OpenSeadragon.World.prototype */{
addItem: function( item ) {
$.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.World.prototype */{
/**
* Add the specified item.
* @param {OpenSeadragon.TiledImage} item - The item to add.
* @param {Number} options.index - index for the item (optional).
* @fires OpenSeadragon.World.event:add-item
*/
addItem: function( item, options ) {
$.console.assert(item, "[World.addItem] item is required");
$.console.assert(item instanceof $.TiledImage, "[World.addItem] only TiledImages supported at this time");
options = options || {};
if (options.index !== undefined) {
var index = Math.max(0, Math.min(this._items.length, options.index));
this._items.splice(index, 0, item);
} else {
this._items.push( item );
this._figureSizes();
},
/**
* Get the item at the specified level.
* @param {Number} level The item to retrieve level.
* @returns {OpenSeadragon.TiledImage} The item at the specified level.
*/
getItemAt: function( level ) {
if ( level >= this._items.length ) {
throw new Error( "Level bigger than number of items." );
}
return this._items[ level ];
this._figureSizes();
/**
* Raised when an item is added to the World.
* @event add-item
* @memberOf OpenSeadragon.World
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the World which raised the event.
* @property {OpenSeadragon.Drawer} item - The item that has been added
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.raiseEvent( 'add-item', {
item: item
} );
},
/**
* Get the level of the given item or -1 if not present.
* @param {OpenSeadragon.TiledImage} item The item.
* @returns {Number} The level of the item or -1 if not present.
* Get the item at the specified index.
* @param {Number} index - The item's index.
* @returns {OpenSeadragon.TiledImage} The item at the specified index.
*/
getLevelOfItem: function( item ) {
getItemAt: function( index ) {
$.console.assert(index !== 'undefined', "[World.getItemAt] index is required");
return this._items[ index ];
},
/**
* Get the index of the given item or -1 if not present.
* @param {OpenSeadragon.TiledImage} item - The item.
* @returns {Number} The index of the item or -1 if not present.
*/
getIndexOfItem: function( item ) {
$.console.assert(item, "[World.getIndexOfItem] item is required");
return $.indexOf( this._items, item );
},
@ -82,52 +118,56 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
},
/**
* Change the level of a layer so that it appears over or under others.
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the changing
* level layer.
* @param {Number} level The new level
* @fires OpenSeadragon.Viewer.event:layer-level-changed
* Change the index of a item so that it appears over or under others.
* @param {OpenSeadragon.TiledImage} item - The item to move.
* @param {Number} index - The new index.
* @fires OpenSeadragon.World.event:item-index-changed
*/
setItemLevel: function( item, level ) {
var oldLevel = this.getLevelOfItem( item );
setItemIndex: function( item, index ) {
$.console.assert(item, "[World.setItemIndex] item is required");
$.console.assert(index !== 'undefined', "[World.setItemIndex] index is required");
if ( level >= this._items.length ) {
throw new Error( "Level bigger than number of layers." );
var oldIndex = this.getIndexOfItem( item );
if ( index >= this._items.length ) {
throw new Error( "Index bigger than number of layers." );
}
if ( level === oldLevel || oldLevel === -1 ) {
if ( index === oldIndex || oldIndex === -1 ) {
return;
}
this._items.splice( oldLevel, 1 );
this._items.splice( level, 0, item );
this._items.splice( oldIndex, 1 );
this._items.splice( index, 0, item );
/**
* Raised when the order of the layers has been changed.
* @event layer-level-changed
* @memberOf OpenSeadragon.Viewer
* Raised when the order of the indexes has been changed.
* @event item-index-changed
* @memberOf OpenSeadragon.World
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
* @property {OpenSeadragon.Drawer} drawer - The drawer which level has
* @property {OpenSeadragon.World} eventSource - A reference to the World which raised the event.
* @property {OpenSeadragon.TiledImage} item - The item whose index has
* been changed
* @property {Number} previousLevel - The previous level of the drawer
* @property {Number} newLevel - The new level of the drawer
* @property {Number} previousIndex - The previous index of the item
* @property {Number} newIndex - The new index of the item
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
// TODO: deprecate
this.viewer.raiseEvent( 'layer-level-changed', {
drawer: item,
previousLevel: oldLevel,
newLevel: level
this.raiseEvent( 'item-index-changed', {
item: item,
previousIndex: oldIndex,
newIndex: index
} );
},
/**
* Remove a layer. If there is only one layer, close the viewer.
* Remove an item.
* @function
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer
* to remove
* @fires OpenSeadragon.Viewer.event:remove-layer
* @param {OpenSeadragon.TiledImage} item - The item to remove.
* @fires OpenSeadragon.World.event:remove-item
*/
removeItem: function( item ) {
$.console.assert(item, "[World.removeItem] item is required");
var index = this._items.indexOf( item );
if ( index === -1 ) {
return;
@ -137,30 +177,41 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
this._figureSizes();
/**
* Raised when a layer is removed.
* @event remove-layer
* @memberOf OpenSeadragon.Viewer
* Raised when a item is removed.
* @event remove-item
* @memberOf OpenSeadragon.World
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
* @property {OpenSeadragon.World} eventSource - A reference to the World which raised the event.
* @property {OpenSeadragon.TiledImage} item - The item's underlying item.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
// TODO: deprecate
this.raiseEvent( 'remove-layer', { drawer: item } );
this.raiseEvent( 'remove-item', { item: item } );
},
resetTiles: function() {
/**
* Clears all tiles and triggers updates for all items.
* @function
*/
resetItems: function() {
for ( var i = 0; i < this._items.length; i++ ) {
this._items[i].reset();
}
},
/**
* Updates (i.e. draws) all items.
* @function
*/
update: function() {
for ( var i = 0; i < this._items.length; i++ ) {
this._items[i].update();
}
},
/**
* @function
* @returns {Boolean} true if any items need updating.
*/
needsUpdate: function() {
for ( var i = 0; i < this._items.length; i++ ) {
if ( this._items[i].needsUpdate() ) {
@ -170,18 +221,29 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
return false;
},
/**
* @function
* @returns {OpenSeadragon.Rect} the smallest rectangle that encloses all items, in world coordinates.
*/
getHomeBounds: function() {
return this._homeBounds.clone();
},
getContentSize: function() {
return this._contentSize.clone();
},
/**
* To facilitate zoom constraints, we keep track of the pixel density of the
* densest item in the World (i.e. the item whose content size to world size
* ratio is the highest) and save it as this "content factor".
* @function
* @returns {Number} the number of content units per world unit.
*/
getContentFactor: function() {
return this._contentFactor;
},
/**
* @function
* @private
*/
_figureSizes: function() {
if ( !this._items.length ) {
this._homeBounds = new $.Rect(0, 0, 1, 1);
@ -209,6 +271,6 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
this._contentSize = new $.Point(this._homeBounds.width * this._contentFactor,
this._homeBounds.height * this._contentFactor);
}
};
});
}( OpenSeadragon ));