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 LoadingBar control of Cocos UI.
 28  * @class
 29  * @extends ccui.Widget
 30  *
 31  * @property {ccui.LoadingBar.TYPE_LEFT | ccui.LoadingBar.TYPE_RIGHT}   direction   - The progress direction of loadingbar
 32  * @property {Number}               percent     - The current progress of loadingbar
 33  */
 34 ccui.LoadingBar = ccui.Widget.extend(/** @lends ccui.LoadingBar# */{
 35     _direction: null,
 36     _percent: 100,
 37     _totalLength: 0,
 38     _barRenderer: null,
 39     _renderBarTexType: ccui.Widget.LOCAL_TEXTURE,
 40     _barRendererTextureSize: null,
 41     _scale9Enabled: false,
 42     _prevIgnoreSize: true,
 43     _capInsets: null,
 44     _textureFile: "",
 45     _isTextureLoaded: false,
 46     _className: "LoadingBar",
 47     _barRendererAdaptDirty: true,
 48 
 49     /**
 50      * allocates and initializes a UILoadingBar.                                                        <br/>
 51      * Constructor of ccui.LoadingBar, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 52      * @param {string} textureName
 53      * @param {Number} percentage
 54      * @example
 55      * // example
 56      * var uiLoadingBar = new ccui.LoadingBar;
 57      */
 58     ctor: function (textureName, percentage) {
 59         this._direction = ccui.LoadingBar.TYPE_LEFT;
 60         this._barRendererTextureSize = cc.size(0, 0);
 61         this._capInsets = cc.rect(0, 0, 0, 0);
 62         ccui.Widget.prototype.ctor.call(this);
 63 
 64         if(textureName !== undefined)
 65             this.loadTexture(textureName);
 66         if(percentage !== undefined)
 67             this.setPercent(percentage);
 68     },
 69 
 70     _initRenderer: function () {
 71         //todo use Scale9Sprite
 72         this._barRenderer = new cc.Sprite();
 73         this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
 74         this._barRenderer.setAnchorPoint(0.0, 0.5);
 75     },
 76 
 77     /**
 78      * Changes the progress direction of LoadingBar.                           <br/>
 79      * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
 80      * @param {ccui.LoadingBar.TYPE_LEFT | ccui.LoadingBar.TYPE_RIGHT} dir
 81      */
 82     setDirection: function (dir) {
 83         if (this._direction === dir)
 84             return;
 85         this._direction = dir;
 86         switch (this._direction) {
 87             case ccui.LoadingBar.TYPE_LEFT:
 88                 this._barRenderer.setAnchorPoint(0, 0.5);
 89                 this._barRenderer.setPosition(0, this._contentSize.height*0.5);
 90                 if (!this._scale9Enabled)  
 91                     this._barRenderer.setFlippedX(false);  
 92 
 93                 break;
 94             case ccui.LoadingBar.TYPE_RIGHT:
 95                 this._barRenderer.setAnchorPoint(1, 0.5);
 96                 this._barRenderer.setPosition(this._totalLength,this._contentSize.height*0.5);
 97                 if (!this._scale9Enabled)  
 98                     this._barRenderer.setFlippedX(true);  
 99 
100                 break;
101         }
102     },
103 
104     /**
105      * Returns the progress direction of LoadingBar.                               <br/>
106      * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
107      * @returns {ccui.LoadingBar.TYPE_LEFT | ccui.LoadingBar.TYPE_RIGHT}
108      */
109     getDirection: function () {
110         return this._direction;
111     },
112 
113     /**
114      * Loads texture for LoadingBar.
115      * @param {String} texture
116      * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
117      */
118     loadTexture: function (texture, texType) {
119         if (!texture)
120             return;
121         texType = texType || ccui.Widget.LOCAL_TEXTURE;
122         this._renderBarTexType = texType;
123         this._textureFile = texture;
124         var barRenderer = this._barRenderer;
125 
126         var self = this;
127         if(!barRenderer._textureLoaded){
128             barRenderer.addEventListener("load", function(){
129                 self.loadTexture(self._textureFile, self._renderBarTexType);
130                 self._setPercent(self._percent);
131             });
132         }
133 
134         switch (this._renderBarTexType) {
135             case ccui.Widget.LOCAL_TEXTURE:
136                 barRenderer.initWithFile(texture);
137                 break;
138             case ccui.Widget.PLIST_TEXTURE:
139                 barRenderer.initWithSpriteFrameName(texture);
140                 break;
141             default:
142                 break;
143         }
144 
145         var bz = barRenderer.getContentSize();
146         this._barRendererTextureSize.width = bz.width;
147         this._barRendererTextureSize.height = bz.height;
148 
149         switch (this._direction) {
150             case ccui.LoadingBar.TYPE_LEFT:
151                 barRenderer.setAnchorPoint(0,0.5);
152                 if (!this._scale9Enabled)
153                     barRenderer.setFlippedX(false);
154                 break;
155             case ccui.LoadingBar.TYPE_RIGHT:
156                 barRenderer.setAnchorPoint(1,0.5);
157                 if (!this._scale9Enabled)
158                     barRenderer.setFlippedX(true);
159                 break;
160         }
161         if (this._scale9Enabled)
162             barRenderer.setCapInsets(this._capInsets);
163 
164         this._updateChildrenDisplayedRGBA();
165         this._barRendererScaleChangedWithSize();
166         this._updateContentSizeWithTextureSize(this._barRendererTextureSize);
167         this._barRendererAdaptDirty = true;
168         this._findLayout();
169     },
170 
171     /**
172      * Sets if LoadingBar is using scale9 renderer.
173      * @param {Boolean} enabled
174      */
175     setScale9Enabled: function (enabled) {
176         //todo use setScale9Enabled
177         if (this._scale9Enabled === enabled)
178             return;
179         this._scale9Enabled = enabled;
180         this.removeProtectedChild(this._barRenderer);
181 
182         this._barRenderer = this._scale9Enabled ? new ccui.Scale9Sprite() : new cc.Sprite();
183 
184         this.loadTexture(this._textureFile, this._renderBarTexType);
185         this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
186         if (this._scale9Enabled) {
187             var ignoreBefore = this._ignoreSize;
188             this.ignoreContentAdaptWithSize(false);
189             this._prevIgnoreSize = ignoreBefore;
190         } else
191             this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
192         this.setCapInsets(this._capInsets);
193         this.setPercent(this._percent);
194         this._barRendererAdaptDirty = true;
195     },
196 
197     /**
198      * Returns LoadingBar is using scale9 renderer or not..
199      * @returns {Boolean}
200      */
201     isScale9Enabled: function () {
202         return this._scale9Enabled;
203     },
204 
205     /**
206      * Sets capinsets for LoadingBar, if LoadingBar is using scale9 renderer.
207      * @param {cc.Rect} capInsets
208      */
209     setCapInsets: function (capInsets) {
210         if(!capInsets)
211             return;
212         var locInsets = this._capInsets;
213         locInsets.x = capInsets.x;
214         locInsets.y = capInsets.y;
215         locInsets.width = capInsets.width;
216         locInsets.height = capInsets.height;
217 
218         if (this._scale9Enabled)
219             this._barRenderer.setCapInsets(capInsets);
220     },
221 
222     /**
223      * Returns cap insets for loadingBar.
224      * @returns {cc.Rect}
225      */
226     getCapInsets: function () {
227         return cc.rect(this._capInsets);
228     },
229 
230     /**
231      * The current progress of loadingBar
232      * @param {number} percent   percent value from 1 to 100.
233      */
234     setPercent: function (percent) {
235         if(percent > 100)
236             percent = 100;
237         if(percent < 0)
238             percent = 0;
239         if (percent === this._percent)
240             return;
241         this._percent = percent;
242         this._setPercent(percent);
243     },
244 
245     _setPercent: function(){
246         var res, rect, spriteRenderer, spriteTextureRect;
247 
248         if (this._totalLength <= 0)
249             return;
250         res = this._percent / 100.0;
251 
252         if (this._scale9Enabled)
253             this._setScale9Scale();
254         else {
255             spriteRenderer = this._barRenderer;
256             spriteTextureRect = this._barRendererTextureSize;
257             rect = spriteRenderer.getTextureRect();
258             rect.width = spriteTextureRect.width * res;
259             spriteRenderer.setTextureRect(
260                 cc.rect(
261                     rect.x,
262                     rect.y,
263                     spriteTextureRect.width * res,
264                     spriteTextureRect.height
265                 ),
266                 spriteRenderer._rectRotated
267             );
268         }
269     },
270 
271     /**
272      * Sets the contentSize of ccui.LoadingBar
273      * @override
274      * @param {Number|cc.Size} contentSize
275      * @param {Number} [height]
276      */
277     setContentSize: function(contentSize, height){
278         ccui.Widget.prototype.setContentSize.call(this, contentSize, height);
279         this._totalLength = (height === undefined) ? contentSize.width : contentSize;
280     },
281 
282     /**
283      * Returns the progress direction of LoadingBar.
284      * @returns {number} percent value from 1 to 100.
285      */
286     getPercent: function () {
287         return this._percent;
288     },
289 
290     _onSizeChanged: function () {
291         ccui.Widget.prototype._onSizeChanged.call(this);
292         this._barRendererAdaptDirty = true;
293     },
294 
295     _adaptRenderers: function(){
296         if (this._barRendererAdaptDirty){
297             this._barRendererScaleChangedWithSize();
298             this._barRendererAdaptDirty = false;
299         }
300     },
301 
302     /**
303      * Ignore the LoadingBar's custom size,  if ignore is true that LoadingBar will ignore it's custom size, use renderer's content size, false otherwise.
304      * @override
305      * @param {Boolean}ignore
306      */
307     ignoreContentAdaptWithSize: function (ignore) {
308         if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
309             ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
310             this._prevIgnoreSize = ignore;
311         }
312     },
313 
314     /**
315      * Returns the texture size of renderer.
316      * @returns {cc.Size|*}
317      */
318     getVirtualRendererSize:function(){
319         return cc.size(this._barRendererTextureSize);
320     },
321 
322     /**
323      * Returns the renderer of ccui.LoadingBar
324      * @override
325      * @returns {cc.Node}
326      */
327     getVirtualRenderer: function () {
328         return this._barRenderer;
329     },
330 
331     _barRendererScaleChangedWithSize: function () {
332         var locBarRender = this._barRenderer, locContentSize = this._contentSize;
333         if(this._unifySize){
334             this._totalLength = this._contentSize.width;
335             this.setPercent(this._percent);
336         }else if (this._ignoreSize) {
337             if (!this._scale9Enabled) {
338                 this._totalLength = this._barRendererTextureSize.width;
339                 locBarRender.setScale(1.0);
340             }
341         } else {
342             this._totalLength = locContentSize.width;
343             if (this._scale9Enabled){
344                 this._setScale9Scale();
345                 locBarRender.setScale(1.0);
346             } else {
347                 var textureSize = this._barRendererTextureSize;
348                 if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
349                     locBarRender.setScale(1.0);
350                     return;
351                 }
352                 var scaleX = locContentSize.width / textureSize.width;
353                 var scaleY = locContentSize.height / textureSize.height;
354                 locBarRender.setScaleX(scaleX);
355                 locBarRender.setScaleY(scaleY);
356             }
357         }
358         switch (this._direction) {
359             case ccui.LoadingBar.TYPE_LEFT:
360                 locBarRender.setPosition(0, locContentSize.height * 0.5);
361                 break;
362             case ccui.LoadingBar.TYPE_RIGHT:
363                 locBarRender.setPosition(this._totalLength, locContentSize.height * 0.5);
364                 break;
365             default:
366                 break;
367         }
368     },
369 
370     _setScale9Scale: function () {
371         var width = (this._percent) / 100 * this._totalLength;
372         this._barRenderer.setPreferredSize(cc.size(width, this._contentSize.height));
373     },
374 
375     /**
376      * Returns the "class name" of widget.
377      * @returns {string}
378      */
379     getDescription: function () {
380         return "LoadingBar";
381     },
382 
383     _createCloneInstance: function () {
384         return new ccui.LoadingBar();
385     },
386 
387     _copySpecialProperties: function (loadingBar) {
388         if(loadingBar instanceof ccui.LoadingBar){
389             this._prevIgnoreSize = loadingBar._prevIgnoreSize;
390             this.setScale9Enabled(loadingBar._scale9Enabled);
391             this.loadTexture(loadingBar._textureFile, loadingBar._renderBarTexType);
392             this.setCapInsets(loadingBar._capInsets);
393             this.setPercent(loadingBar._percent);
394             this.setDirection(loadingBar._direction);
395         }
396     }
397 });
398 
399 var _p = ccui.LoadingBar.prototype;
400 
401 // Extended properties
402 /** @expose */
403 _p.direction;
404 cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
405 /** @expose */
406 _p.percent;
407 cc.defineGetterSetter(_p, "percent", _p.getPercent, _p.setPercent);
408 
409 _p = null;
410 
411 /**
412  * Allocates and initializes a UILoadingBar.
413  * @deprecated since v3.0, please use new ccui.LoadingBar() instead.
414  * @param {string} textureName
415  * @param {Number} percentage
416  * @return {ccui.LoadingBar}
417  */
418 ccui.LoadingBar.create = function (textureName, percentage) {
419     return new ccui.LoadingBar(textureName, percentage);
420 };
421 
422 // Constants
423 //loadingBar Type
424 
425 /**
426  * The left direction of ccui.LoadingBar.
427  * @constant
428  * @type {number}
429  */
430 ccui.LoadingBar.TYPE_LEFT = 0;
431 /**
432  * The right direction of ccui.LoadingBar.
433  * @constant
434  * @type {number}
435  */
436 ccui.LoadingBar.TYPE_RIGHT = 1;
437 
438 /**
439  * The zOrder value of ccui.LoadingBar's renderer.
440  * @constant
441  * @type {number}
442  */
443 ccui.LoadingBar.RENDERER_ZORDER = -1;