1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * slider event type
 27  * @type {Obejct}
 28  */
 29 ccs.SliderEventType = {percent_changed: 0};
 30 
 31 /**
 32  * Base class for ccs.UISlider
 33  * @class
 34  * @extends ccs.UIWidget
 35  */
 36 ccs.UISlider = ccs.UIWidget.extend(/** @lends ccs.UISlider# */{
 37     _barRenderer: null,
 38     _progressBarRenderer: null,
 39     _progressBarTextureSize: null,
 40     _slidBallNormalRenderer: null,
 41     _slidBallPressedRenderer: null,
 42     _slidBallDisabledRenderer: null,
 43     _slidBallRenderer: null,
 44     _barLength: 0,
 45     _percent: 0,
 46     _scale9Enabled: false,
 47     _prevIgnoreSize: true,
 48     _textureFile: "",
 49     _progressBarTextureFile: "",
 50     _slidBallNormalTextureFile: "",
 51     _slidBallPressedTextureFile: "",
 52     _slidBallDisabledTextureFile: "",
 53     _capInsetsBarRenderer: null,
 54     _capInsetsProgressBarRenderer: null,
 55     _sliderEventListener: null,
 56     _sliderEventSelector: null,
 57     _barTexType: null,
 58     _progressBarTexType: null,
 59     _ballNTexType: null,
 60     _ballPTexType: null,
 61     _ballDTexType: null,
 62     ctor: function () {
 63         ccs.UIWidget.prototype.ctor.call(this);
 64         this._barRenderer = null;
 65         this._progressBarRenderer = null;
 66         this._progressBarTextureSize = cc.size(0, 0);
 67         this._slidBallNormalRenderer = null;
 68         this._slidBallPressedRenderer = null;
 69         this._slidBallDisabledRenderer = null;
 70         this._slidBallRenderer = null;
 71         this._barLength = 0;
 72         this._percent = 0;
 73         this._scale9Enabled = false;
 74         this._prevIgnoreSize = true;
 75         this._textureFile = "";
 76         this._progressBarTextureFile = "";
 77         this._slidBallNormalTextureFile = "";
 78         this._slidBallPressedTextureFile = "";
 79         this._slidBallDisabledTextureFile = "";
 80         this._capInsetsBarRenderer = cc.RectZero();
 81         this._capInsetsProgressBarRenderer = cc.RectZero();
 82         this._sliderEventListener = null;
 83         this._sliderEventSelector = null;
 84         this._barTexType = ccs.TextureResType.local;
 85         this._progressBarTexType = ccs.TextureResType.local;
 86         this._ballNTexType = ccs.TextureResType.local;
 87         this._ballPTexType = ccs.TextureResType.local;
 88         this._ballDTexType = ccs.TextureResType.local;
 89     },
 90 
 91     initRenderer: function () {
 92         ccs.UIWidget.prototype.initRenderer.call(this);
 93         this._barRenderer = cc.Sprite.create();
 94         this._progressBarRenderer = cc.Sprite.create();
 95         this._progressBarRenderer.setAnchorPoint(cc.p(0.0, 0.5));
 96         this._renderer.addChild(this._barRenderer, -1);
 97         this._renderer.addChild(this._progressBarRenderer, -1);
 98         this._slidBallNormalRenderer = cc.Sprite.create();
 99         this._slidBallPressedRenderer = cc.Sprite.create();
100         this._slidBallPressedRenderer.setVisible(false);
101         this._slidBallDisabledRenderer = cc.Sprite.create();
102         this._slidBallDisabledRenderer.setVisible(false);
103         this._slidBallRenderer = cc.Node.create();
104         this._slidBallRenderer.addChild(this._slidBallNormalRenderer);
105         this._slidBallRenderer.addChild(this._slidBallPressedRenderer);
106         this._slidBallRenderer.addChild(this._slidBallDisabledRenderer);
107         this._renderer.addChild(this._slidBallRenderer);
108     },
109 
110     /**
111      * Load texture for slider bar.
112      * @param {String} fileName
113      * @param {ccs.TextureResType} texType
114      */
115     loadBarTexture: function (fileName, texType) {
116         if (!fileName) {
117             return;
118         }
119         texType = texType || ccs.TextureResType.local;
120         this._textureFile = fileName;
121         this._barTexType = texType;
122         switch (this._barTexType) {
123             case ccs.TextureResType.local:
124                 this._barRenderer.initWithFile(fileName);
125                 break;
126             case ccs.TextureResType.plist:
127                 this._barRenderer.initWithSpriteFrameName(fileName);
128                 break;
129             default:
130                 break;
131         }
132         if (this._scale9Enabled) {
133             this._barRenderer.setColor(this.getColor());
134             this._barRenderer.setOpacity(this.getOpacity());
135         }
136         else {
137             this._barRenderer.setColor(this.getColor());
138             this._barRenderer.setOpacity(this.getOpacity());
139         }
140         this.barRendererScaleChangedWithSize();
141     },
142 
143     /**
144      * Load dark state texture for slider progress bar.
145      * @param {String} fileName
146      * @param {ccs.TextureResType} texType
147      */
148     loadProgressBarTexture: function (fileName, texType) {
149         if (!fileName) {
150             return;
151         }
152         texType = texType || ccs.TextureResType.local;
153         this._progressBarTextureFile = fileName;
154         this._progressBarTexType = texType;
155         switch (this._progressBarTexType) {
156             case ccs.TextureResType.local:
157                 this._progressBarRenderer.initWithFile(fileName);
158                 break;
159             case ccs.TextureResType.plist:
160                 this._progressBarRenderer.initWithSpriteFrameName(fileName);
161                 break;
162             default:
163                 break;
164         }
165         if (this._scale9Enabled) {
166             this._progressBarRenderer.setColor(this.getColor());
167             this._progressBarRenderer.setOpacity(this.getOpacity());
168         }
169         else {
170             this._progressBarRenderer.setColor(this.getColor());
171             this._progressBarRenderer.setOpacity(this.getOpacity());
172         }
173         this._progressBarRenderer.setAnchorPoint(cc.p(0.0, 0.5));
174         var locSize = this._progressBarRenderer.getContentSize();
175         this._progressBarTextureSize.width = locSize.width;
176         this._progressBarTextureSize.height = locSize.height;
177         this.progressBarRendererScaleChangedWithSize();
178     },
179 
180     /**
181      * Sets if slider is using scale9 renderer.
182      * @param {Boolean} able
183      */
184     setScale9Enabled: function (able) {
185         if (this._scale9Enabled == able) {
186             return;
187         }
188 
189         this._scale9Enabled = able;
190         this._renderer.removeChild(this._barRenderer, true);
191         this._renderer.removeChild(this._progressBarRenderer, true);
192         this._barRenderer = null;
193         this._progressBarRenderer = null;
194         if (this._scale9Enabled) {
195             this._barRenderer = cc.Scale9Sprite.create();
196             this._progressBarRenderer = cc.Scale9Sprite.create();
197         }
198         else {
199             this._barRenderer = cc.Sprite.create();
200             this._progressBarRenderer = cc.Sprite.create();
201         }
202         this.loadBarTexture(this._textureFile, this._barTexType);
203         this.loadProgressBarTexture(this._progressBarTextureFile, this._progressBarTexType);
204         this._renderer.addChild(this._barRenderer, -1);
205         this._renderer.addChild(this._progressBarRenderer, -1);
206         if (this._scale9Enabled) {
207             var ignoreBefore = this._ignoreSize;
208             this.ignoreContentAdaptWithSize(false);
209             this._prevIgnoreSize = ignoreBefore;
210         }
211         else {
212             this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
213         }
214         this.setCapInsetsBarRenderer(this._capInsetsBarRenderer);
215         this.setCapInsetProgressBarRebderer(this._capInsetsProgressBarRenderer);
216     },
217 
218     /**
219      * override "ignoreContentAdaptWithSize" method of widget.
220      * @param {Boolean} ignore
221      */
222     ignoreContentAdaptWithSize: function (ignore) {
223         if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
224             ccs.UIWidget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
225             this._prevIgnoreSize = ignore;
226         }
227     },
228 
229     /**
230      * Sets capinsets for slider, if slider is using scale9 renderer.
231      * @param {cc.Rect} capInsets
232      */
233     setCapInsets: function (capInsets) {
234         this.setCapInsetsBarRenderer(capInsets);
235         this.setCapInsetProgressBarRebderer(capInsets);
236     },
237 
238     /**
239      * Sets capinsets for slider, if slider is using scale9 renderer.
240      * @param {cc.Rect} capInsets
241      */
242     setCapInsetsBarRenderer: function (capInsets) {
243         this._capInsetsBarRenderer = capInsets;
244         if (!this._scale9Enabled) {
245             return;
246         }
247         this._barRenderer.setCapInsets(capInsets);
248     },
249 
250     /**
251      * Sets capinsets for slider, if slider is using scale9 renderer.
252      * @param {cc.Rect} capInsets
253      */
254     setCapInsetProgressBarRebderer: function (capInsets) {
255         this._capInsetsProgressBarRenderer = capInsets;
256         if (!this._scale9Enabled) {
257             return;
258         }
259         this._progressBarRenderer.setCapInsets(capInsets);
260     },
261 
262     /**
263      * Load textures for slider ball.
264      * @param {String} normal
265      * @param {String} pressed
266      * @param {String} disabled
267      * @param {ccs.TextureResType} texType
268      */
269     loadSlidBallTextures: function (normal, pressed, disabled, texType) {
270         this.loadSlidBallTextureNormal(normal, texType);
271         this.loadSlidBallTexturePressed(pressed, texType);
272         this.loadSlidBallTextureDisabled(disabled, texType);
273     },
274 
275     /**
276      * Load normal state texture for slider ball.
277      * @param {String} normal
278      * @param {ccs.TextureResType} texType
279      */
280     loadSlidBallTextureNormal: function (normal, texType) {
281         if (!normal) {
282             return;
283         }
284         texType = texType || ccs.TextureResType.local;
285         this._slidBallNormalTextureFile = normal;
286         this._ballNTexType = texType;
287         switch (this._ballNTexType) {
288             case ccs.TextureResType.local:
289                 this._slidBallNormalRenderer.initWithFile(normal);
290                 break;
291             case ccs.TextureResType.plist:
292                 this._slidBallNormalRenderer.initWithSpriteFrameName(normal);
293                 break;
294             default:
295                 break;
296         }
297         this._slidBallNormalRenderer.setColor(this.getColor());
298         this._slidBallNormalRenderer.setOpacity(this.getOpacity());
299     },
300 
301     /**
302      * Load selected state texture for slider ball.
303      * @param {String} pressed
304      * @param {ccs.TextureResType} texType
305      */
306     loadSlidBallTexturePressed: function (pressed, texType) {
307         if (!pressed) {
308             return;
309         }
310         texType = texType || ccs.TextureResType.local;
311         this._slidBallPressedTextureFile = pressed;
312         this._ballPTexType = texType;
313         switch (this._ballPTexType) {
314             case ccs.TextureResType.local:
315                 this._slidBallPressedRenderer.initWithFile(pressed);
316                 break;
317             case ccs.TextureResType.plist:
318                 this._slidBallPressedRenderer.initWithSpriteFrameName(pressed);
319                 break;
320             default:
321                 break;
322         }
323         this._slidBallPressedRenderer.setColor(this.getColor());
324         this._slidBallPressedRenderer.setOpacity(this.getOpacity());
325     },
326 
327     /**
328      * Load dark state texture for slider ball.
329      * @param {String} disabled
330      * @param {ccs.TextureResType} texType
331      */
332     loadSlidBallTextureDisabled: function (disabled, texType) {
333         if (!disabled) {
334             return;
335         }
336         texType = texType || ccs.TextureResType.local;
337         this._slidBallDisabledTextureFile = disabled;
338         this._ballDTexType = texType;
339         switch (this._ballDTexType) {
340             case ccs.TextureResType.local:
341                 this._slidBallDisabledRenderer.initWithFile(disabled);
342                 break;
343             case ccs.TextureResType.plist:
344                 this._slidBallDisabledRenderer.initWithSpriteFrameName(disabled);
345                 break;
346             default:
347                 break;
348         }
349         this._slidBallDisabledRenderer.setColor(this.getColor());
350         this._slidBallDisabledRenderer.setOpacity(this.getOpacity());
351     },
352 
353     /**
354      * Changes the progress direction of slider.
355      * @param {number} percent
356      */
357     setPercent: function (percent) {
358         if (percent > 100) {
359             percent = 100;
360         }
361         if (percent < 0) {
362             percent = 0;
363         }
364         this._percent = percent;
365         var dis = this._barLength * (percent / 100.0);
366         this._slidBallRenderer.setPosition(cc.p(-this._barLength / 2.0 + dis, 0.0));
367         if (this._scale9Enabled) {
368             this._progressBarRenderer.setPreferredSize(cc.size(dis, this._progressBarTextureSize.height));
369         }
370         else {
371             var x = 0, y = 0;
372             switch (this._progressBarTexType) {
373                 case ccs.TextureResType.plist:
374                     var barNode = this._progressBarRenderer;
375                     if (barNode) {
376                         var to = barNode.getTextureRect().origin;
377                         x = to.x;
378                         y = to.y;
379                     }
380                     break;
381                 default:
382                     break;
383             }
384             this._progressBarRenderer.setTextureRect(cc.rect(x, y, this._progressBarTextureSize.width * (percent / 100.0), this._progressBarTextureSize.height));
385         }
386     },
387 
388     onTouchBegan: function (touchPoint) {
389         var pass = ccs.UIWidget.prototype.onTouchBegan.call(this,touchPoint);
390         var nsp = this._renderer.convertToNodeSpace(touchPoint);
391         this.setPercent(this.getPercentWithBallPos(nsp.x));
392         this.percentChangedEvent();
393         return pass;
394     },
395 
396     onTouchMoved: function (touchPoint) {
397         var nsp = this._renderer.convertToNodeSpace(touchPoint);
398         this._slidBallRenderer.setPosition(cc.p(nsp.x, 0));
399         this.setPercent(this.getPercentWithBallPos(nsp.x));
400         this.percentChangedEvent();
401     },
402 
403     onTouchEnded: function (touchPoint) {
404         ccs.UIWidget.prototype.onTouchEnded.call(this, touchPoint);
405     },
406 
407     onTouchCancelled: function (touchPoint) {
408         ccs.UIWidget.prototype.onTouchCancelled.call(this, touchPoint);
409     },
410 
411     /**
412      * get percent with ballPos
413      * @param {cc.Point} px
414      * @returns {number}
415      */
416     getPercentWithBallPos: function (px) {
417         return (((px - (-this._barLength / 2.0)) / this._barLength) * 100.0);
418     },
419 
420     /**
421      * add event listener
422      * @param {Function} selector
423      * @param {Object} target
424      */
425     addEventListenerSlider: function (selector, target) {
426         this._sliderEventSelector = selector;
427         this._sliderEventListener = target;
428     },
429 
430     percentChangedEvent: function () {
431         if (this._sliderEventListener && this._sliderEventSelector) {
432             this._sliderEventSelector.call(this._sliderEventListener, this, ccs.SliderEventType.percent_changed);
433         }
434     },
435 
436     /**
437      * Gets the progress direction of slider.
438      * @returns {number}
439      */
440     getPercent: function () {
441         return this._percent;
442     },
443 
444     onSizeChanged: function () {
445         this.barRendererScaleChangedWithSize();
446         this.progressBarRendererScaleChangedWithSize();
447     },
448 
449     /**
450      * override "getContentSize" method of widget.
451      * @returns {cc.Size}
452      */
453     getContentSize: function () {
454         var locContentSize = this._barRenderer.getContentSize();
455         return cc.size(locContentSize.width,locContentSize.height);
456     },
457 
458     /**
459      * override "getContentSize" method of widget.
460      * @returns {cc.Node}
461      */
462     getVirtualRenderer: function () {
463         return this._barRenderer;
464     },
465 
466     barRendererScaleChangedWithSize: function () {
467         if (this._ignoreSize) {
468             this._barRenderer.setScale(1.0);
469             var locSize = this._barRenderer.getContentSize();
470             this._size.width = locSize.width;
471             this._size.height = locSize.height;
472             this._barLength = locSize.width;
473         }
474         else {
475             this._barLength = this._size.width;
476             if (this._scale9Enabled) {
477                 this._barRenderer.setPreferredSize(cc.size(this._size.width,this._size.height));
478             }
479             else {
480                 var btextureSize = this._barRenderer.getContentSize();
481                 if (btextureSize.width <= 0.0 || btextureSize.height <= 0.0) {
482                     this._barRenderer.setScale(1.0);
483                     return;
484                 }
485                 var bscaleX = this._size.width / btextureSize.width;
486                 var bscaleY = this._size.height / btextureSize.height;
487                 this._barRenderer.setScaleX(bscaleX);
488                 this._barRenderer.setScaleY(bscaleY);
489             }
490         }
491         this.setPercent(this._percent);
492     },
493 
494     progressBarRendererScaleChangedWithSize: function () {
495         if (this._ignoreSize) {
496             if (!this._scale9Enabled) {
497                 var ptextureSize = this._progressBarTextureSize;
498                 var pscaleX = this._size.width / ptextureSize.width;
499                 var pscaleY = this._size.height / ptextureSize.height;
500                 this._progressBarRenderer.setScaleX(pscaleX);
501                 this._progressBarRenderer.setScaleY(pscaleY);
502             }
503         }
504         else {
505             if (this._scale9Enabled) {
506                 this._progressBarRenderer.setPreferredSize(cc.size(this._size.width,this._size.height));
507             }
508             else {
509                 var ptextureSize = this._progressBarTextureSize;
510                 if (ptextureSize.width <= 0.0 || ptextureSize.height <= 0.0) {
511                     this._progressBarRenderer.setScale(1.0);
512                     return;
513                 }
514                 var pscaleX = this._size.width / ptextureSize.width;
515                 var pscaleY = this._size.height / ptextureSize.height;
516                 this._progressBarRenderer.setScaleX(pscaleX);
517                 this._progressBarRenderer.setScaleY(pscaleY);
518             }
519         }
520         this._progressBarRenderer.setPosition(cc.p(-this._barLength * 0.5, 0.0));
521         this.setPercent(this._percent);
522     },
523 
524     onPressStateChangedToNormal: function () {
525         this._slidBallNormalRenderer.setVisible(true);
526         this._slidBallPressedRenderer.setVisible(false);
527         this._slidBallDisabledRenderer.setVisible(false);
528     },
529 
530     onPressStateChangedToPressed: function () {
531         this._slidBallNormalRenderer.setVisible(false);
532         this._slidBallPressedRenderer.setVisible(true);
533         this._slidBallDisabledRenderer.setVisible(false);
534     },
535 
536     onPressStateChangedToDisabled: function () {
537         this._slidBallNormalRenderer.setVisible(false);
538         this._slidBallPressedRenderer.setVisible(false);
539         this._slidBallDisabledRenderer.setVisible(true);
540     },
541 
542     /**
543      * Returns the "class name" of widget.
544      * @returns {string}
545      */
546     getDescription: function () {
547         return "Slider";
548     },
549 
550     createCloneInstance: function () {
551         return ccs.UISlider.create();
552     },
553 
554     copySpecialProperties: function (slider) {
555         this._prevIgnoreSize = slider._prevIgnoreSize;
556         this.setScale9Enabled(slider._scale9Enabled);
557         this.loadBarTexture(slider._textureFile, slider._barTexType);
558         this.loadProgressBarTexture(slider._progressBarTextureFile, slider._progressBarTexType);
559         this.loadSlidBallTextureNormal(slider._slidBallNormalTextureFile, slider._ballNTexType);
560         this.loadSlidBallTexturePressed(slider._slidBallPressedTextureFile, slider._ballPTexType);
561         this.loadSlidBallTextureDisabled(slider._slidBallDisabledTextureFile, slider._ballDTexType);
562         this.setPercent(slider.getPercent());
563     }
564 });
565 /**
566  * allocates and initializes a UISlider.
567  * @constructs
568  * @return {ccs.UISlider}
569  * @example
570  * // example
571  * var uiSlider = ccs.UISlider.create();
572  */
573 ccs.UISlider.create = function () {
574     var uiSlider = new ccs.UISlider();
575     if (uiSlider && uiSlider.init()) {
576         return uiSlider;
577     }
578     return null;
579 };