1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * The ImageView control of Cocos GUI
 28  * @class
 29  * @extends ccui.Widget
 30  */
 31 ccui.ImageView = ccui.Widget.extend(/** @lends ccui.ImageView# */{
 32     _scale9Enabled: false,
 33     _prevIgnoreSize: true,
 34     _capInsets: null,
 35     _imageRenderer: null,
 36     _textureFile: "",
 37     _imageTexType: ccui.Widget.LOCAL_TEXTURE,
 38     _imageTextureSize: null,
 39     _className:"ImageView",
 40     _imageRendererAdaptDirty: true,
 41 
 42     /**
 43      * allocates and initializes a ccui.ImageView.
 44      * Constructor of ccui.ImageView, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 45      * @param {String} imageFileName
 46      * @param {Number} [texType==ccui.Widget.LOCAL_TEXTURE]
 47      * @example
 48      * // example
 49      * var uiImageView = new ccui.ImageView;
 50      */
 51     ctor: function (imageFileName, texType) {
 52         this._capInsets = cc.rect(0,0,0,0);
 53         this._imageTextureSize = cc.size(this._capInsets.width, this._capInsets.height);
 54         ccui.Widget.prototype.ctor.call(this);
 55         texType = texType === undefined ? 0 : texType;
 56         this._init(imageFileName, texType);
 57     },
 58 
 59     /**
 60      * Initializes an imageView. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
 61      * @param {String} imageFileName
 62      * @param {Number} [texType==ccui.Widget.LOCAL_TEXTURE]
 63      * @returns {boolean}
 64      */
 65     _init: function(imageFileName, texType){
 66         if(imageFileName === undefined)
 67             this._imageTexType = ccui.Widget.LOCAL_TEXTURE;
 68         else
 69             this.loadTexture(imageFileName, texType);
 70     },
 71 
 72     _initRenderer: function () {
 73         //todo create Scale9Sprite and setScale9Enabled(false)
 74         this._imageRenderer = new cc.Sprite();
 75         this.addProtectedChild(this._imageRenderer, ccui.ImageView.RENDERER_ZORDER, -1);
 76     },
 77 
 78     /**
 79      * Loads textures for button.
 80      * @param {String} fileName
 81      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
 82      */
 83     loadTexture: function (fileName, texType) {
 84         //todo use this code when _initRenderer use Scale9Sprite
 85         //if (!fileName || (this._textureFile == fileName && this._imageTexType == texType)) {
 86         if (!fileName) {
 87             return;
 88         }
 89         var self = this;
 90         texType = texType || ccui.Widget.LOCAL_TEXTURE;
 91         this._textureFile = fileName;
 92         this._imageTexType = texType;
 93         var imageRenderer = self._imageRenderer;
 94 
 95         if(!imageRenderer._textureLoaded){
 96             imageRenderer.addEventListener("load", function(){
 97                 self.loadTexture(self._textureFile, self._imageTexType);
 98             });
 99         }
100 
101         switch (self._imageTexType) {
102             case ccui.Widget.LOCAL_TEXTURE:
103                 if(self._scale9Enabled){
104                     imageRenderer.initWithFile(fileName);
105                     imageRenderer.setCapInsets(self._capInsets);
106                 }else{
107                     //SetTexture cannot load resource
108                     imageRenderer.initWithFile(fileName);
109                 }
110                 break;
111             case ccui.Widget.PLIST_TEXTURE:
112                 if(self._scale9Enabled){
113                     imageRenderer.initWithSpriteFrameName(fileName);
114                     imageRenderer.setCapInsets(self._capInsets);
115                 }else{
116                     //SetTexture cannot load resource
117                     imageRenderer.initWithSpriteFrameName(fileName);
118                 }
119                 break;
120             default:
121                 break;
122         }
123 
124         self._imageTextureSize = imageRenderer.getContentSize();
125 
126         this._updateChildrenDisplayedRGBA();
127 
128         self._updateContentSizeWithTextureSize(self._imageTextureSize);
129         self._imageRendererAdaptDirty = true;
130         self._findLayout();
131 
132     },
133 
134     /**
135      * Sets texture rect
136      * @param {cc.Rect} rect
137      */
138     setTextureRect: function (rect) {
139         if (!this._scale9Enabled)
140             this._imageRenderer.setTextureRect(rect);
141     },
142 
143     /**
144      * Sets if button is using scale9 renderer.
145      * @param {Boolean} able
146      */
147     setScale9Enabled: function (able) {
148         //todo setScale9Enabled
149         if (this._scale9Enabled === able)
150             return;
151 
152         this._scale9Enabled = able;
153         this.removeProtectedChild(this._imageRenderer);
154         this._imageRenderer = null;
155         if (this._scale9Enabled) {
156             this._imageRenderer = new ccui.Scale9Sprite();
157         } else {
158             this._imageRenderer = new cc.Sprite();
159         }
160         this.loadTexture(this._textureFile, this._imageTexType);
161         this.addProtectedChild(this._imageRenderer, ccui.ImageView.RENDERER_ZORDER, -1);
162         if (this._scale9Enabled) {
163             var ignoreBefore = this._ignoreSize;
164             this.ignoreContentAdaptWithSize(false);
165             this._prevIgnoreSize = ignoreBefore;
166         } else
167             this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
168         this.setCapInsets(this._capInsets);
169         this._imageRendererAdaptDirty = true;
170     },
171 
172     /**
173      * Returns ImageView is using scale9 renderer or not.
174      * @returns {Boolean}
175      */
176     isScale9Enabled:function(){
177         return this._scale9Enabled;
178     },
179 
180     /**
181      * Ignore the imageView's custom size, true that imageView will ignore it's custom size, use renderer's content size, false otherwise.
182      * @override
183      * @param {Boolean} ignore
184      */
185     ignoreContentAdaptWithSize: function (ignore) {
186         if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
187             ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
188             this._prevIgnoreSize = ignore;
189         }
190     },
191 
192     /**
193      * Sets capinsets for button, if button is using scale9 renderer.
194      * @param {cc.Rect} capInsets
195      */
196     setCapInsets: function (capInsets) {
197         if(!capInsets)
198             return;
199         var locInsets = this._capInsets;
200         locInsets.x = capInsets.x;
201         locInsets.y = capInsets.y;
202         locInsets.width = capInsets.width;
203         locInsets.height = capInsets.height;
204 
205         if (!this._scale9Enabled)
206             return;
207         this._imageRenderer.setCapInsets(capInsets);
208     },
209 
210     /**
211      * Returns cap insets of ccui.ImageView.
212      * @returns {cc.Rect}
213      */
214     getCapInsets:function(){
215         return cc.rect(this._capInsets);
216     },
217 
218     _onSizeChanged: function () {
219         ccui.Widget.prototype._onSizeChanged.call(this);
220         this._imageRendererAdaptDirty = true;
221     },
222 
223     _adaptRenderers: function(){
224         if (this._imageRendererAdaptDirty){
225             this._imageTextureScaleChangedWithSize();
226             this._imageRendererAdaptDirty = false;
227         }
228     },
229 
230     /**
231      * Returns the image's texture size.
232      * @returns {cc.Size}
233      */
234     getVirtualRendererSize: function(){
235         return cc.size(this._imageTextureSize);
236     },
237 
238     /**
239      * Returns the renderer of ccui.ImageView
240      * @override
241      * @returns {cc.Node}
242      */
243     getVirtualRenderer: function () {
244         return this._imageRenderer;
245     },
246 
247     _imageTextureScaleChangedWithSize: function () {
248         if (this._ignoreSize) {
249             if (!this._scale9Enabled)
250                 this._imageRenderer.setScale(1.0);
251         } else {
252             if (this._scale9Enabled){
253                 this._imageRenderer.setPreferredSize(this._contentSize);
254                 this._imageRenderer.setScale(1);
255             } else {
256                 var textureSize = this._imageTextureSize;
257                 if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
258                     this._imageRenderer.setScale(1.0);
259                     return;
260                 }
261                 this._imageRenderer.setScaleX(this._contentSize.width / textureSize.width);
262                 this._imageRenderer.setScaleY(this._contentSize.height / textureSize.height);
263             }
264         }
265         this._imageRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
266     },
267 
268     /**
269      * Returns the "class name" of ccui.ImageView.
270      * @override
271      * @returns {string}
272      */
273     getDescription: function () {
274         return "ImageView";
275     },
276 
277     _createCloneInstance:function(){
278         return new ccui.ImageView();
279     },
280 
281     _copySpecialProperties: function (imageView) {
282         if(imageView instanceof ccui.ImageView){
283             this._prevIgnoreSize = imageView._prevIgnoreSize;
284             this.setScale9Enabled(imageView._scale9Enabled);
285             this.loadTexture(imageView._textureFile, imageView._imageTexType);
286             this.setCapInsets(imageView._capInsets);
287         }
288     },
289     /**
290      * Sets _customSize of ccui.Widget, if ignoreSize is true, the content size is its renderer's contentSize, otherwise the content size is parameter.
291      * and updates size percent by parent content size. At last, updates its children's size and position.
292      * @param {cc.Size|Number} contentSize content size or width of content size
293      * @param {Number} [height]
294      * @override
295      */
296     setContentSize: function(contentSize, height){
297         if(height != null)
298             contentSize = cc.size(contentSize, height);
299         ccui.Widget.prototype.setContentSize.call(this, contentSize);
300         if(!this._scale9Enabled){
301             var iContentSize = this._imageRenderer.getContentSize();
302             this._imageRenderer.setScaleX(contentSize.width / iContentSize.width);
303             this._imageRenderer.setScaleY(contentSize.height / iContentSize.height);
304         }else{
305             this._imageRenderer.setContentSize(contentSize);
306         }
307 
308     }
309 
310 });
311 
312 /**
313  * Allocates and initializes a UIImageView.
314  * @deprecated since v3.0, please use new ccui.ImageView() instead.
315  * @param {string} imageFileName
316  * @param {Number} texType
317  * @return {ccui.ImageView}
318  */
319 ccui.ImageView.create = function (imageFileName, texType) {
320     return new ccui.ImageView(imageFileName, texType);
321 };
322 
323 // Constants
324 /**
325  * The zOrder value of ccui.ImageView's renderer.
326  * @constant
327  * @type {number}
328  */
329 ccui.ImageView.RENDERER_ZORDER = -1;
330