1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  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  * android back button
 29  * @deprecated These were for android devices, but does not work in html5 environment
 30  * @constant
 31  * @type Number
 32  */
 33 cc.TYPE_BACK_CLICKED = 1;
 34 /**
 35  * android menu button
 36  * @deprecated for android devices, does not work in html5 environment
 37  * @constant
 38  * @type Number
 39  */
 40 cc.TYPE_MENU_CLICKED = 2;
 41 
 42 /**
 43  * Dispatch the keyboard message
 44  * @class
 45  * @extends cc.Class
 46  */
 47 cc.KeyboardDispatcher = cc.Class.extend(/** @lends cc.KeyboardDispatcher# */{
 48     /**
 49      * add delegate to concern keyboard msg
 50      * @param {cc.KeyboardDelegate} delegate keyboard delegate object
 51      */
 52     addDelegate:function (delegate) {
 53         if (!delegate)
 54             return;
 55 
 56         if (!this._locked)
 57             this.forceAddDelegate(delegate);
 58         else {
 59             this._handlersToAdd.push(delegate);
 60             this._toAdd = true;
 61         }
 62     },
 63 
 64     /**
 65      * remove the delegate from the delegates who concern keyboard msg
 66      * @param {cc.KeyboardDelegate} delegate
 67      */
 68     removeDelegate:function (delegate) {
 69         if (!delegate) {
 70             return;
 71         }
 72         if (!this._locked) {
 73             this.forceRemoveDelegate(delegate);
 74         }
 75         else {
 76             this._handlersToRemove.push(delegate);
 77             this._toRemove = true;
 78         }
 79     },
 80 
 81     /**
 82      * force add the delegate
 83      * @param {cc.KeyboardDelegate} delegate
 84      */
 85     forceAddDelegate:function (delegate) {
 86         var handler = cc.KeyboardHandler.create(delegate);
 87         if (handler) {
 88             //if handler already exist
 89             var locDelegates = this._delegates;
 90             for (var i = 0, len = locDelegates.length; i < len; i++) {
 91                 if (locDelegates[i].getDelegate() == handler.getDelegate()) {
 92                     cc.log("cc.KeyboardDispatcher.forceAddDelegate(): the delegate has been added.");
 93                     return;
 94                 }
 95             }
 96             this._delegates.push(handler);
 97         }
 98     },
 99 
100     /**
101      * force remove the delegate
102      * @param {cc.KeyboardDelegate} delegate
103      */
104     forceRemoveDelegate:function (delegate) {
105         var locDelegates = this._delegates;
106         for (var i = 0, len = locDelegates.length; i < len; i++) {
107             if (locDelegates[i].getDelegate() == delegate) {
108                 locDelegates.splice(i, 1);
109                 return;
110             }
111         }
112     },
113 
114     /**
115      * dispatch the keyboard message to the delegates
116      * @param {event} e
117      * @param {Boolean} keydown whether this is a keydown or keyup
118      * @return {Boolean}
119      */
120     dispatchKeyboardMSG:function (e, keydown) {
121         this._locked = true;
122         e.stopPropagation();
123         e.preventDefault();
124 
125         var i = 0;
126         //update keymap
127         if (keydown && e) {     //if keydown and our keymap doesnt have it
128             //execute all deletegate that registered a keyboard event
129             for (i = 0; i < this._delegates.length; i++) {
130                 if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyDown)
131                     this._delegates[i].getDelegate().onKeyDown(e.keyCode);
132             }
133         }  else if (!keydown && e) {//if keyup and our keymap have that key in it
134             for (i = 0; i < this._delegates.length; i++) {
135                 if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyUp)
136                     this._delegates[i].getDelegate().onKeyUp(e.keyCode);
137             }
138         }
139         this._locked = false;
140         if (this._toRemove) {
141             this._toRemove = false;
142             var locHandlersToRemove = this._handlersToRemove;
143             for (i = 0; i < locHandlersToRemove.length; ++i) {
144                 this.forceRemoveDelegate(locHandlersToRemove[i]);
145             }
146             locHandlersToRemove.length = 0;
147         }
148 
149         if (this._toAdd) {
150             this._toAdd = false;
151             var locHandlersToAdd = this._handlersToAdd;
152             for (i = 0; i < locHandlersToAdd.length; ++i) {
153                 this.forceAddDelegate(locHandlersToAdd[i]);
154             }
155             locHandlersToAdd.length = 0;
156         }
157         return true;
158     },
159 
160     //private
161     _delegates:[],
162     _locked:false,
163     _toAdd:false,
164     _toRemove:false,
165     _handlersToAdd:[],
166     _handlersToRemove:[]
167 });
168 
169 /**
170  * Returns the shared cc.KeyboardDispatcher object for the system.
171  * @return {cc.keyboardDispatcher}
172  */
173 cc.KeyboardDispatcher.getInstance = function () {
174     if (!cc.keyboardDispatcher) {
175         cc.keyboardDispatcher = new cc.KeyboardDispatcher();
176         //make canvas focusable
177         cc.canvas.setAttribute('tabindex', 1);
178         cc.canvas.style.outline = 'none';
179         cc.canvas.style.cursor = 'default';
180         cc.canvas.addEventListener("keydown", function (e) {
181             cc.keyboardDispatcher.dispatchKeyboardMSG(e, true);
182         });
183         cc.canvas.addEventListener("keyup", function (e) {
184             cc.keyboardDispatcher.dispatchKeyboardMSG(e, false);
185         });
186     }
187     return cc.keyboardDispatcher;
188 };
189 
190 /**
191  * Release the shared cc.KeyboardDispatcher object from the system.
192  */
193 cc.KeyboardDispatcher.purgeSharedDispatcher = function () {
194     if (cc.keyboardDispatcher) {
195         delete cc.keyboardDispatcher;
196         cc.keyboardDispatcher = null;
197     }
198 };
199