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

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

The newest version!
/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2015 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 org.geomajas.geometry.Coordinate;
import org.geomajas.geometry.service.MathService;
import org.geomajas.gwt.client.map.RenderSpace;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.map.View;
import org.geomajas.gwt2.client.map.ViewPort;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.TouchEvent;

/**
 * Generic controller that is used on touch devices. Note that gestures and multi touch are not supported by some mobile
 * browsers.
 *
 * @author Jan De Moerloose
 * @since 2.0.0
 */
public class TouchNavigationController extends NavigationController implements PointerController {

	protected boolean zooming;

	protected Coordinate startCenter;

	protected double startDist;


	public void onMapTouchCancel(TouchEvent event) {
		onMapTouchEnd(event);
	}

	public void onMapTouchStart(TouchEvent event) {
		if (event.getTouches().length() == 2) {
			Coordinate p1 = getWorldLocation(event.getTouches().get(0), RenderSpace.WORLD);
			Coordinate p2 = getWorldLocation(event.getTouches().get(1), RenderSpace.WORLD);
			startCenter = getCenter(p1, p2);
			startDist = MathService.distance(p1, p2);
			stopPanning(null);
			this.zooming = true;
		} else {
			onDown(event);
		}
		event.preventDefault();
		event.stopPropagation();
	}

	public void onMapTouchMove(TouchEvent event) {
		if (event.getTouches().length() == 2 && zooming) {
			Coordinate p1 = getWorldLocation(event.getTouches().get(0), RenderSpace.WORLD);
			Coordinate p2 = getWorldLocation(event.getTouches().get(1), RenderSpace.WORLD);
			double scale = MathService.distance(p1, p2) / startDist;
			Coordinate newCenter = getCenter(p1, p2);
			double dx = startCenter.getX() - newCenter.getX();
			double dy = startCenter.getY() - newCenter.getY();
			double resolution = mapPresenter.getViewPort().getResolution() / scale;
			Coordinate position = calculatePosition(scale, startCenter);
			View view = new View(new Coordinate(position.getX() + dx, position.getY() + dy), resolution);
			view.setInteractive(true);
			mapPresenter.getViewPort().applyView(view);
		} else {
			onDrag(event);
		}
		event.preventDefault();
		event.stopPropagation();
	}

	public void onMapTouchEnd(TouchEvent event) {
		if (zooming) {
			if (event.getTouches().length() == 0) {
				zooming = false;
			}
			mapPresenter.getViewPort().stopInteraction();
		} else {
			onUp(event);
		}
		event.preventDefault();
		event.stopPropagation();
	}

	private Coordinate getWorldLocation(Touch touch, RenderSpace world) {
		Element element = mapPresenter.asWidget().getElement();
		Coordinate c = new Coordinate(touch.getRelativeX(element), touch.getRelativeY(element));
		return mapPresenter.getViewPort().getTransformationService()
				.transform(c, RenderSpace.SCREEN, RenderSpace.WORLD);
	}

	private Coordinate getCenter(Coordinate p1, Coordinate p2) {
		return new Coordinate(0.5 * (p1.getX() + p2.getX()), 0.5 * (p1.getY() + p2.getY()));
	}

	/**
	 * Calculate the target position should there be a rescale point. The idea is that after zooming in or out, the
	 * mouse cursor would still lie at the same position in world space.
	 */
	protected Coordinate calculatePosition(double scale, Coordinate rescalePoint) {
		ViewPort viewPort = mapPresenter.getViewPort();
		Coordinate position = viewPort.getPosition();
		double dX = (rescalePoint.getX() - position.getX()) * (1 - 1 / scale);
		double dY = (rescalePoint.getY() - position.getY()) * (1 - 1 / scale);
		return new Coordinate(position.getX() + dX, position.getY() + dY);
	}

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

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

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy