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