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