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