/* * 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.plugin.editing.example.client.sample; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ResizeLayoutPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import org.geomajas.geometry.Bbox; import org.geomajas.geometry.Coordinate; import org.geomajas.geometry.Geometry; import org.geomajas.geometry.service.GeometryService; import org.geomajas.geometry.service.GeometryValidationState; import org.geomajas.gwt2.client.GeomajasImpl; import org.geomajas.gwt2.client.GeomajasServerExtension; import org.geomajas.gwt2.client.map.MapPresenter; import org.geomajas.gwt2.example.base.client.sample.SamplePanel; import org.geomajas.gwt2.plugin.editing.client.Editing; import org.geomajas.gwt2.plugin.editing.client.GeometryEditor; import org.geomajas.plugin.editing.client.event.GeometryEditChangeStateEvent; import org.geomajas.plugin.editing.client.event.GeometryEditChangeStateHandler; import org.geomajas.plugin.editing.client.event.GeometryEditStartEvent; import org.geomajas.plugin.editing.client.event.GeometryEditStartHandler; import org.geomajas.plugin.editing.client.event.GeometryEditStopEvent; import org.geomajas.plugin.editing.client.event.GeometryEditStopHandler; import org.geomajas.plugin.editing.client.event.GeometryEditValidationEvent; import org.geomajas.plugin.editing.client.event.GeometryEditValidationHandler; import org.geomajas.plugin.editing.client.operation.GeometryOperationFailedException; import org.geomajas.plugin.editing.client.service.GeometryEditService; import org.geomajas.plugin.editing.client.service.GeometryEditState; import org.geomajas.plugin.editing.client.service.GeometryIndex; import org.geomajas.plugin.editing.client.service.GeometryIndexType; import org.geomajas.plugin.editing.client.service.validation.GeometryValidator; /** * Sample that demonstrates validation of geometries when adding/editing. * * @author Pieter De Graef * @author Jan Venstermans */ public class GeometryValidationPanel implements SamplePanel { /** * UI binder for this widget. * * @author Pieter De Graef */ interface MyUiBinder extends UiBinder<Widget, GeometryValidationPanel> { } private static final MyUiBinder UI_BINDER = GWT.create(MyUiBinder.class); private MapPresenter mapPresenter; @UiField protected Button createBtn; @UiField protected Button editBtn; @UiField protected Button editCustomBtn; @UiField protected Button stopBtn; @UiField protected Button clearEventBtn; @UiField protected Button addRingBtn; @UiField protected ResizeLayoutPanel mapPanel; @UiField protected VerticalPanel validationEventLayout; private GeometryEditService editService; public Widget asWidget() { Widget layout = UI_BINDER.createAndBindUi(this); // Create the mapPresenter and add an InitializationHandler: mapPresenter = GeomajasImpl.getInstance().createMapPresenter(); mapPresenter.setSize(480, 480); // Define the whole layout: DecoratorPanel mapDecorator = new DecoratorPanel(); mapDecorator.add(mapPresenter.asWidget()); mapPanel.add(mapDecorator); // Initialize the map, and return the layout: GeomajasServerExtension.getInstance().initializeMap(mapPresenter, "appEditingExample", "mapEditingExampleOsm"); // Prepare editing: GeometryEditor editor = Editing.getInstance().createGeometryEditor(mapPresenter); editService = editor.getEditService(); // Add editing handlers that change the enabled state of the buttons: editService.addGeometryEditStartHandler(new GeometryEditStartHandler() { @Override public void onGeometryEditStart(GeometryEditStartEvent event) { createBtn.setEnabled(false); editBtn.setEnabled(false); editCustomBtn.setEnabled(false); stopBtn.setEnabled(true); addRingBtn.setVisible(true); } }); editService.addGeometryEditStopHandler(new GeometryEditStopHandler() { @Override public void onGeometryEditStop(GeometryEditStopEvent event) { createBtn.setEnabled(true); editBtn.setEnabled(true); editCustomBtn.setEnabled(true); stopBtn.setEnabled(false); addRingBtn.setVisible(false); } }); editService.addGeometryEditChangeStateHandler(new GeometryEditChangeStateHandler() { @Override public void onChangeEditingState(GeometryEditChangeStateEvent event) { // Only enable the "add ring" button when the user is not busy creating a new polygon (state INSERTING). addRingBtn.setEnabled(editService.getEditingState() == GeometryEditState.IDLE); } }); editService.addGeometryEditValidationHandler(new MyGeometryValidationHandler()); return layout; } @UiHandler("createBtn") protected void onCreateButtonClicked(ClickEvent event) { validationEventLayout.clear(); // Create an empty point geometry. It has no coordinate yet. That is up to the user... Geometry point = new Geometry(Geometry.POLYGON, 0, -1); // Enable default validation editService.setDefaultValidation(true); editService.start(point); // Set the editing service in "INSERTING" mode. Make sure it starts inserting in the correct index. try { // Add an empty LinearRing to the Polygon. GeometryIndex index = editService.addEmptyChild(); // Make sure we can start adding coordinates into the empty LinearRing: index = editService.getIndexService().addChildren(index, GeometryIndexType.TYPE_VERTEX, 0); // Set state to "inserting". The user must start clicking on the map to insert additional points: editService.setEditingState(GeometryEditState.INSERTING); // Make sure the service knows where to insert (in the empty LinearRing): editService.setInsertIndex(index); } catch (GeometryOperationFailedException e) { e.printStackTrace(); } // Et voila, the use may now click on the map... } @UiHandler("editBtn") protected void onEditButtonClicked(ClickEvent event) { validationEventLayout.clear(); // Create a point geometry in the center of the map: Geometry ring = new Geometry(Geometry.LINEAR_RING, 0, -1); Bbox bounds = mapPresenter.getViewPort().getBounds(); double x1 = bounds.getX() + bounds.getWidth() / 4; double x2 = bounds.getMaxX() - bounds.getWidth() / 4; double y1 = bounds.getY() + bounds.getHeight() / 4; double y2 = bounds.getMaxY() - bounds.getHeight() / 4; ring.setCoordinates(new Coordinate[] { new Coordinate(x1, y1), new Coordinate(x2, y1), new Coordinate(x2, y2), new Coordinate(x1, y2), new Coordinate(x1, y1) }); Geometry polygon = new Geometry(Geometry.POLYGON, 0, 5); polygon.setGeometries(new Geometry[] { ring }); // Enable default validation editService.setDefaultValidation(true); // Now start editing it: editService.start(polygon); } @UiHandler("editCustomBtn") protected void onEditCustomButtonClicked(ClickEvent event) { validationEventLayout.clear(); // Create a point geometry in the center of the map: Geometry ring = new Geometry(Geometry.LINEAR_RING, 0, -1); Bbox bounds = mapPresenter.getViewPort().getBounds(); double x1 = bounds.getX() + bounds.getWidth() / 4; double x2 = bounds.getMaxX() - bounds.getWidth() / 4; double y1 = bounds.getY() + bounds.getHeight() / 4; double y2 = bounds.getMaxY() - bounds.getHeight() / 4; ring.setCoordinates(new Coordinate[] { new Coordinate(x1, y1), new Coordinate(x2, y1), new Coordinate(x2, y2), new Coordinate(x1, y2), new Coordinate(x1, y1) }); Geometry polygon = new Geometry(Geometry.POLYGON, 0, 5); polygon.setGeometries(new Geometry[] { ring }); // Set a custom validator: editService.setValidator(new GeometryValidator() { private boolean rollBack; @Override public GeometryValidationState validate(Geometry geometry, GeometryIndex index) { if (GeometryService.getNumPoints(geometry) > 7) { rollBack = true; return GeometryValidationState.INVALID_COORDINATE; } rollBack = false; return GeometryValidationState.VALID; } @Override public boolean isRollBack() { return rollBack; } @Override public Object getValidationContext() { return null; } }); editService.start(polygon); } @UiHandler("addRingBtn") protected void onAddRingButtonClicked(ClickEvent event) { // Set the editing service in "INSERTING" mode. Make sure it starts inserting in the correct index. try { // Add an empty LinearRing to the Polygon. Geometry polygon = editService.getGeometry(); GeometryIndex index = editService.getIndexService().create(GeometryIndexType.TYPE_GEOMETRY, polygon.getGeometries().length); index = editService.addEmptyChild(index); // Make sure we can start adding coordinates into the empty LinearRing: index = editService.getIndexService().addChildren(index, GeometryIndexType.TYPE_VERTEX, 0); // Set state to "inserting". The user must start clicking on the map to insert additional points: editService.setEditingState(GeometryEditState.INSERTING); // Make sure the service knows where to insert (in the empty LinearRing): editService.setInsertIndex(index); } catch (GeometryOperationFailedException e) { e.printStackTrace(); } } @UiHandler("stopBtn") protected void onStopButtonClicked(ClickEvent event) { editService.stop(); } @UiHandler("clearEventBtn") protected void onClearEventsButtonClicked(ClickEvent event) { validationEventLayout.clear(); } /** * Handler that catches events of geometry validation. * * @author Jan Venstermans */ private class MyGeometryValidationHandler implements GeometryEditValidationHandler { @Override public void onGeometryEditValidation(GeometryEditValidationEvent event) { if (!event.getValidationState().isValid()) { validationEventLayout.add(new Label("Geometry invalid: " + event.getValidationState().toString())); } } } }