1 /****************************************************************************
  2  Copyright (c) 2010-2014 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * <p>
 27  *     The base class of event listener.                                                                        <br/>
 28  *     If you need custom listener which with different callback, you need to inherit this class.               <br/>
 29  *     For instance, you could refer to EventListenerAcceleration, EventListenerKeyboard,                       <br/>
 30  *      EventListenerTouchOneByOne, EventListenerCustom.
 31  * </p>
 32  * @class
 33  * @extends cc.Class
 34  */
 35 cc.EventListener = cc.Class.extend(/** @lends cc.EventListener# */{
 36     _onEvent: null,                          // Event callback function
 37     _type: 0,                                 // Event listener type
 38     _listenerID: null,                       // Event listener ID
 39     _registered: false,                     // Whether the listener has been added to dispatcher.
 40 
 41     _fixedPriority: 0,                      // The higher the number, the higher the priority, 0 is for scene graph base priority.
 42     _node: null,                           // scene graph based priority
 43     _paused: false,                        // Whether the listener is paused
 44 
 45     /**
 46      * Initializes event with type and callback function
 47      * @param {number} type
 48      * @param {string} listenerID
 49      * @param {function} callback
 50      */
 51     ctor: function (type, listenerID, callback) {
 52         this._onEvent = callback;
 53         this._type = type || 0;
 54         this._listenerID = listenerID || "";
 55     },
 56 
 57     _setPaused: function (paused) {
 58         this._paused = paused;
 59     },
 60 
 61     _isPaused: function () {
 62         return this._paused;
 63     },
 64 
 65     _setRegistered: function (registered) {
 66         this._registered = registered;
 67     },
 68 
 69     _isRegistered: function () {
 70         return this._registered;
 71     },
 72 
 73     _getType: function () {
 74         return this._type;
 75     },
 76 
 77     _getListenerID: function () {
 78         return this._listenerID;
 79     },
 80 
 81     _setFixedPriority: function (fixedPriority) {
 82         this._fixedPriority = fixedPriority;
 83     },
 84 
 85     _getFixedPriority: function () {
 86         return this._fixedPriority;
 87     },
 88 
 89     _setSceneGraphPriority: function (node) {
 90         this._node = node;
 91     },
 92 
 93     _getSceneGraphPriority: function () {
 94         return this._node;
 95     },
 96 
 97     /**
 98      * Checks whether the listener is available.
 99      * @returns {boolean}
100      */
101     checkAvailable: function () {
102         return this._onEvent != null;
103     },
104 
105     /**
106      * Clones the listener, its subclasses have to override this method.
107      * @returns {cc.EventListener}
108      */
109     clone: function () {
110         return null;
111     },
112 
113     /**
114      * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
115      * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
116      * This is a hack, and should be removed once JSB fixes the retain/release bug
117      */
118     retain:function () {
119     },
120     release:function () {
121     }
122 });
123 
124 // event listener type
125 cc.EventListener.UNKNOWN = 0;
126 cc.EventListener.TOUCH_ONE_BY_ONE = 1;
127 cc.EventListener.TOUCH_ALL_AT_ONCE = 2;
128 cc.EventListener.KEYBOARD = 3;
129 cc.EventListener.MOUSE = 4;
130 cc.EventListener.ACCELERATION = 5;
131 cc.EventListener.CUSTOM = 6;
132 
133 cc._EventListenerCustom = cc.EventListener.extend({
134     _onCustomEvent: null,
135     ctor: function (listenerId, callback) {
136         this._onCustomEvent = callback;
137         var selfPointer = this;
138         var listener = function (event) {
139             if (selfPointer._onCustomEvent != null)
140                 selfPointer._onCustomEvent(event);
141         };
142 
143         cc.EventListener.prototype.ctor.call(this, cc.EventListener.CUSTOM, listenerId, listener);
144     },
145 
146     checkAvailable: function () {
147         return (cc.EventListener.prototype.checkAvailable.call(this) && this._onCustomEvent != null);
148     },
149 
150     clone: function () {
151         return new cc._EventListenerCustom(this._listenerID, this._onCustomEvent);
152     }
153 });
154 
155 cc._EventListenerCustom.create = function (eventName, callback) {
156     return new cc._EventListenerCustom(eventName, callback);
157 };
158 
159 cc._EventListenerAcceleration = cc.EventListener.extend({
160     _onAccelerationEvent: null,
161     ctor: function (callback) {
162         this._onAccelerationEvent = callback;
163         var selfPointer = this;
164         var listener = function (event) {
165             selfPointer._onAccelerationEvent(event._acc, event);
166         };
167         cc.EventListener.prototype.ctor.call(this, cc.EventListener.ACCELERATION, cc._EventListenerAcceleration.LISTENER_ID, listener);
168     },
169 
170     checkAvailable: function () {
171         if (!this._onAccelerationEvent)
172             throw "cc._EventListenerAcceleration.checkAvailable(): _onAccelerationEvent must be non-nil";
173         return true;
174     },
175 
176     clone: function () {
177         return new cc._EventListenerAcceleration(this._onAccelerationEvent);
178     }
179 });
180 
181 cc._EventListenerAcceleration.LISTENER_ID = "__cc_acceleration";
182 
183 cc._EventListenerAcceleration.create = function (callback) {
184     return new cc._EventListenerAcceleration(callback);
185 };
186 
187 cc._EventListenerKeyboard = cc.EventListener.extend({
188     onKeyPressed: null,
189     onKeyReleased: null,
190 
191     ctor: function () {
192         var selfPointer = this;
193         var listener = function (event) {
194             if (event._isPressed) {
195                 if (selfPointer.onKeyPressed)
196                     selfPointer.onKeyPressed(event._keyCode, event);
197             } else {
198                 if (selfPointer.onKeyReleased)
199                     selfPointer.onKeyReleased(event._keyCode, event);
200             }
201         };
202         cc.EventListener.prototype.ctor.call(this, cc.EventListener.KEYBOARD, cc._EventListenerKeyboard.LISTENER_ID, listener);
203     },
204 
205     clone: function () {
206         var eventListener = new cc._EventListenerKeyboard();
207         eventListener.onKeyPressed = this.onKeyPressed;
208         eventListener.onKeyReleased = this.onKeyReleased;
209         return eventListener;
210     },
211 
212     checkAvailable: function () {
213         if (this.onKeyPressed == null && this.onKeyReleased == null) {
214             cc.log("cc._EventListenerKeyboard.checkAvailable(): Invalid EventListenerKeyboard!");
215             return false;
216         }
217         return true;
218     }
219 });
220 
221 cc._EventListenerKeyboard.LISTENER_ID = "__cc_keyboard";
222 
223 cc._EventListenerKeyboard.create = function () {
224     return new cc._EventListenerKeyboard();
225 };
226 
227 cc._EventListenerMouse = cc.EventListener.extend({
228     onMouseDown: null,
229     onMouseUp: null,
230     onMouseMove: null,
231     onMouseScroll: null,
232 
233     ctor: function () {
234         var selfPointer = this;
235         var listener = function (event) {
236             var eventType = cc.EventMouse;
237             switch (event._eventType) {
238                 case eventType.DOWN:
239                     if (selfPointer.onMouseDown)
240                         selfPointer.onMouseDown(event);
241                     break;
242                 case eventType.UP:
243                     if (selfPointer.onMouseUp)
244                         selfPointer.onMouseUp(event);
245                     break;
246                 case eventType.MOVE:
247                     if (selfPointer.onMouseMove)
248                         selfPointer.onMouseMove(event);
249                     break;
250                 case eventType.SCROLL:
251                     if (selfPointer.onMouseScroll)
252                         selfPointer.onMouseScroll(event);
253                     break;
254                 default:
255                     break;
256             }
257         };
258         cc.EventListener.prototype.ctor.call(this, cc.EventListener.MOUSE, cc._EventListenerMouse.LISTENER_ID, listener);
259     },
260 
261     clone: function () {
262         var eventListener = new cc._EventListenerMouse();
263         eventListener.onMouseDown = this.onMouseDown;
264         eventListener.onMouseUp = this.onMouseUp;
265         eventListener.onMouseMove = this.onMouseMove;
266         eventListener.onMouseScroll = this.onMouseScroll;
267         return eventListener;
268     },
269 
270     checkAvailable: function () {
271         return true;
272     }
273 });
274 
275 cc._EventListenerMouse.LISTENER_ID = "__cc_mouse";
276 
277 cc._EventListenerMouse.create = function () {
278     return new cc._EventListenerMouse();
279 };
280 
281 cc._EventListenerTouchOneByOne = cc.EventListener.extend({
282     _claimedTouches: null,
283     swallowTouches: false,
284     onTouchBegan: null,
285     onTouchMoved: null,
286     onTouchEnded: null,
287     onTouchCancelled: null,
288 
289     ctor: function () {
290         cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ONE_BY_ONE, cc._EventListenerTouchOneByOne.LISTENER_ID, null);
291         this._claimedTouches = [];
292     },
293 
294     setSwallowTouches: function (needSwallow) {
295         this.swallowTouches = needSwallow;
296     },
297 
298     clone: function () {
299         var eventListener = new cc._EventListenerTouchOneByOne();
300         eventListener.onTouchBegan = this.onTouchBegan;
301         eventListener.onTouchMoved = this.onTouchMoved;
302         eventListener.onTouchEnded = this.onTouchEnded;
303         eventListener.onTouchCancelled = this.onTouchCancelled;
304         eventListener.swallowTouches = this.swallowTouches;
305         return eventListener;
306     },
307 
308     checkAvailable: function () {
309         if(!this.onTouchBegan){
310             cc.log("cc._EventListenerTouchOneByOne.checkAvailable(): Invalid EventListenerTouchOneByOne!");
311             return false;
312         }
313         return true;
314     }
315 });
316 
317 cc._EventListenerTouchOneByOne.LISTENER_ID = "__cc_touch_one_by_one";
318 
319 cc._EventListenerTouchOneByOne.create = function () {
320     return new cc._EventListenerTouchOneByOne();
321 };
322 
323 cc._EventListenerTouchAllAtOnce = cc.EventListener.extend({
324     onTouchesBegan: null,
325     onTouchesMoved: null,
326     onTouchesEnded: null,
327     onTouchesCancelled: null,
328 
329     ctor: function(){
330        cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ALL_AT_ONCE, cc._EventListenerTouchAllAtOnce.LISTENER_ID, null);
331     },
332 
333     clone: function(){
334         var eventListener = new cc._EventListenerTouchAllAtOnce();
335         eventListener.onTouchesBegan = this.onTouchesBegan;
336         eventListener.onTouchesMoved = this.onTouchesMoved;
337         eventListener.onTouchesEnded = this.onTouchesEnded;
338         eventListener.onTouchesCancelled = this.onTouchesCancelled;
339         return eventListener;
340     },
341 
342     checkAvailable: function(){
343         if (this.onTouchesBegan == null && this.onTouchesMoved == null
344             && this.onTouchesEnded == null && this.onTouchesCancelled == null) {
345             cc.log("cc._EventListenerTouchAllAtOnce.checkAvailable(): Invalid EventListenerTouchAllAtOnce!");
346             return false;
347         }
348         return true;
349     }
350 });
351 
352 cc._EventListenerTouchAllAtOnce.LISTENER_ID = "__cc_touch_all_at_once";
353 
354 cc._EventListenerTouchAllAtOnce.create = function(){
355      return new cc._EventListenerTouchAllAtOnce();
356 };
357 
358 /**
359  * Create a EventListener object by json object
360  * @param {object} argObj a json object
361  * @returns {cc.EventListener}
362  * @example
363  * cc.EventListener.create({
364  *       event: cc.EventListener.TOUCH_ONE_BY_ONE,
365  *       swallowTouches: true,
366  *       onTouchBegan: function (touch, event) {
367  *           //do something
368  *           return true;
369  *       }
370  *    });
371  */
372 cc.EventListener.create = function(argObj){
373     if(!argObj || !argObj.event){
374         throw "Invalid parameter.";
375     }
376     var listenerType = argObj.event;
377     delete argObj.event;
378 
379     var listener = null;
380     if(listenerType === cc.EventListener.TOUCH_ONE_BY_ONE)
381         listener = new cc._EventListenerTouchOneByOne();
382     else if(listenerType === cc.EventListener.TOUCH_ALL_AT_ONCE)
383         listener = new cc._EventListenerTouchAllAtOnce();
384     else if(listenerType === cc.EventListener.MOUSE)
385         listener = new cc._EventListenerMouse();
386     else if(listenerType === cc.EventListener.CUSTOM){
387         listener = new cc._EventListenerCustom(argObj.eventName, argObj.callback);
388         delete argObj.eventName;
389         delete argObj.callback;
390     } else if(listenerType === cc.EventListener.KEYBOARD)
391         listener = new cc._EventListenerKeyboard();
392     else if(listenerType === cc.EventListener.ACCELERATION){
393         listener = new cc._EventListenerAcceleration(argObj.callback);
394         delete argObj.callback;
395     }
396 
397     for(var key in argObj) {
398         listener[key] = argObj[key];
399     }
400 
401     return listener;
402 };