/*
* 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.gwt.client.controller;
import java.util.List;
import org.geomajas.configuration.SnappingRuleInfo;
import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.spatial.snapping.Snapper;
import org.geomajas.gwt.client.spatial.snapping.Snapper.SnapMode;
import org.geomajas.gwt.client.widget.MapWidget;
import com.google.gwt.event.dom.client.MouseEvent;
/**
* <p>
* Basic controller to start building upon when you need snapping. Using snapping goes through the "getScreenPosition"
* and "getWorldPosition" methods. These will return snapped points instead of the actual points , but only when
* snapping is activated. Snapping can be activated and deactivated at any time. Activating snapping, requires you to
* pass along a list of snapping rules to follow, and a snapping mode. (SnapMode.MODE_ALL_GEOMTRIES_EQUAL or
* SnapMode.MODE_PRIORITY_TO_INTERSECTING_GEOMETRIES)
* </p>
*
* @author Pieter De Graef
*/
public abstract class AbstractSnappingController extends AbstractGraphicsController {
/**
* The internal snapper that is used for the snapping functionality.
*/
private Snapper snapper;
/**
* Boolean that indicates whether or not snapping is currently active.
*/
private boolean snappingActive;
// -------------------------------------------------------------------------
// Constructor:
// -------------------------------------------------------------------------
/**
* Just like the <code>AbstractSnappingController</code>, this class expects a map widget at construction.
*/
protected AbstractSnappingController(MapWidget mapWidget) {
super(mapWidget);
}
// -------------------------------------------------------------------------
// Protected methods:
// -------------------------------------------------------------------------
/**
* Activate snapping on this controller. When snapping is activated, the methods "getScreenPosition" and
* "getWorldPosition" (to ask the position of an event), will return snapped positions.
*
* @param rules
* A list of <code>SnappingRuleInfo</code>s. These determine to what layers to snap, using what distances
* and what algorithms.
* @param mode
* The snapper mode. Either the snapper considers all geometries equal, or it tries to snap to
* intersecting geometries before snapping to other geometries. Basically:
* <ul>
* <li>SnapMode.MODE_ALL_GEOMTRIES_EQUAL</li>
* <li>SnapMode.MODE_PRIORITY_TO_INTERSECTING_GEOMETRIES</li>
* </ul>
*/
public void activateSnapping(List<SnappingRuleInfo> rules, SnapMode mode) {
if (rules != null) {
snapper = new Snapper(mapWidget.getMapModel(), rules, mode);
snappingActive = true;
}
}
/**
* Deactivate snapping for the time being. Snapping can be activated again at any time.
*/
public void deactivateSnapping() {
snappingActive = false;
}
/**
* Return the screen position of the mouse event, unless snapping is activated. If that is the case, a snapped
* point will be returned (still in screen space).
*/
protected Coordinate getScreenPosition(MouseEvent<?> event) {
if (snappingActive) {
return getTransformer().worldToView(getWorldPosition(event));
}
return super.getScreenPosition(event);
}
/**
* Return the screen position of the mouse event, unless snapping is activated. If that is the case, a snapped
* point will be returned (still in pan space).
*/
protected Coordinate getPanPosition(MouseEvent<?> event) {
if (snappingActive) {
return getTransformer().worldToPan(getWorldPosition(event));
}
return super.getPanPosition(event);
}
/**
* Return the world position of the mouse event, unless snapping is activated. If that is the case, a snapped point
* will be returned (still in world space).
*/
protected Coordinate getWorldPosition(MouseEvent<?> event) {
Coordinate world = super.getWorldPosition(event);
if (snappingActive) {
return snapper.snap(world);
}
return world;
}
// -------------------------------------------------------------------------
// Getters:
// -------------------------------------------------------------------------
/**
* Return the used snapper. (can be null)
*
* @return {@link Snapper} object
*/
public Snapper getSnapper() {
return snapper;
}
/**
* See whether or not snapping is currently activated.
*
* @return true when snapping is active
*/
public boolean isSnappingActive() {
return snappingActive;
}
}