1 /***************************************
  2  * Copyright 2011, 2012 GlobWeb contributors.
  3  *
  4  * This file is part of GlobWeb.
  5  *
  6  * GlobWeb is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU Lesser General Public License as published by
  8  * the Free Software Foundation, version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * GlobWeb is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14  * GNU Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>.
 18  ***************************************/
 19 
 20 define( function() {
 21 
 22 /**************************************************************************************************************/
 23 
 24 /** @export
 25 	@constructor
 26 	KeyboardNavigationHandler constructor
 27 	@param options Configuration properties for the KeyboardNavigationHandler :
 28 			<ul>
 29 				<li>panFactor  : Factor for panning within the scene</li>
 30 				<li>zoomFactor : Factor for zooming into the scene</li>
 31 				<li>installOnDocument : True to install the event listener on the document and not on the canvas</li>
 32 			</ul>
 33  */
 34 var KeyboardNavigationHandler = function(options){
 35 	
 36 	/**************************************************************************************************************/
 37 	
 38 	/**
 39  	 * Private variables
 40 	 */
 41 	var _navigation = null;
 42 	var self = this;
 43 	
 44 	/**
 45 	 * Public variables
 46 	 */
 47 	this.panFactor = 10.;
 48 	this.zoomFactor = 1.;
 49 	
 50 	// Setup options
 51 	if ( options )
 52 	{
 53 		if ( options['panFactor'] && typeof options['panFactor'] == 'number' )
 54 			this.panFactor = options['panFactor'];
 55 		if ( options['zoomFactor'] && typeof options['zoomFactor'] == 'number' )
 56 			this.zoomFactor = options['zoomFactor'];
 57 	}
 58 	
 59 	/**************************************************************************************************************/
 60 	
 61 	/**
 62  	 * Private methods
 63 	 */
 64 
 65 	/**
 66 	 * Set focus
 67 	 */
 68 	var _setFocus = function(event)
 69 	{
 70 		this.focus();
 71 		return false;
 72 	};
 73 	  
 74 	/**
 75 	 *	Event handler for key down
 76 	 */
 77 	var _handleKeyDown = function(event)
 78 	{
 79 		switch( event.keyCode ){
 80 			case 32 :
 81 				// space bar
 82 				// Stop all animations when an event is received
 83 				_navigation.stopAnimations();
 84 				break;
 85 			case 187 :
 86 				// + on Safari
 87 			case 61 :
 88 				// +(=) on Firefox and Opera
 89 			case 107 :
 90 				// + on other
 91 				_navigation.zoom(-self.zoomFactor);
 92 				break;
 93 			case 189 :
 94 				// - on Safari
 95 			case 54 :
 96 				// -(6) on Firefox and Opera
 97 			case 109 :
 98 				// - on other
 99 				_navigation.zoom(self.zoomFactor);
100 				break;
101 			case 81 :
102 				// q
103 			case 37 :
104 				// Left arrow
105 				if ( event.shiftKey )
106 				{
107 					_navigation.rotate( self.panFactor, 0 );
108 				}
109 				else
110 				{
111 					_navigation.pan( self.panFactor, 0 );
112 				}
113 				break;
114 			case 90 :
115 				// z
116 			case 38 :
117 				// Up arrow
118 				if ( event.shiftKey )
119 				{
120 					_navigation.rotate( 0, self.panFactor );
121 				}
122 				else
123 				{
124 
125 					_navigation.pan( 0, self.panFactor );
126 				}
127 				break;
128 			case 68 :
129 				// d
130 			case 39 :
131 				// Right arrow
132 				if ( event.shiftKey )
133 				{
134 					_navigation.rotate( -self.panFactor, 0 );
135 				}
136 				else
137 				{
138 					_navigation.pan( -self.panFactor, 0 );
139 				}
140 				break;
141 			case 83 :
142 				// s
143 			case 40 :
144 				// Down arrow
145 				if ( event.shiftKey )
146 				{
147 					_navigation.rotate( 0, -self.panFactor );
148 				}
149 				else
150 				{
151 
152 					_navigation.pan( 0, -self.panFactor );
153 				}
154 				break;
155 		}
156 		_navigation.globe.renderContext.requestFrame();
157 	};
158 
159 	/**************************************************************************************************************/
160 	
161 	 /**
162 	  * Public methods
163 	  */
164 
165 	/** 
166 		Setup the default event handlers for the navigation
167 	 */
168 	this.install = function(navigation)
169 	{
170 		// Setup the keyboard event handlers
171 		_navigation = navigation;
172 		
173 		if ( options && options.installOnDocument )
174 		{
175 			document.addEventListener("keydown", _handleKeyDown);
176 		}
177 		else
178 		{
179 			var canvas = _navigation.globe.renderContext.canvas;
180 			canvas.addEventListener("keydown", _handleKeyDown);
181 			// Setup focus handling to receive keyboard event on canvas
182 			canvas.tabIndex = "0";
183 			canvas.addEventListener("mousedown", _setFocus);
184 		}
185 	};
186 
187 	/** 
188 		Remove the default event handlers for the navigation
189 	 */
190 	this.uninstall = function()
191 	{	
192 		if ( options && options.installOnDocument )
193 		{
194 			document.removeEventListener("keydown", _handleKeyDown);
195 		}
196 		else
197 		{
198 			var canvas = _navigation.globe.renderContext.canvas;
199 			canvas.removeEventListener("keydown", _handleKeyDown);
200 			canvas.removeEventListener("mousedown", _setFocus);
201 		}
202 	};
203 	
204 };
205 
206 return KeyboardNavigationHandler;
207 
208 });
209 
210