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