1 /**
  2  *
  3  * Copyright (c) 2010-2012 cocos2d-x.org
  4  *
  5  * Copyright 2011 Yannick Loriot. All rights reserved.
  6  * http://yannickloriot.com
  7  *
  8  * Permission is hereby granted, free of charge, to any person obtaining a copy
  9  * of this software and associated documentation files (the "Software"), to deal
 10  * in the Software without restriction, including without limitation the rights
 11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  * copies of the Software, and to permit persons to whom the Software is
 13  * furnished to do so, subject to the following conditions:
 14  *
 15  * The above copyright notice and this permission notice shall be included in
 16  * all copies or substantial portions of the Software.
 17  *
 18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  * THE SOFTWARE.
 25  *
 26  *
 27  * converted to Javascript / cocos2d-x by Angus C
 28  */
 29 
 30 /**
 31  * @ignore
 32  */
 33 cc.SLIDER_MARGIN_H = 24;
 34 cc.SLIDER_MARGIN_V = 8;
 35 
 36 /**
 37  * ControlSlider: Slider ui component.
 38  * @class
 39  * @extends cc.Control
 40  *
 41  * @property {Number}       value               - The value of the slider
 42  * @property {Number}       minValue            - The minimum value of the slider
 43  * @property {Number}       maxValue            - The maximum value of the slider
 44  * @property {Number}       minAllowedValue     - The minimum allowed value of the slider
 45  * @property {Number}       maxAllowedValue     - The maximum allowed value of the slider
 46  * @property {Number}       thumbSprite         - <@readonly> Brightness value of the picker
 47  * @property {cc.Sprite}    progressSprite      - <@readonly> The background sprite
 48  * @property {cc.Sprite}    backgroundSprite    - <@readonly> The overlay sprite
 49  */
 50 cc.ControlSlider = cc.Control.extend(/** @lends cc.ControlSlider# */{
 51     _value:0,
 52     _minimumValue:0,
 53     _maximumValue:0,
 54     _minimumAllowedValue:0,
 55     _maximumAllowedValue:0,
 56 
 57     _thumbSprite:null,
 58     _progressSprite:null,
 59     _backgroundSprite:null,
 60     _className:"ControlSlider",
 61 
 62     getValue:function () {
 63         return this._value;
 64     },
 65     setValue:function (value) {
 66         //clamp between the two bounds
 67         value = Math.max(value, this._minimumValue);
 68         value = Math.min(value, this._maximumValue);
 69         this._value = value;
 70         this.needsLayout();
 71         this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
 72     },
 73 
 74     getMinimumValue:function () {
 75         return this._minimumValue;
 76     },
 77     setMinimumValue:function (minimumValue) {
 78         this._minimumValue = minimumValue;
 79         this._minimumAllowedValue = minimumValue;
 80         if (this._minimumValue >= this._maximumValue)
 81             this._maximumValue = this._minimumValue + 1.0;
 82         this.setValue(this._value);
 83     },
 84 
 85     getMaximumValue:function () {
 86         return this._maximumValue;
 87     },
 88     setMaximumValue:function (maximumValue) {
 89         this._maximumValue = maximumValue;
 90         this._maximumAllowedValue = maximumValue;
 91         if (this._maximumValue <= this._minimumValue)
 92             this._minimumValue = this._maximumValue - 1.0;
 93         this.setValue(this._value);
 94     },
 95     isTouchInside:function (touch) {
 96         var touchLocation = touch.getLocation();
 97         touchLocation = this.getParent().convertToNodeSpace(touchLocation);
 98 
 99         var rect = this.getBoundingBox();
100         rect.width += this._thumbSprite.getContentSize().width;
101         rect.x -= this._thumbSprite.getContentSize().width / 2;
102 
103         return cc.rectContainsPoint(rect, touchLocation);
104     },
105     locationFromTouch:function (touch) {
106         var touchLocation = touch.getLocation();                      // Get the touch position
107         touchLocation = this.convertToNodeSpace(touchLocation);                  // Convert to the node space of this class
108 
109         if (touchLocation.x < 0) {
110             touchLocation.x = 0;
111         } else if (touchLocation.x > this._backgroundSprite.getContentSize().width) {
112             touchLocation.x = this._backgroundSprite.getContentSize().width;
113         }
114 
115         return touchLocation;
116     },
117     getMinimumAllowedValue:function () {
118         return this._minimumAllowedValue;
119     },
120     setMinimumAllowedValue:function (val) {
121         this._minimumAllowedValue = val;
122     },
123 
124     getMaximumAllowedValue:function () {
125         return this._maximumAllowedValue;
126     },
127 
128     setMaximumAllowedValue:function (val) {
129         this._maximumAllowedValue = val;
130     },
131 
132     getThumbSprite:function () {
133         return this._thumbSprite;
134     },
135     getProgressSprite:function () {
136         return this._progressSprite;
137     },
138     getBackgroundSprite:function () {
139         return this._backgroundSprite;
140     },
141 
142     /**
143      * Initializes a slider with a background sprite, a progress bar and a thumb
144      * item.
145      *
146      * @param {cc.Sprite} backgroundSprite  CCSprite, that is used as a background.
147      * @param {cc.Sprite} progressSprite    CCSprite, that is used as a progress bar.
148      * @param {cc.Sprite} thumbSprite         CCMenuItem, that is used as a thumb.
149      */
150     initWithSprites:function (backgroundSprite, progressSprite, thumbSprite) {
151         if (cc.Control.prototype.init.call(this)) {
152             this.ignoreAnchorPointForPosition(false);
153 
154             this._backgroundSprite = backgroundSprite;
155             this._progressSprite = progressSprite;
156             this._thumbSprite = thumbSprite;
157 
158             // Defines the content size
159             var maxRect = cc.ControlUtils.CCRectUnion(backgroundSprite.getBoundingBox(), thumbSprite.getBoundingBox());
160             this.setContentSize(maxRect.width, maxRect.height);
161 
162             // Add the slider background
163             this._backgroundSprite.setAnchorPoint(0.5, 0.5);
164             this._backgroundSprite.setPosition(maxRect.width / 2, maxRect.height / 2);
165             this.addChild(this._backgroundSprite);
166 
167             // Add the progress bar
168             this._progressSprite.setAnchorPoint(0.0, 0.5);
169             this._progressSprite.setPosition(0, maxRect.height / 2);
170             this.addChild(this._progressSprite);
171 
172             // Add the slider thumb
173             this._thumbSprite.setPosition(0, maxRect.height / 2);
174             this.addChild(this._thumbSprite);
175 
176             // Init default values
177             this._minimumValue = 0.0;
178             this._maximumValue = 1.0;
179             this.setValue(this._minimumValue);
180             return true;
181         } else
182             return false;
183     },
184 
185     setEnabled:function (enabled) {
186         cc.Control.prototype.setEnabled.call(this, enabled);
187         if (this._thumbSprite) {
188             this._thumbSprite.setOpacity(enabled ? 255 : 128);
189         }
190     },
191 
192     sliderBegan:function (location) {
193         this.setSelected(true);
194         this.getThumbSprite().setColor(cc.color.GRAY);
195         this.setValue(this.valueForLocation(location));
196     },
197     sliderMoved:function (location) {
198         this.setValue(this.valueForLocation(location));
199     },
200     sliderEnded:function (location) {
201         if (this.isSelected()) {
202             this.setValue(this.valueForLocation(this._thumbSprite.getPosition()));
203         }
204         this._thumbSprite.setColor(cc.color.WHITE);
205         this.setSelected(false);
206     },
207 
208     getTouchLocationInControl:function (touch) {
209         var touchLocation = touch.getLocation();                      // Get the touch position
210         touchLocation = this.convertToNodeSpace(touchLocation);         // Convert to the node space of this class
211 
212         if (touchLocation.x < 0) {
213             touchLocation.x = 0;
214         } else if (touchLocation.x > this._backgroundSprite.getContentSize().width + cc.SLIDER_MARGIN_H) {
215             touchLocation.x = this._backgroundSprite.getContentSize().width + cc.SLIDER_MARGIN_H;
216         }
217         return touchLocation;
218     },
219 
220     onTouchBegan:function (touch, event) {
221         if (!this.isTouchInside(touch)|| !this.isEnabled() || !this.isVisible())
222             return false;
223 
224         var location = this.locationFromTouch(touch);
225         this.sliderBegan(location);
226         return true;
227     },
228     onTouchMoved:function (touch, event) {
229         var location = this.locationFromTouch(touch);
230         this.sliderMoved(location);
231     },
232     onTouchEnded:function (touch, event) {
233         this.sliderEnded(cc.p(0,0));
234     },
235     needsLayout:function(){
236         var percent = (this._value - this._minimumValue) / (this._maximumValue - this._minimumValue);
237         this._thumbSprite.setPositionX(percent * this._backgroundSprite.getContentSize().width);
238 
239         // Stretches content proportional to newLevel
240         var textureRect = this._progressSprite.getTextureRect();
241         textureRect = cc.rect(textureRect.x, textureRect.y, this._thumbSprite.getPositionX(), textureRect.height);
242         this._progressSprite.setTextureRect(textureRect, this._progressSprite.isTextureRectRotated());
243     },
244     /** Returns the value for the given location. */
245     valueForLocation:function (location) {
246         var percent = location.x / this._backgroundSprite.getContentSize().width;
247         return Math.max(Math.min(this._minimumValue + percent * (this._maximumValue - this._minimumValue), this._maximumAllowedValue), this._minimumAllowedValue);
248     }
249 });
250 
251 window._p = cc.ControlSlider.prototype;
252 
253 // Extended properties
254 /** @expose */
255 _p.value;
256 cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
257 /** @expose */
258 _p.minValue;
259 cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
260 /** @expose */
261 _p.maxValue;
262 cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
263 /** @expose */
264 _p.minAllowedValue;
265 cc.defineGetterSetter(_p, "minAllowedValue", _p.getMinimumAllowedValue, _p.setMinimumAllowedValue);
266 /** @expose */
267 _p.maxAllowedValue;
268 cc.defineGetterSetter(_p, "maxAllowedValue", _p.getMaximumAllowedValue, _p.setMaximumAllowedValue);
269 /** @expose */
270 _p.thumbSprite;
271 cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite);
272 /** @expose */
273 _p.progressSprite;
274 cc.defineGetterSetter(_p, "progressSprite", _p.getProgressSprite);
275 /** @expose */
276 _p.backgroundSprite;
277 cc.defineGetterSetter(_p, "backgroundSprite", _p.getBackgroundSprite);
278 
279 delete window._p;
280 
281 /**
282  * Creates a slider with a given background sprite and a progress bar and a
283  * thumb item.
284  *
285  * @see initWithBackgroundSprite:progressSprite:thumbMenuItem:
286  */
287 cc.ControlSlider.create = function (bgFile, progressFile, thumbFile) {
288     if (typeof(bgFile) == "string") {
289         // Prepare background for slider
290         bgFile = cc.Sprite.create(bgFile);
291 
292         // Prepare progress for slider
293         progressFile = cc.Sprite.create(progressFile);
294 
295         // Prepare thumb (menuItem) for slider
296         thumbFile = cc.Sprite.create(thumbFile);
297     }
298 
299     var pRet = new cc.ControlSlider();
300     pRet.initWithSprites(bgFile, progressFile, thumbFile);
301     return pRet;
302 
303 };