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