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 /**
 28  * CCControlSwitch: Switch control ui component
 29  * @class
 30  * @extend cc.Control
 31  */
 32 cc.ControlSwitch = cc.Control.extend(/** @lends cc.ControlSwitch# */{
 33     /** Sprite which represents the view. */
 34     _switchSprite:null,
 35     _initialTouchXPosition:0,
 36 
 37     _moved:false,
 38     /** A Boolean value that determines the off/on state of the switch. */
 39     _on:false,
 40     _className:"ControlSwitch",
 41     ctor:function () {
 42         cc.Control.prototype.ctor.call(this);
 43     },
 44 
 45     /** Creates a switch with a mask sprite, on/off sprites for on/off states, a thumb sprite and an on/off labels. */
 46     initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
 47         if(!maskSprite)
 48             throw "cc.ControlSwitch.initWithMaskSprite(): maskSprite should be non-null.";
 49         if(!onSprite)
 50             throw "cc.ControlSwitch.initWithMaskSprite(): onSprite should be non-null.";
 51         if(!offSprite)
 52             throw "cc.ControlSwitch.initWithMaskSprite(): offSprite should be non-null.";
 53         if(!thumbSprite)
 54             throw "cc.ControlSwitch.initWithMaskSprite(): thumbSprite should be non-null.";
 55         if (this.init()) {
 56             this._on = true;
 57 
 58             this._switchSprite = new cc.ControlSwitchSprite();
 59             this._switchSprite.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
 60             this._switchSprite.setPosition(this._switchSprite.getContentSize().width / 2, this._switchSprite.getContentSize().height / 2);
 61             this.addChild(this._switchSprite);
 62 
 63             this.ignoreAnchorPointForPosition(false);
 64             this.setAnchorPoint(0.5, 0.5);
 65             this.setContentSize(this._switchSprite.getContentSize());
 66             return true;
 67         }
 68         return false;
 69     },
 70 
 71     setOn:function (isOn, animated) {
 72         animated = animated || false;
 73         this._on = isOn;
 74         var xPosition = (this._on) ? this._switchSprite.getOnPosition() : this._switchSprite.getOffPosition();
 75         if(animated){
 76             this._switchSprite.runAction(cc.ActionTween.create(0.2, "sliderXPosition", this._switchSprite.getSliderXPosition(),xPosition));
 77         }else{
 78             this._switchSprite.setSliderXPosition(xPosition);
 79         }
 80         this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
 81     },
 82 
 83     isOn:function () {
 84         return this._on;
 85     },
 86 
 87     hasMoved:function () {
 88         return this._moved;
 89     },
 90 
 91     setEnabled:function (enabled) {
 92         this._enabled = enabled;
 93 
 94         this._switchSprite.setOpacity((enabled) ? 255 : 128);
 95     },
 96 
 97     locationFromTouch:function (touch) {
 98         var touchLocation = touch.getLocation();                      // Get the touch position
 99         touchLocation = this.convertToNodeSpace(touchLocation);                  // Convert to the node space of this class
100 
101         return touchLocation;
102     },
103 
104     onTouchBegan:function (touch, event) {
105         if (!this.isTouchInside(touch)  || !this.isEnabled()|| !this.isVisible()) {
106             return false;
107         }
108 
109         this._moved = false;
110 
111         var location = this.locationFromTouch(touch);
112 
113         this._initialTouchXPosition = location.x - this._switchSprite.getSliderXPosition();
114 
115         this._switchSprite.getThumbSprite().setColor(cc.color.GRAY);
116         this._switchSprite.needsLayout();
117 
118         return true;
119     },
120 
121     onTouchMoved:function (touch, event) {
122         var location = this.locationFromTouch(touch);
123         location = cc.p(location.x - this._initialTouchXPosition, 0);
124 
125         this._moved = true;
126 
127         this._switchSprite.setSliderXPosition(location.x);
128     },
129 
130     onTouchEnded:function (touch, event) {
131         var location = this.locationFromTouch(touch);
132 
133         this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
134 
135         if (this.hasMoved()) {
136             this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
137         } else {
138             this.setOn(!this._on, true);
139         }
140     },
141 
142     onTouchCancelled:function (touch, event) {
143         var location = this.locationFromTouch(touch);
144 
145         this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
146 
147         if (this.hasMoved()) {
148             this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
149         } else {
150             this.setOn(!this._on, true);
151         }
152     }
153 });
154 
155 /** Creates a switch with a mask sprite, on/off sprites for on/off states and a thumb sprite. */
156 cc.ControlSwitch.create = function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
157     var pRet = new cc.ControlSwitch();
158     if (pRet && pRet.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel)) {
159         return pRet;
160     }
161     return null;
162 };
163 
164 /**
165  * ControlSwitchSprite: Sprite switch control ui component
166  * @class
167  * @extend cc.Sprite
168  *
169  * @property {Number}           sliderX         - Slider's x position
170  * @property {cc.Point}         onPos           - The position of slider when switch is on
171  * @property {cc.Point}         offPos          - The position of slider when switch is off
172  * @property {cc.Texture2D}     maskTexture     - The texture of the mask
173  * @property {cc.Point}         texturePos      - The position of the texture
174  * @property {cc.Point}         maskPos         - The position of the mask
175  * @property {cc.Sprite}        onSprite        - The sprite of switch on
176  * @property {cc.Sprite}        offSprite       - The sprite of switch off
177  * @property {cc.Sprite}        thumbSprite     - The thumb sprite of the switch control
178  * @property {cc.LabelTTF}      onLabel         - The sprite of switch on
179  * @property {cc.LabelTTF}      offLabel        - The sprite of switch off
180  * @property {Number}           onSideWidth     - <@readonly> The width of the on side of the switch control
181  * @property {Number}           offSideWidth    - <@readonly> The width of the off side of the switch control
182  */
183 cc.ControlSwitchSprite = cc.Sprite.extend({
184     _sliderXPosition:0,
185     _onPosition:0,
186     _offPosition:0,
187 
188     _textureLocation:0,
189     _maskLocation:0,
190     _maskSize:null,
191 
192     _onSprite:null,
193     _offSprite:null,
194     _thumbSprite:null,
195     _onLabel:null,
196     _offLabel:null,
197     _clipper:null,
198     _stencil:null,
199     _backRT:null,
200 
201     ctor:function () {
202         cc.Sprite.prototype.ctor.call(this);
203         this._sliderXPosition = 0;
204         this._onPosition = 0;
205         this._offPosition = 0;
206         this._maskLocation = 0;
207         this._maskSize = cc.size(0, 0);
208         this._onSprite = null;
209         this._offSprite = null;
210         this._thumbSprite = null;
211         this._onLabel = null;
212         this._offLabel = null;
213     },
214 
215     initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
216         if (cc.Sprite.prototype.initWithTexture.call(this, maskSprite.getTexture())) {
217             // Sets the default values
218             this._onPosition = 0;
219             this._offPosition = -onSprite.getContentSize().width + thumbSprite.getContentSize().width / 2;
220             this._sliderXPosition = this._onPosition;
221 
222             this.setOnSprite(onSprite);
223             this.setOffSprite(offSprite);
224             this.setThumbSprite(thumbSprite);
225             this.setOnLabel(onLabel);
226             this.setOffLabel(offLabel);
227 
228             // Set up the mask with the Mask shader
229             this._stencil = maskSprite;
230             var maskSize = this._maskSize = this._stencil.getContentSize();
231             this._stencil.setPosition(0, 0);
232 
233             // Init clipper for mask
234             this._clipper = cc.ClippingNode.create();
235             this._clipper.setAnchorPoint(0.5, 0.5);
236             this._clipper.setPosition(maskSize.width / 2, maskSize.height / 2);
237             this._clipper.setStencil(this._stencil);
238             this._backRT = cc.RenderTexture.create(maskSize.width, maskSize.height);
239             this._clipper.addChild(this._backRT.getSprite());
240             this.addChild(this._clipper);
241 
242             this.addChild(this._thumbSprite);
243 
244             this.needsLayout();
245             return true;
246         }
247         return false;
248     },
249 
250     needsLayout:function () {
251         this._onSprite.setPosition(this._onSprite.getContentSize().width / 2 + this._sliderXPosition,
252             this._onSprite.getContentSize().height / 2);
253         this._offSprite.setPosition(this._onSprite.getContentSize().width + this._offSprite.getContentSize().width / 2 + this._sliderXPosition,
254             this._offSprite.getContentSize().height / 2);
255 
256         if (this._onLabel) {
257             this._onLabel.setPosition(this._onSprite.getPositionX() - this._thumbSprite.getContentSize().width / 6,
258                 this._onSprite.getContentSize().height / 2);
259         }
260         if (this._offLabel) {
261             this._offLabel.setPosition(this._offSprite.getPositionX() + this._thumbSprite.getContentSize().width / 6,
262                 this._offSprite.getContentSize().height / 2);
263         }
264         this._thumbSprite.setPosition(this._onSprite.getContentSize().width + this._sliderXPosition,
265             this._maskSize.height / 2);
266 
267         this._backRT.begin();
268 
269         this._onSprite.visit();
270         this._offSprite.visit();
271 
272         if (this._onLabel)
273             this._onLabel.visit();
274         if (this._offLabel)
275             this._offLabel.visit();
276 
277         this._backRT.end();
278 
279         //this.setFlippedY(true);
280     },
281 
282     setSliderXPosition:function (sliderXPosition) {
283         if (sliderXPosition <= this._offPosition) {
284             // Off
285             sliderXPosition = this._offPosition;
286         } else if (sliderXPosition >= this._onPosition) {
287             // On
288             sliderXPosition = this._onPosition;
289         }
290 
291         this._sliderXPosition = sliderXPosition;
292 
293         this.needsLayout();
294     },
295     getSliderXPosition:function () {
296         return this._sliderXPosition;
297     },
298 
299     _getOnSideWidth:function () {
300         return this._onSprite.getContentSize().width;
301     },
302 
303     _getOffSideWidth:function () {
304         return this._offSprite.getContentSize().height;
305     },
306 
307     updateTweenAction:function (value, key) {
308         cc.log("key = " + key + ", value = " + value);
309         this.setSliderXPosition(value);
310     },
311 
312     setOnPosition:function (onPosition) {
313         this._onPosition = onPosition;
314     },
315     getOnPosition:function () {
316         return this._onPosition;
317     },
318 
319     setOffPosition:function (offPosition) {
320         this._offPosition = offPosition;
321     },
322     getOffPosition:function () {
323         return this._offPosition;
324     },
325 
326     setMaskTexture:function (maskTexture) {
327         this._stencil.setTexture(maskTexture);
328     },
329     getMaskTexture:function () {
330         return this._stencil.getTexture();
331     },
332 
333     setTextureLocation:function (textureLocation) {
334         this._textureLocation = textureLocation;
335     },
336     getTextureLocation:function () {
337         return this._textureLocation;
338     },
339 
340     setMaskLocation:function (maskLocation) {
341         this._maskLocation = maskLocation;
342     },
343     getMaskLocation:function () {
344         return this._maskLocation;
345     },
346 
347     setOnSprite:function (onSprite) {
348         this._onSprite = onSprite;
349     },
350     getOnSprite:function () {
351         return this._onSprite;
352     },
353 
354     setOffSprite:function (offSprite) {
355         this._offSprite = offSprite;
356     },
357     getOffSprite:function () {
358         return this._offSprite;
359     },
360 
361     setThumbSprite:function (thumbSprite) {
362         this._thumbSprite = thumbSprite;
363     },
364     getThumbSprite:function () {
365         return this._thumbSprite;
366     },
367 
368     setOnLabel:function (onLabel) {
369         this._onLabel = onLabel;
370     },
371     getOnLabel:function () {
372         return this._onLabel;
373     },
374 
375     setOffLabel:function (offLabel) {
376         this._offLabel = offLabel;
377     },
378     getOffLabel:function () {
379         return this._offLabel;
380     }
381 });
382 
383 window._p = cc.ControlSwitchSprite.prototype;
384 
385 /** @expose */
386 _p.sliderX;
387 cc.defineGetterSetter(_p, "sliderX", _p.getSliderXPosition, _p.setSliderXPosition);
388 /** @expose */
389 _p.onPos;
390 cc.defineGetterSetter(_p, "onPos", _p.getOnPosition, _p.setOnPosition);
391 /** @expose */
392 _p.offPos;
393 cc.defineGetterSetter(_p, "offPos", _p.getOffPosition, _p.setOffPosition);
394 /** @expose */
395 _p.maskTexture;
396 cc.defineGetterSetter(_p, "maskTexture", _p.getMaskTexture, _p.setMaskTexture);
397 /** @expose */
398 _p.maskPos;
399 cc.defineGetterSetter(_p, "maskPos", _p.getMaskLocation, _p.setMaskLocation);
400 /** @expose */
401 _p.onSprite;
402 cc.defineGetterSetter(_p, "onSprite", _p.getOnSprite, _p.setOnSprite);
403 /** @expose */
404 _p.offSprite;
405 cc.defineGetterSetter(_p, "offSprite", _p.getOffSprite, _p.setOffSprite);
406 /** @expose */
407 _p.thumbSprite;
408 cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite, _p.setThumbSprite);
409 /** @expose */
410 _p.onLabel;
411 cc.defineGetterSetter(_p, "onLabel", _p.getOnLabel, _p.setOnLabel);
412 /** @expose */
413 _p.offLabel;
414 cc.defineGetterSetter(_p, "offLabel", _p.getOffLabel, _p.setOffLabel);
415 /** @expose */
416 _p.onSideWidth;
417 cc.defineGetterSetter(_p, "onSideWidth", _p._getOnSideWidth);
418 /** @expose */
419 _p.offSideWidth;
420 cc.defineGetterSetter(_p, "offSideWidth", _p._getOffSideWidth);
421 
422 delete window._p;
423