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

org.geomajas.gwt2.client.controller.NavigationController 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 org.geomajas.annotation.Api;
import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.map.RenderSpace;
import org.geomajas.gwt2.client.animation.NavigationAnimationFactory;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.map.ViewPort;

import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.HumanInputEvent;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseWheelEvent;

/**
 * Generic navigation map controller. This controller allows for panning and zooming on the map in many different ways.
 * Options are the following:
 * 
    *
  • Panning: Drag the map to pan.
  • *
  • Double click: Double clicking on some location will see the map zoom in to that location.
  • *
  • Zoom to rectangle: By holding shift or ctrl and dragging at the same time, a rectangle will appear on the * map. On mouse up, the map will than zoom to that rectangle.
  • *
  • *
* For zooming using the mouse wheel there are 2 options, defined by the {@link ScrollZoomType} enum. These options are * the following: *
    *
  • ScrollZoomType.ZOOM_CENTER: Zoom in/out so that the current center of the map remains.
  • *
  • ScrollZoomType.ZOOM_POSITION: Zoom in/out so that the mouse world position remains the same. Can be great * for many subsequent double clicks, to make sure you keep zooming to the same location (wherever the mouse points to). *
  • *
* * @author Pieter De Graef * @since 2.0.0 */ @Api(allMethods = true) public class NavigationController extends AbstractMapController { /** Zooming types on mouse wheel scroll. */ public static enum ScrollZoomType { /** When scroll zooming, retain the center of the map position. */ ZOOM_CENTER, /** When scroll zooming, retain the mouse position. */ ZOOM_POSITION } private final ZoomToRectangleController zoomToRectangleController; protected Coordinate dragOrigin; protected Coordinate lastClickPosition; protected boolean zooming; protected boolean dragging; private ScrollZoomType scrollZoomType = ScrollZoomType.ZOOM_POSITION; // ------------------------------------------------------------------------ // Constructors: // ------------------------------------------------------------------------ /** Create a NavigationController instance. */ public NavigationController() { super(false); zoomToRectangleController = new ZoomToRectangleController(); } // ------------------------------------------------------------------------ // MapController implementation: // ------------------------------------------------------------------------ @Override public void onActivate(MapPresenter mapPresenter) { super.onActivate(mapPresenter); zoomToRectangleController.onActivate(mapPresenter); } @Override public void onMouseDown(MouseDownEvent event) { super.onMouseDown(event); if (event.isControlKeyDown() || event.isShiftKeyDown()) { // Trigger the dragging on the zoomToRectangleController: zoomToRectangleController.onMouseDown(event); } } @Override public void onDown(HumanInputEvent event) { if (event.isControlKeyDown() || event.isShiftKeyDown()) { zooming = true; } else if (!isRightMouseButton(event)) { dragging = true; dragOrigin = getLocation(event, RenderSpace.SCREEN); mapPresenter.setCursor("move"); } lastClickPosition = getLocation(event, RenderSpace.WORLD); } @Override public void onUp(HumanInputEvent event) { if (zooming) { zoomToRectangleController.onUp(event); zooming = false; } else if (dragging) { stopPanning(event); } } @Override public void onMouseMove(MouseMoveEvent event) { if (zooming) { zoomToRectangleController.onMouseMove(event); } else if (dragging) { super.onMouseMove(event); } } @Override public void onDrag(HumanInputEvent event) { updateView(event); } @Override public void onMouseOut(MouseOutEvent event) { if (zooming) { zoomToRectangleController.onMouseOut(event); } else { stopPanning(null); } } @Override public void onDoubleClick(DoubleClickEvent event) { mapPresenter.getViewPort().registerAnimation( NavigationAnimationFactory.createZoomIn(mapPresenter, calculatePosition(true, lastClickPosition))); } @Override public void onMouseWheel(MouseWheelEvent event) { final boolean isNorth; if (event.getDeltaY() == 0) { isNorth = (getWheelDelta(event.getNativeEvent()) < 0); } else { isNorth = event.isNorth(); } Coordinate location = getLocation(event, RenderSpace.WORLD); scrollZoomTo(isNorth, location); } // ------------------------------------------------------------------------ // Getters and setters: // ------------------------------------------------------------------------ /** * Get the scroll zoom type of this controller. * * @return the scroll zoom type. */ public ScrollZoomType getScrollZoomType() { return scrollZoomType; } /** * Set the scroll zoom type of this controller. * * @param scrollZoomType * the scroll zoom type. */ public void setScrollZoomType(ScrollZoomType scrollZoomType) { this.scrollZoomType = scrollZoomType; } // ------------------------------------------------------------------------ // Private methods: // ------------------------------------------------------------------------ protected void stopPanning(HumanInputEvent event) { dragging = false; mapPresenter.setCursor("default"); if (null != event) { updateView(event); } } protected void updateView(HumanInputEvent event) { Coordinate end = getLocation(event, RenderSpace.SCREEN); Coordinate beginWorld = mapPresenter.getViewPort().getTransformationService() .transform(dragOrigin, RenderSpace.SCREEN, RenderSpace.WORLD); Coordinate endWorld = mapPresenter.getViewPort().getTransformationService() .transform(end, RenderSpace.SCREEN, RenderSpace.WORLD); double x = mapPresenter.getViewPort().getPosition().getX() + beginWorld.getX() - endWorld.getX(); double y = mapPresenter.getViewPort().getPosition().getY() + beginWorld.getY() - endWorld.getY(); mapPresenter.getViewPort().applyPosition(new Coordinate(x, y)); dragOrigin = end; } protected native int getWheelDelta(NativeEvent evt) /*-{ return Math.round(-evt.wheelDelta) || 0; }-*/; protected void scrollZoomTo(boolean isNorth, Coordinate location) { ViewPort viewPort = mapPresenter.getViewPort(); int index = viewPort.getResolutionIndex(viewPort.getResolution()); if (isNorth) { if (index < viewPort.getResolutionCount() - 1) { if (scrollZoomType == ScrollZoomType.ZOOM_POSITION) { Coordinate position = calculatePosition(true, location); viewPort.registerAnimation(NavigationAnimationFactory.createZoomIn(mapPresenter, position)); } else { viewPort.registerAnimation(NavigationAnimationFactory.createZoomIn(mapPresenter)); } } } else { if (index > 0) { if (scrollZoomType == ScrollZoomType.ZOOM_POSITION) { Coordinate position = calculatePosition(false, location); viewPort.registerAnimation(NavigationAnimationFactory.createZoomOut(mapPresenter, position)); } else { viewPort.registerAnimation(NavigationAnimationFactory.createZoomOut(mapPresenter)); } } } } /** * 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(boolean zoomIn, Coordinate rescalePoint) { ViewPort viewPort = mapPresenter.getViewPort(); Coordinate position = viewPort.getPosition(); int index = viewPort.getResolutionIndex(viewPort.getResolution()); double resolution = viewPort.getResolution(); if (zoomIn && index < viewPort.getResolutionCount() - 1) { resolution = viewPort.getResolution(index + 1); } else if (!zoomIn && index > 0) { resolution = viewPort.getResolution(index - 1); } double factor = viewPort.getResolution() / resolution; double dX = (rescalePoint.getX() - position.getX()) * (1 - 1 / factor); double dY = (rescalePoint.getY() - position.getY()) * (1 - 1 / factor); return new Coordinate(position.getX() + dX, position.getY() + dY); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy