/* * 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.plugin.editing.gwt.example.client.widget; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.geomajas.geometry.Geometry; import org.geomajas.gwt.client.handler.MapUpHandler; 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.gfx.GeometryRenderer; import org.geomajas.plugin.editing.client.handler.AbstractGeometryIndexMapHandler; import org.geomajas.plugin.editing.client.handler.GeometryIndexMapHandlerFactory; import org.geomajas.plugin.editing.client.operation.GeometryOperationFailedException; import org.geomajas.plugin.editing.client.service.GeometryEditService; import org.geomajas.plugin.editing.client.service.GeometryIndex; import org.geomajas.plugin.editing.client.service.GeometryIndexNotFoundException; import org.geomajas.plugin.editing.client.service.GeometryIndexType; import org.geomajas.plugin.editing.gwt.client.handler.EditingHandlerRegistry; import org.geomajas.plugin.editing.gwt.example.client.event.GeometryEditResumeEvent; import org.geomajas.plugin.editing.gwt.example.client.event.GeometryEditSuspendEvent; import org.geomajas.plugin.editing.gwt.example.client.event.GeometryEditSuspendReason; import com.google.gwt.event.dom.client.HumanInputEvent; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.user.client.Window; import com.smartgwt.client.types.SelectionType; import com.smartgwt.client.widgets.events.ClickEvent; import com.smartgwt.client.widgets.events.ClickHandler; import com.smartgwt.client.widgets.toolbar.ToolStripButton; /** * Toolbar button for deleting inner rings from a polygon. * * @author Pieter De Graef */ public class DeleteRingBtn extends ToolStripButton implements GeometryEditStartHandler, GeometryEditStopHandler { private MenuBar menuBar; private GeometryEditService service; private GeometryIndexMapHandlerFactory factory; public DeleteRingBtn(final MenuBar menuBar, final GeometryEditService service, final GeometryRenderer renderer) { this.menuBar = menuBar; this.service = service; factory = new GeometryIndexMapHandlerFactory() { public AbstractGeometryIndexMapHandler create() { return new DeleteRingHandler(); } }; setDisabled(true); setHoverWidth(300); setActionType(SelectionType.CHECKBOX); setTooltip("Remove an interior ring from the geometry by clicking on it."); setIcon("[ISOMORPHIC]/geomajas/osgeo/ring-delete.png"); setIconSize(24); setHeight(32); addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { if (isSelected()) { disableVerticesAndEdges(null, service.getGeometry()); // We change the registry by adding a handler that deletes inner rings: EditingHandlerRegistry.addGeometryHandlerFactory(factory); // Trigger a redraw to apply the change in the registry: renderer.redraw(); menuBar.getEventBus() .fireEvent(new GeometryEditSuspendEvent(GeometryEditSuspendReason.REMOVE_RING)); } else { resumeNormalBehavior(); } } }); service.addGeometryEditStartHandler(this); service.addGeometryEditStopHandler(this); } // ------------------------------------------------------------------------ // GeometryEditWorkflowHandler implementation: // ------------------------------------------------------------------------ public void onGeometryEditStart(GeometryEditStartEvent event) { String geometryType = service.getGeometry().getGeometryType(); if (Geometry.LINEAR_RING.equals(geometryType) || Geometry.POLYGON.equals(geometryType) || Geometry.MULTI_POLYGON.equals(geometryType)) { setDisabled(false); } } public void onGeometryEditStop(GeometryEditStopEvent event) { setDisabled(true); } private void disableVerticesAndEdges(GeometryIndex geomIndex, Geometry geometry) { if (geometry.getGeometries() != null) { for (int i = 0; i < geometry.getGeometries().length; i++) { GeometryIndex childIndex = service.getIndexService().addChildren(geomIndex, GeometryIndexType.TYPE_GEOMETRY, i); disableVerticesAndEdges(childIndex, geometry.getGeometries()[i]); } // Also disable background for polygons: if (Geometry.POLYGON.equals(geometry.getGeometryType())) { GeometryIndex shellIndex = service.getIndexService().addChildren(geomIndex, GeometryIndexType.TYPE_GEOMETRY, 0); service.getIndexStateService().disable(Collections.singletonList(shellIndex)); } } if (geometry.getCoordinates() != null) { List<GeometryIndex> toDisable = new ArrayList<GeometryIndex>(); for (int i = 0; i < geometry.getCoordinates().length - 1; i++) { toDisable.add(service.getIndexService().addChildren(geomIndex, GeometryIndexType.TYPE_VERTEX, i)); toDisable.add(service.getIndexService().addChildren(geomIndex, GeometryIndexType.TYPE_EDGE, i)); } service.getIndexStateService().disable(toDisable); } } private void resumeNormalBehavior() { EditingHandlerRegistry.removeGeometryHandlerFactory(factory); service.getIndexStateService().enableAll(); menuBar.getEventBus().fireEvent(new GeometryEditResumeEvent()); } // ------------------------------------------------------------------------ // Private classes: // ------------------------------------------------------------------------ /** * Private handler that deletes a ring when the user clicks on it. * * @author Pieter De Graef */ private class DeleteRingHandler extends AbstractGeometryIndexMapHandler implements MapUpHandler, MouseOverHandler, MouseOutHandler { public void onUp(HumanInputEvent<?> event) { if (service.getIndexStateService().isMarkedForDeletion(index)) { try { service.remove(Collections.singletonList(index)); } catch (GeometryOperationFailedException e) { Window.alert("Error occurred while deleting the inner ring: " + e.getMessage()); } resumeNormalBehavior(); setSelected(false); } } public void onMouseOver(MouseOverEvent event) { try { String geometryType = service.getIndexService().getGeometryType(service.getGeometry(), index); if (Geometry.LINEAR_RING.equals(geometryType) || Geometry.POLYGON.equals(geometryType) || Geometry.MULTI_POLYGON.equals(geometryType)) { if (service.getIndexService().getValue(index) > 0) { // Only inner rings must be marked. The outer shell can remain as-is. service.getIndexStateService().markForDeletionBegin(Collections.singletonList(index)); } } } catch (GeometryIndexNotFoundException e) { Window.alert("Error occurred while deleting the inner ring: " + e.getMessage()); } } public void onMouseOut(MouseOutEvent event) { if (service.getIndexStateService().isMarkedForDeletion(index)) { service.getIndexStateService().markForDeletionEnd(Collections.singletonList(index)); } } } }