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