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