/* * 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 org.geomajas.geometry.Coordinate; import org.geomajas.gwt.client.gfx.PaintableGroup; import org.geomajas.gwt.client.gfx.paintable.Composite; import org.geomajas.gwt.client.gfx.style.ShapeStyle; import org.geomajas.gwt.client.spatial.geometry.LineString; import org.geomajas.gwt.client.widget.MapWidget; import org.geomajas.gwt.client.widget.MapWidget.RenderGroup; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseEvent; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseUpEvent; /** * <p> * Base controller which handles the display of circles, by dragging the mouse. When creating extensions of this class, * one should always implement the <code>onCircleReady</code> method. It is called when a circle has been successfully * drawn (on the mouse up event). * </p> * <p> * This class also has a few protected methods that may assist in getting crucial data regarding the circle that is * being or has been drawn. See <code>getScreenCenter</code>, <code>getScreenRadius</code>, <code>getWorldCenter</code>, * <code>getWorldRadius</code>. * </p> * * @author Pieter De Graef */ public abstract class AbstractCircleController extends AbstractGraphicsController { private PaintableGroup circleGroup = new Composite("circle"); private Coordinate center; // In screen coordinates. private double radius; protected ShapeStyle circleStyle = new ShapeStyle("#FF9900", 0.2f, "#FF9900", 0.8f, 2); protected boolean dragging; // ------------------------------------------------------------------------- // Constructors // ------------------------------------------------------------------------- public AbstractCircleController(MapWidget mapWidget) { super(mapWidget); } // ------------------------------------------------------------------------- // GraphicsController implementation: // ------------------------------------------------------------------------- /** * Register center point for the circle, and start dragging and rendering. * * @param event * event */ public void onMouseDown(MouseDownEvent event) { if (event.getNativeButton() != NativeEvent.BUTTON_RIGHT) { dragging = true; center = getScreenPosition(event); LineString radiusLine = mapWidget.getMapModel().getGeometryFactory().createLineString( new Coordinate[] { center, center }); mapWidget.getVectorContext().drawGroup(mapWidget.getGroup(RenderGroup.SCREEN), circleGroup); mapWidget.getVectorContext().drawCircle(circleGroup, "outer", center, 1.0f, circleStyle); mapWidget.getVectorContext().drawCircle(circleGroup, "center", center, 2.0f, circleStyle); mapWidget.getVectorContext().drawLine(circleGroup, "radius", radiusLine, circleStyle); } } /** * Finish drawing the circle. At this point, the circle is removed from the map, but not before the * <code>onCircleReady</code> method is called. This abstract method should be implemented by extending classes. * Therein, one can call all the protected methods in this class (<code>getScreenCenter</code>, * <code>getScreenRadius</code>, <code>getWorldCenter</code>, <code>getWorldRadius</code>). */ public void onMouseUp(MouseUpEvent event) { if (dragging) { // Assure dragging or clicking started inside this widget. updateGraphics(event); onCircleReady(); stopDragging(); } } /** Update the rendering of the circle. */ public void onMouseMove(MouseMoveEvent event) { if (dragging) { // Assure dragging or clicking started inside this widget. updateGraphics(event); } } /** Remove the circle from the map. */ public void onMouseOut(MouseOutEvent event) { stopDragging(); } // ------------------------------------------------------------------------- // Protected methods: // ------------------------------------------------------------------------- /** * Method one should implement when using this class. It is called when a circle has been successfully drawn. (on * the mouse up event) */ protected abstract void onCircleReady(); /** Return the center position of the circle in screen coordinates. */ protected Coordinate getScreenCenter() { return center; } /** Return the circle's radius in screen pixels. */ protected double getScreenRadius() { return radius; } /** Return the center position of the circle in world coordinates. */ protected Coordinate getWorldCenter() { if (center != null) { return mapWidget.getMapModel().getMapView().getWorldViewTransformer().viewToWorld(center); } return null; } /** Return the circle's radius in world length units. */ protected double getWorldRadius() { if (center != null) { Coordinate screenEndPoint = new Coordinate(center.getX() + radius, center.getY()); Coordinate worldEndPoint = mapWidget.getMapModel().getMapView().getWorldViewTransformer().viewToWorld( screenEndPoint); double deltaX = worldEndPoint.getX() - getWorldCenter().getX(); double deltaY = worldEndPoint.getY() - getWorldCenter().getY(); return (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)); } return 0; } // ------------------------------------------------------------------------- // Private methods: // ------------------------------------------------------------------------- private void stopDragging() { if (dragging) { dragging = false; mapWidget.getVectorContext().deleteGroup(circleGroup); center = null; radius = 0; } } private void updateGraphics(MouseEvent<?> event) { Coordinate position = getScreenPosition(event); double deltaX = position.getX() - getScreenCenter().getX(); double deltaY = position.getY() - getScreenCenter().getY(); radius = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)); LineString radiusLine = mapWidget.getMapModel().getGeometryFactory().createLineString( new Coordinate[] { center, position }); mapWidget.getVectorContext().drawCircle(circleGroup, "outer", center, radius, circleStyle); mapWidget.getVectorContext().drawLine(circleGroup, "radius", radiusLine, circleStyle); } }