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