001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui.cursortool.editing;
034:
035: import java.awt.BasicStroke;
036: import java.awt.Cursor;
037: import java.awt.Shape;
038: import java.awt.event.MouseEvent;
039: import java.awt.geom.AffineTransform;
040: import java.awt.geom.NoninvertibleTransformException;
041: import java.util.ArrayList;
042: import java.util.Collection;
043: import java.util.Collections;
044: import java.util.Iterator;
045: import java.util.List;
046:
047: import javax.swing.Icon;
048:
049: import com.vividsolutions.jts.geom.Coordinate;
050: import com.vividsolutions.jts.geom.CoordinateFilter;
051: import com.vividsolutions.jts.geom.Envelope;
052: import com.vividsolutions.jts.geom.Geometry;
053: import com.vividsolutions.jts.geom.GeometryCollection;
054: import com.vividsolutions.jts.geom.GeometryFactory;
055: import com.vividsolutions.jump.geom.CoordUtil;
056: import com.vividsolutions.jump.workbench.model.Layer;
057: import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
058: import com.vividsolutions.jump.workbench.ui.EditTransaction;
059: import com.vividsolutions.jump.workbench.ui.cursortool.DragTool;
060: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
061:
062: public class MoveSelectedItemsTool extends DragTool {
063: private EnableCheckFactory checkFactory;
064: private Shape selectedFeaturesShape;
065: private GeometryFactory geometryFactory = new GeometryFactory();
066: private List verticesToSnap = null;
067:
068: public MoveSelectedItemsTool(EnableCheckFactory checkFactory) {
069: this .checkFactory = checkFactory;
070: setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
071: BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 3 }, 0));
072: allowSnapping();
073: }
074:
075: protected void gestureFinished() throws java.lang.Exception {
076: reportNothingToUndoYet();
077: final Coordinate displacement = CoordUtil.subtract(
078: getModelDestination(), getModelSource());
079: ArrayList transactions = new ArrayList();
080: for (Iterator i = getPanel().getSelectionManager()
081: .getLayersWithSelectedItems().iterator(); i.hasNext();) {
082: Layer layerWithSelectedItems = (Layer) i.next();
083: transactions.add(createTransaction(layerWithSelectedItems,
084: displacement));
085: }
086: EditTransaction.commit(transactions);
087: }
088:
089: private EditTransaction createTransaction(Layer layer,
090: final Coordinate displacement) {
091: EditTransaction transaction = EditTransaction
092: .createTransactionOnSelection(
093: new EditTransaction.SelectionEditor() {
094: public Geometry edit(
095: Geometry geometryWithSelectedItems,
096: Collection selectedItems) {
097: for (Iterator j = selectedItems
098: .iterator(); j.hasNext();) {
099: Geometry item = (Geometry) j.next();
100: move(item, displacement);
101: }
102:
103: return geometryWithSelectedItems;
104: }
105: }, getPanel(), getPanel().getContext(),
106: getName(), layer, isRollingBackInvalidEdits(),
107: false);
108: return transaction;
109: }
110:
111: private void move(Geometry geometry, final Coordinate displacement) {
112: geometry.apply(new CoordinateFilter() {
113: public void filter(Coordinate coordinate) {
114: coordinate.setCoordinate(CoordUtil.add(coordinate,
115: displacement));
116: }
117: });
118: }
119:
120: public Cursor getCursor() {
121: return Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
122: }
123:
124: public Icon getIcon() {
125: return IconLoader.icon("Move.gif");
126: }
127:
128: public void mousePressed(MouseEvent e) {
129: try {
130: if (!check(checkFactory
131: .createAtLeastNItemsMustBeSelectedCheck(1))) {
132: return;
133: }
134:
135: if (!check(checkFactory
136: .createSelectedItemsLayersMustBeEditableCheck())) {
137: return;
138: }
139:
140: verticesToSnap = null;
141: selectedFeaturesShape = createSelectedItemsShape();
142: super .mousePressed(e);
143: } catch (Throwable t) {
144: getPanel().getContext().handleThrowable(t);
145: }
146: }
147:
148: private Collection verticesToSnap() {
149: //Lazily initialized because not used if there are no snapping policies. [Jon Aquino]
150: Envelope viewportEnvelope = getPanel().getViewport()
151: .getEnvelopeInModelCoordinates();
152:
153: if (verticesToSnap == null) {
154: verticesToSnap = new ArrayList();
155: for (Iterator i = getPanel().getSelectionManager()
156: .getSelectedItems().iterator(); i.hasNext();) {
157: Geometry selectedItem = (Geometry) i.next();
158: Coordinate[] coordinates = selectedItem
159: .getCoordinates();
160:
161: for (int j = 0; j < coordinates.length; j++) {
162: if (viewportEnvelope.contains(coordinates[j])) {
163: verticesToSnap.add(coordinates[j]);
164: }
165: }
166: }
167:
168: if (verticesToSnap.size() > 100) {
169: Collections.shuffle(verticesToSnap);
170: verticesToSnap = verticesToSnap.subList(0, 99);
171: }
172: }
173:
174: return verticesToSnap;
175: }
176:
177: private Shape createSelectedItemsShape()
178: throws NoninvertibleTransformException {
179: List itemsToRender = new ArrayList(getPanel()
180: .getSelectionManager().getSelectedItems());
181: if (itemsToRender.size() > 100) {
182: Collections.shuffle(itemsToRender);
183: itemsToRender = itemsToRender.subList(0, 99);
184: }
185:
186: GeometryCollection gc = geometryFactory
187: .createGeometryCollection((Geometry[]) itemsToRender
188: .toArray(new Geometry[] {}));
189:
190: return getPanel().getJava2DConverter().toShape(gc);
191: }
192:
193: protected Shape getShape() throws Exception {
194: AffineTransform transform = new AffineTransform();
195: transform.translate(getViewDestination().getX()
196: - getViewSource().getX(), getViewDestination().getY()
197: - getViewSource().getY());
198:
199: return transform.createTransformedShape(selectedFeaturesShape);
200: }
201:
202: protected void setModelDestination(Coordinate modelDestination) {
203: for (Iterator i = verticesToSnap().iterator(); i.hasNext();) {
204: Coordinate vertex = (Coordinate) i.next();
205: Coordinate displacement = CoordUtil.subtract(vertex,
206: getModelSource());
207: Coordinate snapPoint = snap(CoordUtil.add(modelDestination,
208: displacement));
209:
210: if (getSnapManager().wasSnapCoordinateFound()) {
211: this.modelDestination = CoordUtil.subtract(snapPoint,
212: displacement);
213: return;
214: }
215: }
216: this.modelDestination = modelDestination;
217: }
218:
219: }
|