All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geomajas.gwt2.client.controller.TouchNavigationController Maven / Gradle / Ivy

/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2014 Geosparc nv, http://www.geosparc.com/, Belgium.
 *
 * The program is available in open source according to the GNU Affero
 * General Public License. All contributions in this program are covered
 * by the Geomajas Contributors License Agreement. For full licensing
 * details, see LICENSE.txt in the project root.
 */

package org.geomajas.gwt2.client.controller;

import com.google.gwt.event.dom.client.GestureChangeEvent;
import com.google.gwt.event.dom.client.GestureEndEvent;
import com.google.gwt.event.dom.client.GestureStartEvent;
import com.google.gwt.event.dom.client.TouchCancelEvent;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchEvent;
import com.google.gwt.event.dom.client.TouchMoveEvent;
import com.google.gwt.event.dom.client.TouchStartEvent;
import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.map.RenderSpace;
import org.geomajas.gwt2.client.map.MapPresenter;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Generic controller that is used on touch devices. Note that gestures and multi touch are not supported by some mobile
 * browsers.
 *
 * @author Dosi Bingov
 * @since 2.0.0
 */
public class TouchNavigationController extends AbstractMapController {

	private static Logger logger = Logger.getLogger("");

	protected Coordinate touchedOrigin;

	protected Coordinate lastTouchedPosition;

	protected boolean zooming;

	protected Coordinate centerPoint;

	private double beginResolution;

	public TouchNavigationController() {
		super(false);
	}

	// ------------------------------------------------------------------------
	// Touch events:
	// ------------------------------------------------------------------------

	@Override
	public void onTouchStart(TouchStartEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> onTouchStart()");
		event.preventDefault();
		lastTouchedPosition = getLocation(event, RenderSpace.WORLD);
		touchedOrigin = getLocation(event, RenderSpace.SCREEN);
		centerPoint = getMidPoint(event);
	}

	@Override
	public void onTouchEnd(TouchEndEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> onTouchEnd()");
		//TODO: it is never fired = find out what is wrong with that
	}

	@Override
	public void onTouchMove(TouchMoveEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> onTouchMove()");
		event.preventDefault();
		event.stopPropagation();
		panView(event);
	}

	@Override
	public void onTouchCancel(TouchCancelEvent event) {
		event.preventDefault();
		event.stopPropagation();
		logger.log(Level.INFO, "TouchNavigationController -> onTouchCancel()");
	}

	// ------------------------------------------------------------------------
	// Gesture events:
	// ------------------------------------------------------------------------

	@Override
	public void onGestureStart(GestureStartEvent event) {
		event.preventDefault();
		event.stopPropagation();
		beginResolution = mapPresenter.getViewPort().getResolution();
		zooming = true;
		logger.log(Level.INFO, "TouchNavigationController -> onGestureStart() viewport resolution=" + beginResolution);
		//zoomTo(event.getResolution(), false);
	}

	@Override
	public void onGestureEnd(GestureEndEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> onGestureEnd()");
		event.preventDefault();
		event.stopPropagation();
		zooming = false;
	}

	@Override
	public void onGestureChange(GestureChangeEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> onGestureChange()");
		event.preventDefault();
		event.stopPropagation();
		zoomTo(event.getScale());
	}

	// ------------------------------------------------------------------------
	// Methods:
	// ------------------------------------------------------------------------

	@Override
	public void onActivate(MapPresenter mapPresenter) {
		this.mapPresenter = mapPresenter;
		this.eventParser = mapPresenter.getMapEventParser();
	}

	@Override
	public void onDeactivate(MapPresenter mapPresenter) {
	}

	protected void zoomTo(double scale) {
		logger.log(Level.INFO, "TouchNavigationController -> zoomTo(resolution=" + scale + " )");
		logger.log(Level.INFO, "begin viewport resolution =" + beginResolution);
		double zoomResolution = beginResolution * scale;
		logger.log(Level.INFO, "zoomResolution=" + zoomResolution);
		mapPresenter.getViewPort().registerAnimation(null); // without animation for touch devices
		mapPresenter.getViewPort().applyResolution(zoomResolution);
		zooming = true;
	}

	/**
	 * Method used to calculate exact middle point between multiple touches of a touch events.
	 *
	 * @param event a touch event
	 * @return middle point
	 */
	protected Coordinate getMidPoint(TouchEvent event) {
		Coordinate[] coords = new Coordinate[event.getTouches().length()];
		for (int i = 0; i < event.getTargetTouches().length(); i++) {
			coords[i] = new Coordinate(event.getTouches().get(i).getClientX(), event.getTouches().get(i).getClientY());
		}

		double x = 0;
		double y = 0;

		for (Coordinate coord : coords) {
			x += coord.getX();
			y += coord.getY();
		}

		x /= coords.length;
		y /= coords.length;

		return new Coordinate(x, y);
	}

	/**
	 * Update the view of the map when touching and dragging.
	 *
	 * @param event
	 */
	protected void panView(TouchEvent event) {
		logger.log(Level.INFO, "TouchNavigationController -> panView(TouchEvent event, boolean isTouchEnded)");
		logger.log(Level.INFO, "zooming=" + zooming);
		if (zooming) {
			return;
		}

		Coordinate end = getMidPoint(event);
		mapPresenter.getViewPort().applyPosition(transformToMapCoords(end));
		touchedOrigin = end;
	}

	/**
	 * Transforms pixel coordinates to map coordinates.
	 *
	 * @param pixelCoords
	 * @return Coordinate object on the map
	 */
	protected Coordinate transformToMapCoords(Coordinate pixelCoords) {
		Coordinate beginWorld = mapPresenter.getViewPort().getTransformationService()
				.transform(touchedOrigin, RenderSpace.SCREEN, RenderSpace.WORLD);
		Coordinate endWorld = mapPresenter.getViewPort().getTransformationService()
				.transform(pixelCoords, RenderSpace.SCREEN, RenderSpace.WORLD);
		double x = mapPresenter.getViewPort().getPosition().getX() + beginWorld.getX() - endWorld.getX();
		double y = mapPresenter.getViewPort().getPosition().getY() + beginWorld.getY() - endWorld.getY();

		return new Coordinate(x, y);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy