/* * 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.client.service; import java.util.ArrayList; import java.util.List; import org.geomajas.plugin.editing.client.event.state.GeometryIndexDeselectedEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexDeselectedHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexDisabledEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexDisabledHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexEnabledEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexEnabledHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexHighlightBeginEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexHighlightBeginHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexHighlightEndEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexHighlightEndHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexMarkForDeletionBeginEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexMarkForDeletionBeginHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexMarkForDeletionEndEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexMarkForDeletionEndHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSelectedEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSelectedHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSnappingBeginEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSnappingBeginHandler; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSnappingEndEvent; import org.geomajas.plugin.editing.client.event.state.GeometryIndexSnappingEndHandler; import com.google.gwt.event.shared.HandlerRegistration; /** * <p> * Service that keeps track of the state of all the individual parts of the geometry being edited. The supported states * for any part of a geometry are the following: * <ul> * <li><b>Selection</b>: vertices and edges can be selected. This selection process can assist the user in his * operations. Specific controllers could then allow for the operations to be performed on this selection only. For * example dragging of selected vertices.</li> * <li><b>Highlighting</b>: vertices and edges can be highlighted usually when the mouse hovers over them.</li> * <li><b>Marked for deletion</b>: vertices and edges can be marked for deletion. Specific controllers could then be * implement actions for the user for actually delete the indices that are marked.</li> * <li><b>Enabled/Disabled</b>: All parts of the geometry can be individually enabled/disabled for further editing.</li> * <li><b>Snapping</b>: During dragging or inserting it can be possible that snapping is being used. This state keeps * track of whether or not any vertices have snapped to some external geometry.</li> * </ul> * </p> * * @author Pieter De Graef */ public class GeometryIndexStateServiceImpl implements GeometryIndexStateService { private final List<GeometryIndex> highlights = new ArrayList<GeometryIndex>(); private final List<GeometryIndex> markedForDeletion = new ArrayList<GeometryIndex>(); private final List<GeometryIndex> selection = new ArrayList<GeometryIndex>(); private final List<GeometryIndex> disabled = new ArrayList<GeometryIndex>(); private final List<GeometryIndex> snapped = new ArrayList<GeometryIndex>(); private final GeometryEditServiceImpl editingService; // ------------------------------------------------------------------------ // Public constructors: // ------------------------------------------------------------------------ /** * Initialize this service with a reference to the editing service to which this service belongs. * * @param editingService * The editing service to which this service belongs. */ protected GeometryIndexStateServiceImpl(GeometryEditServiceImpl editingService) { this.editingService = editingService; } // ------------------------------------------------------------------------ // Methods concerning Vertex/Edge selection: // ------------------------------------------------------------------------ @Override public HandlerRegistration addGeometryIndexSelectedHandler(GeometryIndexSelectedHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexSelectedHandler.TYPE, handler); } @Override public HandlerRegistration addGeometryIndexDeselectedHandler(GeometryIndexDeselectedHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexDeselectedHandler.TYPE, handler); } @Override public void select(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (!selection.contains(index)) { temp.add(index); } } selection.addAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexSelectedEvent(editingService.getGeometry(), temp)); } @Override public void deselect(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (selection.contains(index)) { temp.add(index); } } selection.removeAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexDeselectedEvent(editingService.getGeometry(), temp)); } @Override public void deselectAll() { if (selection.size() > 0) { List<GeometryIndex> clone = new ArrayList<GeometryIndex>(selection); selection.clear(); editingService.getEventBus().fireEvent( new GeometryIndexDeselectedEvent(editingService.getGeometry(), clone)); } } @Override public boolean isSelected(GeometryIndex index) { return selection.contains(index); } @Override public List<GeometryIndex> getSelection() { return selection; } // ------------------------------------------------------------------------ // Methods concerning disabling of indices: // ------------------------------------------------------------------------ @Override public HandlerRegistration addGeometryIndexDisabledHandler(GeometryIndexDisabledHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexDisabledHandler.TYPE, handler); } @Override public HandlerRegistration addGeometryIndexEnabledHandler(GeometryIndexEnabledHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexEnabledHandler.TYPE, handler); } @Override public void enable(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (disabled.contains(index)) { temp.add(index); } } disabled.removeAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexEnabledEvent(editingService.getGeometry(), temp)); } @Override public void disable(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (!disabled.contains(index)) { temp.add(index); } } disabled.addAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexDisabledEvent(editingService.getGeometry(), temp)); } @Override public void enableAll() { if (disabled.size() > 0) { List<GeometryIndex> clone = new ArrayList<GeometryIndex>(disabled); disabled.clear(); editingService.getEventBus().fireEvent(new GeometryIndexEnabledEvent(editingService.getGeometry(), clone)); } } @Override public boolean isEnabled(GeometryIndex index) { return !disabled.contains(index); } // ------------------------------------------------------------------------ // Methods concerning highlighting: // ------------------------------------------------------------------------ @Override public HandlerRegistration addGeometryIndexHighlightBeginHandler(GeometryIndexHighlightBeginHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexHighlightBeginHandler.TYPE, handler); } @Override public HandlerRegistration addGeometryIndexHighlightEndHandler(GeometryIndexHighlightEndHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexHighlightEndHandler.TYPE, handler); } @Override public void highlightBegin(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (!highlights.contains(index)) { temp.add(index); } } highlights.addAll(temp); editingService.getEventBus() .fireEvent(new GeometryIndexHighlightBeginEvent(editingService.getGeometry(), temp)); } @Override public void highlightEnd(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (highlights.contains(index)) { temp.add(index); } } highlights.removeAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexHighlightEndEvent(editingService.getGeometry(), temp)); } @Override public void highlightEndAll() { if (highlights.size() > 0) { List<GeometryIndex> clone = new ArrayList<GeometryIndex>(highlights); highlights.clear(); editingService.getEventBus().fireEvent( new GeometryIndexHighlightEndEvent(editingService.getGeometry(), clone)); } } @Override public boolean isHightlighted(GeometryIndex index) { return highlights.contains(index); } // ------------------------------------------------------------------------ // Methods concerning the mark for deletion: // ------------------------------------------------------------------------ @Override public HandlerRegistration addGeometryIndexMarkForDeletionBeginHandler( GeometryIndexMarkForDeletionBeginHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexMarkForDeletionBeginHandler.TYPE, handler); } @Override public HandlerRegistration addGeometryIndexMarkForDeletionEndHandler(GeometryIndexMarkForDeletionEndHandler h) { return editingService.getEventBus().addHandler(GeometryIndexMarkForDeletionEndHandler.TYPE, h); } @Override public void markForDeletionBegin(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (!markedForDeletion.contains(index)) { temp.add(index); } } markedForDeletion.addAll(temp); editingService.getEventBus().fireEvent( new GeometryIndexMarkForDeletionBeginEvent(editingService.getGeometry(), temp)); } @Override public void markForDeletionEnd(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (markedForDeletion.contains(index)) { temp.add(index); } } markedForDeletion.removeAll(temp); editingService.getEventBus().fireEvent( new GeometryIndexMarkForDeletionEndEvent(editingService.getGeometry(), temp)); } @Override public void markForDeletionEndAll() { if (markedForDeletion.size() > 0) { List<GeometryIndex> clone = new ArrayList<GeometryIndex>(markedForDeletion); markedForDeletion.clear(); editingService.getEventBus().fireEvent( new GeometryIndexMarkForDeletionEndEvent(editingService.getGeometry(), clone)); } } @Override public boolean isMarkedForDeletion(GeometryIndex index) { return markedForDeletion.contains(index); } // ------------------------------------------------------------------------ // Methods concerning snapping: // ------------------------------------------------------------------------ @Override public HandlerRegistration addGeometryIndexSnappingBeginHandler(GeometryIndexSnappingBeginHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexSnappingBeginHandler.TYPE, handler); } @Override public HandlerRegistration addGeometryIndexSnappingEndHandler(GeometryIndexSnappingEndHandler handler) { return editingService.getEventBus().addHandler(GeometryIndexSnappingEndHandler.TYPE, handler); } @Override public void snappingBegin(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (!snapped.contains(index)) { temp.add(index); } } snapped.addAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexSnappingBeginEvent(editingService.getGeometry(), temp)); } @Override public void snappingEnd(List<GeometryIndex> indices) { List<GeometryIndex> temp = new ArrayList<GeometryIndex>(); for (GeometryIndex index : indices) { if (snapped.contains(index)) { temp.add(index); } } snapped.removeAll(temp); editingService.getEventBus().fireEvent(new GeometryIndexSnappingEndEvent(editingService.getGeometry(), temp)); } @Override public boolean isSnapped(GeometryIndex index) { return snapped.contains(index); } @Override public void snappingEndAll() { if (snapped.size() > 0) { List<GeometryIndex> clone = new ArrayList<GeometryIndex>(snapped); snapped.clear(); editingService.getEventBus().fireEvent( new GeometryIndexSnappingEndEvent(editingService.getGeometry(), clone)); } } }