/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.workbench.ui.cursortool.editing; import java.awt.Color; import java.awt.Cursor; import java.awt.Point; import java.awt.Shape; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.swing.Icon; import javax.swing.JComponent; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateFilter; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.plugin.EnableCheck; import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory; import com.vividsolutions.jump.workbench.ui.EditTransaction; import com.vividsolutions.jump.workbench.ui.cursortool.DragTool; import com.vividsolutions.jump.workbench.ui.images.IconLoader; public class MoveVertexTool extends DragTool { public final static int TOLERANCE = 5; private EnableCheckFactory checkFactory; public MoveVertexTool(EnableCheckFactory checkFactory) { this.checkFactory = checkFactory; setColor(new Color(194, 179, 205)); setStrokeWidth(5); allowSnapping(); } public Cursor getCursor() { return createCursor(IconLoader.icon("MoveVertexCursor3.gif").getImage()); } public Icon getIcon() { return IconLoader.icon("MoveVertex.gif"); } protected void gestureFinished() throws Exception { reportNothingToUndoYet(); //#execute(UndoableCommand) will be called. [Jon Aquino] moveVertices(getModelSource(), getModelDestination()); } public void mousePressed(final MouseEvent e) { try { if (!check(checkFactory.createAtLeastNLayersMustBeEditableCheck(1))) { return; } if (!check(checkFactory.createAtLeastNItemsMustBeSelectedCheck(1))) { return; } if (!check(new EnableCheck() { public String check(JComponent component) { try { return !nearSelectionHandle(e.getPoint()) ? I18N.get("ui.cursortool.MoveVertexTool.no-editable-selection-handles-here") : null; } catch (Exception e) { return e.toString(); } } })) { return; } super.mousePressed(e); } catch (Throwable t) { getPanel().getContext().handleThrowable(t); } } private boolean nearSelectionHandle(Point2D p) throws NoninvertibleTransformException { final Envelope buffer = vertexBuffer(getPanel().getViewport().toModelCoordinate(p)); final boolean[] result = new boolean[] { false }; for (Iterator i = getPanel().getSelectionManager().getLayersWithSelectedItems().iterator(); i.hasNext(); ) { Layer layer = (Layer) i.next(); if (!layer.isEditable()) { continue; } for (Iterator j = getPanel().getSelectionManager().getSelectedItems(layer).iterator(); j.hasNext(); ) { Geometry item = (Geometry) j.next(); item.apply(new CoordinateFilter() { public void filter(Coordinate coord) { if (buffer.contains(coord)) { result[0] = true; } } }); } } return result[0]; } private Envelope vertexBuffer(Coordinate c) throws NoninvertibleTransformException { double tolerance = TOLERANCE / getPanel().getViewport().getScale(); return vertexBuffer(c, tolerance); } public void moveVertices(Coordinate initialLocation, Coordinate finalLocation) throws Exception { final Envelope oldVertexBuffer = vertexBuffer(initialLocation); final Coordinate newVertex = finalLocation; ArrayList transactions = new ArrayList(); for (Iterator i = getPanel().getSelectionManager().getLayersWithSelectedItems().iterator(); i.hasNext(); ) { Layer layerWithSelectedItems = (Layer) i.next(); if (!layerWithSelectedItems.isEditable()) { continue; } transactions.add(createTransaction(layerWithSelectedItems, oldVertexBuffer, newVertex)); } EditTransaction.commit(transactions); } private EditTransaction createTransaction( Layer layer, final Envelope oldVertexBuffer, final Coordinate newVertex) { return EditTransaction.createTransactionOnSelection(new EditTransaction.SelectionEditor() { public Geometry edit(Geometry geometryWithSelectedItems, Collection selectedItems) { for (Iterator j = selectedItems.iterator(); j.hasNext();) { Geometry item = (Geometry) j.next(); edit(item); } return geometryWithSelectedItems; } private void edit(Geometry selectedItem) { selectedItem.apply(new CoordinateFilter() { public void filter(Coordinate coordinate) { if (oldVertexBuffer.contains(coordinate)) { coordinate.x = newVertex.x; coordinate.y = newVertex.y; } } }); } }, getPanel(), getPanel().getContext(), getName(), layer, isRollingBackInvalidEdits(), false); } protected Shape getShape(Point2D source, Point2D destination) throws Exception { double radius = 20; return new Ellipse2D.Double( destination.getX() - (radius / 2), destination.getY() - (radius / 2), radius, radius); } private Envelope vertexBuffer(Coordinate vertex, double tolerance) { return new Envelope( vertex.x - tolerance, vertex.x + tolerance, vertex.y - tolerance, vertex.y + tolerance); } }