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 	Mouse_navigationHandler constructor
 27 	@param options Configuration properties for the Mouse_navigationHandler :
 28 			<ul>
 29 				<li>zoomOnDblClick : if true defines animation on double click</li>
 30 			</ul>
 31  */
 32 var MouseNavigationHandler = function(options){
 33 	
 34 	/**************************************************************************************************************/
 35 	
 36 	/**
 37  	 * Private variables
 38 	 */
 39 	 
 40 	var _navigation = null;
 41 	var _pressedButton = -1;
 42 	var _lastMouseX = -1;
 43 	var _lastMouseY = -1;
 44 	var _needsStartEvent = false;
 45 	var _needsEndEvent = false;
 46 	var _dx = 0;
 47 	var _dy = 0;
 48 
 49 	/**************************************************************************************************************/
 50 	
 51 	/**
 52  	 * Private methods
 53 	 */
 54 
 55 	/**
 56 		Event handler for mouse wheel
 57 	 */
 58 	var _handleMouseWheel = function(event)
 59 	{
 60 		_navigation.globe.publish("startNavigation");
 61 		
 62 		var factor;
 63 
 64 		// Check differences between firefox and the rest of the world
 65 		if ( event.wheelDelta === undefined)
 66 		{
 67 			factor = event.detail;
 68 		}
 69 		else
 70 		{
 71 			factor = -event.wheelDelta / 120.0;	
 72 		}
 73 		_navigation.zoom(factor);
 74 		
 75 		// Stop all animations when an event is received
 76 		_navigation.stopAnimations();
 77 		
 78 		// Launch inertia if needed
 79 		if ( _navigation.inertia )
 80 		{
 81 			_navigation.inertia.launch("zoom", factor < 0 ? -1 : 1 );
 82 		}
 83 
 84 		// Stop mouse wheel to be propagated, because default is to scroll the page
 85 		// This is need when using Firefox event listener on DOMMouseScroll
 86 		if ( event.preventDefault )
 87 		{
 88 			event.preventDefault();
 89 		}
 90 		event.returnValue = false;
 91 		
 92 		_navigation.globe.publish("endNavigation");
 93 		_navigation.globe.renderContext.requestFrame();
 94 			
 95 		// Return false to stop mouse wheel to be propagated when using onmousewheel
 96 		return false;
 97 	};
 98 
 99 	/**
100 	 * Event handler for mouse down
101 	 */
102 	var _handleMouseDown = function(event)
103 	{
104 		document.addEventListener("mouseup", _handleMouseUp);
105 		_pressedButton = event.button;
106 		
107 		// Stop all animations when an event is received
108 		_navigation.stopAnimations();
109 
110 		if ( event.button == 0 || event.button == 1 )
111 		{		
112 			_lastMouseX = event.clientX;
113 			_lastMouseY = event.clientY;
114 			_dx = 0;
115 			_dy = 0;
116 			
117 			_needsStartEvent = true;
118 			
119 			// Return false to stop mouse down to be propagated when using onmousedown
120 			return false;
121 		}
122 		
123 		return true;
124 	};
125 
126 	/**
127 	 * Event handler for mouse up
128 	 */
129 	var _handleMouseUp = function(event)
130 	{
131 		// No button pressed anymore
132 		_pressedButton = -1;
133 		document.removeEventListener("mouseup", _handleMouseUp);
134 
135 		if ( _navigation.inertia && (_dx != 0 || _dy != 0)  )
136 		{	
137 			if ( event.button == 0 )
138 			{
139 				_navigation.inertia.launch("pan", _dx, _dy );
140 			
141 			}
142 			if ( event.button == 1 )
143 			{
144 				_navigation.inertia.launch("rotate", _dx, _dy );
145 			}
146 		}
147 
148 		if ( event.button == 0 || event.button == 1 )
149 		{
150 
151 			if (_needsEndEvent ) {
152 				_navigation.globe.publish("endNavigation");
153 			}
154 
155 			_needsStartEvent = false;
156 			_needsEndEvent = false;
157 			
158 			// Stop mouse up event
159 			return false;
160 		}
161 
162 		return true;
163 	};
164 
165 	/**
166 		Event handler for mouse move
167 	*/
168 	var _handleMouseMove = function(event)
169 	{
170 		// No button pressed
171 		if (_pressedButton < 0)
172 			return;
173 		
174 		_dx = (event.clientX - _lastMouseX);
175 		_dy = (event.clientY - _lastMouseY);
176 		
177 		if ( _dx == 0 && _dy == 0 )
178 			return;
179 		
180 		var ret = false;
181 		// Pan
182 		if ( _pressedButton == 0 )
183 		{
184 			if ( _needsStartEvent ) { 
185 				_navigation.globe.publish("startNavigation");
186 				_needsStartEvent  = false;
187 				_needsEndEvent = true;
188 			}
189 			_navigation.pan( _dx, _dy );
190 			_navigation.globe.renderContext.requestFrame();
191 			ret = true;
192 		}
193 		// Rotate
194 		else if ( _pressedButton == 1 )
195 		{
196 			_navigation.rotate(_dx,_dy);
197 			_navigation.globe.renderContext.requestFrame();
198 			ret = true;
199 		}
200 		
201 		_lastMouseX = event.clientX;
202 		_lastMouseY = event.clientY;
203 		
204 		return ret;
205 	};
206 
207 	/**
208 		Event handler for mouse double click
209 	 */
210 	var _handleMouseDblClick = function(event)
211 	{
212 		if (event.button == 0)
213 		{
214 			var pos = _navigation.globe.renderContext.getXYRelativeToCanvas(event);
215 			var geo = _navigation.globe.getLonLatFromPixel( pos[0], pos[1] );
216 		
217 			if (geo)
218 			{
219 				_navigation.zoomTo(geo);
220 			}
221 		}
222 	};
223 
224 	/**************************************************************************************************************/
225 	
226 	 /**
227 	  * Public methods
228 	  */
229 			
230 	/** 
231 	 *	Setup the default event handlers for the _navigation
232 	 */
233 	this.install = function(nav)
234 	{
235 		_navigation = nav;
236 		
237 		var canvas = _navigation.globe.renderContext.canvas;
238 		
239 		// Setup the mouse event handlers
240 		canvas.addEventListener("mousedown", _handleMouseDown);
241 		canvas.addEventListener("mousemove", _handleMouseMove);
242 		
243 		if ( options.zoomOnDblClick )
244 			canvas.addEventListener("dblclick", _handleMouseDblClick);
245 			
246 		// For Firefox
247 		canvas.addEventListener("DOMMouseScroll", _handleMouseWheel);
248 		canvas.addEventListener("mousewheel", _handleMouseWheel);
249 	};
250 
251 	/** 
252 	 *	Remove the default event handlers for the _navigation
253 	 */
254 	this.uninstall = function()
255 	{
256 		// Setup the mouse event handlers
257 		var canvas = _navigation.globe.renderContext.canvas;
258 
259 		canvas.removeEventListener("mousedown", _handleMouseDown);
260 		canvas.removeEventListener("mousemove", _handleMouseMove);
261 		
262 		if ( options.zoomOnDblClick )
263 			canvas.removeEventListener("dblclick", _handleMouseDblClick);
264 			
265 		// For Firefox
266 		canvas.removeEventListener("DOMMouseScroll", _handleMouseWheel);
267 		canvas.removeEventListener("mousewheel", _handleMouseWheel);
268 	};
269 };
270 
271 return MouseNavigationHandler;
272 
273 });
274