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             for (i = 0; i < this._handlersToRemove.length; ++i) {
143                 this.forceRemoveDelegate(this._handlersToRemove[i]);
144             }
145             delete this._handlersToRemove;
146             this._handlersToRemove = [];
147         }
148 
149         if (this._toAdd) {
150             this._toAdd = false;
151             for (i = 0; i < this._handlersToAdd.length; ++i) {
152                 this.forceAddDelegate(this._handlersToAdd[i]);
153             }
154             this._handlersToAdd = [];
155         }
156         return true;
157     },
158 
159     //private
160     _delegates:[],
161     _locked:false,
162     _toAdd:false,
163     _toRemove:false,
164     _handlersToAdd:[],
165     _handlersToRemove:[]
166 });
167 
168 /**
169  * Returns the shared cc.KeyboardDispatcher object for the system.
170  * @return {cc.keyboardDispatcher}
171  */
172 cc.KeyboardDispatcher.getInstance = function () {
173     if (!cc.keyboardDispatcher) {
174         cc.keyboardDispatcher = new cc.KeyboardDispatcher();
175         //make canvas focusable
176         cc.canvas.setAttribute('tabindex', 1);
177         cc.canvas.style.outline = 'none';
178         cc.canvas.style.cursor = 'default';
179         cc.canvas.addEventListener("keydown", function (e) {
180             cc.keyboardDispatcher.dispatchKeyboardMSG(e, true);
181         });
182         cc.canvas.addEventListener("keyup", function (e) {
183             cc.keyboardDispatcher.dispatchKeyboardMSG(e, false);
184         });
185     }
186     return cc.keyboardDispatcher;
187 };
188 
189 /**
190  * Release the shared cc.KeyboardDispatcher object from the system.
191  */
192 cc.KeyboardDispatcher.purgeSharedDispatcher = function () {
193     if (cc.keyboardDispatcher) {
194         delete cc.keyboardDispatcher;
195         cc.keyboardDispatcher = null;
196     }
197 };
198