Trevor Parscal has uploaded a new change for review. https://gerrit.wikimedia.org/r/113163
Change subject: [WIP] Centralize image handling into a stand-alone model ...................................................................... [WIP] Centralize image handling into a stand-alone model Unify the access of additional image information by abstracting it into a model. TODO: * Make MediaEdit dialog use this model * Add events for responding to changes * More restructuring and such Change-Id: I017a017924f544cc8bc9b7d8245335759ae0e890 --- M VisualEditor.php M modules/ve-mw/ce/nodes/ve.ce.MWImageNode.js A modules/ve-mw/dm/models/ve.dm.MWImageModel.js M modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js 4 files changed, 179 insertions(+), 78 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/63/113163/1 diff --git a/VisualEditor.php b/VisualEditor.php index 56edb22..900d083 100644 --- a/VisualEditor.php +++ b/VisualEditor.php @@ -547,6 +547,7 @@ 'modules/ve-mw/dm/metaitems/ve.dm.MWTOCDisableMetaItem.js', 'modules/ve-mw/dm/metaitems/ve.dm.MWTOCForceMetaItem.js', + 'modules/ve-mw/dm/models/ve.dm.MWImageModel.js', 'modules/ve-mw/dm/models/ve.dm.MWTransclusionModel.js', 'modules/ve-mw/dm/models/ve.dm.MWTransclusionPartModel.js', 'modules/ve-mw/dm/models/ve.dm.MWTransclusionContentModel.js', diff --git a/modules/ve-mw/ce/nodes/ve.ce.MWImageNode.js b/modules/ve-mw/ce/nodes/ve.ce.MWImageNode.js index 152d8f6..959af0e 100644 --- a/modules/ve-mw/ce/nodes/ve.ce.MWImageNode.js +++ b/modules/ve-mw/ce/nodes/ve.ce.MWImageNode.js @@ -131,36 +131,12 @@ /** * Fetch the original dimensions from the API * - * @returns {jQuery.Promise} Promise from getImageInfo + * @returns {jQuery.Promise} Promise from ve.dm.MWImageModel#static-method-getInfo */ ve.ce.MWImageNode.prototype.fetchDimensions = function () { - return this.getModel().getImageInfo() - .done( ve.bind( function ( imageInfo ) { - var svgMaxSize, maxDimensions, - dimensions = { - 'width': imageInfo.width, - 'height': imageInfo.height - }; - this.setOriginalDimensions( dimensions ); - - if ( imageInfo.mediatype === 'BITMAP' ) { - maxDimensions = dimensions; - } else if ( imageInfo.mediatype === 'DRAWING' ) { - svgMaxSize = mw.config.get( 'wgVisualEditor' ).svgMaxSize; - if ( this.getRatio() > 1 ) { - maxDimensions = { - 'width': Math.round( svgMaxSize * this.getRatio() ), - 'height': svgMaxSize - }; - } else { - maxDimensions = { - 'width': svgMaxSize, - 'height': Math.round( svgMaxSize / this.getRatio() ) - }; - } - } - if ( maxDimensions ) { - this.setMaxDimensions( maxDimensions ); - } + return ve.dm.MWImageModel.static.getInfo( this.getModel().getFilename() ) + .done( ve.bind( function ( info ) { + this.setOriginalDimensions( info.originalDimensions ); + this.setMaxDimensions( info.maxDimensions ); }, this ) ); }; diff --git a/modules/ve-mw/dm/models/ve.dm.MWImageModel.js b/modules/ve-mw/dm/models/ve.dm.MWImageModel.js new file mode 100644 index 0000000..5490064 --- /dev/null +++ b/modules/ve-mw/dm/models/ve.dm.MWImageModel.js @@ -0,0 +1,173 @@ +/*! + * VisualEditor DataModel MWImageModel class. + * + * @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/*global mw */ + +/** + * MediaWiki image model. + * + * @class + * @mixins OO.EventEmitter + * @mixins ve.Scalable + * + * @constructor + */ +ve.dm.MWImageModel = function VeDmMWImageModel() { + // Mixin constructors + OO.EventEmitter.call( this ); + ve.Scalable.call( this ); + + // Properties + this.viewNode = null; + this.modelNode = null; + this.mediaType = null; +}; + +/* Inheritance */ + +OO.mixinClass( ve.dm.MWImageModel, OO.EventEmitter ); +OO.mixinClass( ve.dm.MWImageModel, ve.Scalable ); + +/* Events */ + +/** + * @event change + */ + +/* Static Properties */ + +ve.dm.MWImageModel.static.infoCache = {}; + +/* Static Methods */ + +/** + * Get the original size of the image object from the API, if it exists + * + * @static + * @param {string} filename Image file name + * @returns {jQuery.Promise} Promise which resolves with an info object containing width, height and + * mediatype properties + */ +ve.dm.MWImageModel.static.getInfo = function ( filename ) { + var deferred = $.Deferred(), + cache = this.infoCache; + + if ( cache[filename] ) { + deferred.resolve( cache[filename] ); + } else { + // Get image info from server + ve.init.mw.Target.static.apiRequest( + { + 'action': 'query', + 'prop': 'imageinfo', + 'indexpageids': '1', + 'iiprop': 'size|mediatype', + 'titles': filename + }, + { 'type': 'POST' } + ) + .done( function ( res ) { + var svgMaxSize, + page = res.query && res.query.pages[res.query.pageids[0]], + info = page && page.imageinfo && page.imageinfo[0], + originalDimensions = { + 'width': info.width, + 'height': info.height + }, + maxDimensions = originalDimensions, + ratio = originalDimensions.width / originalDimensions.height; + + // Calculate max dimensions for drawings + if ( info.mediatype === 'DRAWING' ) { + svgMaxSize = mw.config.get( 'wgVisualEditor' ).svgMaxSize; + maxDimensions = ratio > 1 ? + { 'width': Math.round( svgMaxSize * ratio ), 'height': svgMaxSize } : + { 'width': svgMaxSize, 'height': Math.round( svgMaxSize / ratio ) }; + } + + if ( info ) { + info = { + 'originalDimensions': originalDimensions, + 'maxDimensions': maxDimensions, + 'mediaType': info.mediatype + }; + // Store result and resolve + cache[filename] = info; + deferred.resolve( info ); + } else { + deferred.reject(); + } + } ) + .fail( function () { + deferred.reject(); + } ); + } + + return deferred.promise(); +}; + +/* Methods */ + +/** + * Load from image data, and fetch additional info from server. + * + * @param {ve.ce.ImageNode} view Image node + * @returns {jQuery.Promise} Promise, resolved when info is loaded + */ +ve.dm.MWImageModel.prototype.load = function ( view ) { + var model = view.getModel(), + deferred = $.Deferred(); + + // Get dimensional info + this.setPropertiesFromScalable( view ); + + // Get additional info from API + this.constructor.static.getInfo( model.getFilename() ) + .done( ve.bind( function ( info ) { + this.setOriginalDimensions( info.originalDimensions ); + this.setMaxDimensions( info.maxDimensions ); + this.setMediaType( info.mediaType ); + }, this ) ) + .alaways( ve.bind( function () { + deferred.resolve(); + }, this ) ); + + return deferred.promise(); +}; + +/** + * Get plain object representation of image. + * + * @returns {Object|null} Plain object representation, or null if empty + */ +ve.dm.MWImageModel.prototype.getPlainObject = function () { + return { + // TODO: Export properties in a format compatible with Parsoid image attributes + }; +}; + +/** + * Get symbolic name of media type. + * + * Example values: "BITMAP" for JPEG or PNG images; "DRAWING" for SVG graphics + * + * @returns {string|null} Symbolic media type name, or null if empty + */ +ve.dm.MWImageModel.prototype.getMediaType = function () { + return this.mediaType; +}; + +/** + * Set symbolic name of media type. + * + * @see #getMediaType. + * + * @returns {string} Symbolic media type name + */ +ve.dm.MWImageModel.prototype.setMediaType = function ( type ) { + this.mediaType = type; +}; diff --git a/modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js b/modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js index 340a6d5..43d1ef2 100644 --- a/modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js +++ b/modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js @@ -27,55 +27,6 @@ /* Methods */ /** - * Get the original size of the media object from the API, if it exists - * - * @returns {jQuery.Promise} Promise which resolves with a width, height and mediatype object - */ -ve.dm.MWImageNode.prototype.getImageInfo = function () { - var node = this, - store = this.getDocument().getStore(), - index = store.indexOfHash( this.getSizeHash() ), - deferred = $.Deferred(); - - if ( index ) { - // The dimensions already stored - deferred.resolve( store.value( index ) ); - } else { - // Look for the media size through the API - ve.init.mw.Target.static.apiRequest( { - 'action': 'query', - 'prop': 'imageinfo', - 'indexpageids': '1', - 'iiprop': 'size|mediatype', - 'titles': this.getFilename() - }, { 'type': 'POST' } ) - .done( function ( resp ) { - var originalSize, - page = resp.query && resp.query.pages[resp.query.pageids[0]], - imageinfo = page && page.imageinfo && page.imageinfo[0]; - - if ( imageinfo ) { - originalSize = { - 'width': imageinfo.width, - 'height': imageinfo.height, - 'mediatype': imageinfo.mediatype - }; - - // Store result and resolve - store.index( originalSize, node.getSizeHash() ); - deferred.resolve( originalSize ); - } else { - deferred.reject(); - } - } ) - .fail( function () { - deferred.reject(); - } ); - } - return deferred.promise(); -}; - -/** * Get the normalised filename of the image * * @returns {string} Filename -- To view, visit https://gerrit.wikimedia.org/r/113163 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I017a017924f544cc8bc9b7d8245335759ae0e890 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Trevor Parscal <tpars...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits