/* * 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 org.openjump.util.python.pythonexampleclasses; import java.awt.geom.GeneralPath; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.Shape; import java.util.List; import java.util.ArrayList; import java.util.EventObject; import java.util.EventListener; import javax.swing.Icon; import javax.swing.ImageIcon; import java.util.Iterator; import org.python.core.Py; import org.python.core.PyException; import org.python.core.PyString; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.operation.valid.IsValidOp; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.ui.EditTransaction; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.cursortool.editing.*; public class DrawCustomTool extends ConstrainedNClickTool { private FeatureDrawingUtil featureDrawingUtil; private int minClicks = 1; private int fireClicks = 2; private Icon icon = null; private String toolName = "Custom Tool"; private String geoType = "Point"; private FeedbackListener feedbackListener = null; private FinalDrawListener finalGeoListener = null; private ActivationListener activationListener = null; private DeActivationListener deActivationListener = null; public DrawCustomTool(FeatureDrawingUtil featureDrawingUtil) { super(); drawClosed = false; this.featureDrawingUtil = featureDrawingUtil; } public void activate(LayerViewPanel layerViewPanel) { super.activate(layerViewPanel); if (activationListener != null){ WorkbenchContext wc = this.getWorkbench().getContext(); CustomToolEvent toolEvent = new CustomToolEvent(this, null, wc); activationListener.handleActivation(toolEvent); } } public void deactivate() { cancelGesture(); super.deactivate(); if (deActivationListener != null){ WorkbenchContext wc = this.getWorkbench().getContext(); CustomToolEvent toolEvent = new CustomToolEvent(this, null, wc); deActivationListener.handleDeActivation(toolEvent); } } public void setFireClicks(int fireClicks) { this.fireClicks = fireClicks; } public void setMinClicks(int minClicks) { this.minClicks = minClicks; } public void setMaxClicks(int maxClicks) { this.n = maxClicks; //number of clicks at which to finish the drawing (stored in super) } public void setIcon(Icon icon) { this.icon = icon; } public void setToolName(String toolName) { this.toolName = toolName; } public void setGeometryType(String geoType) { boolean goodType = (geoType.equalsIgnoreCase("POINT") || geoType.equalsIgnoreCase("LINESTRING") || geoType.equalsIgnoreCase("POLYGON")); if (goodType) this.geoType = geoType; else throw new PyException(Py.ValueError, new PyString(geoType + ": invalid geometry type")); } public void setStrokeWidth(int width) { super.setStrokeWidth(width); } public interface FinalDrawListener extends EventListener { public void finalDraw(CustomToolEvent event); } public interface FeedbackListener extends EventListener { public void feedbackDraw(CustomToolEvent event); } public interface ActivationListener extends EventListener { public void handleActivation(CustomToolEvent event); } public interface DeActivationListener extends EventListener { public void handleDeActivation(CustomToolEvent event); } public void setFeedbackListener(FeedbackListener listener) { feedbackListener = listener; } public void setFinalGeoListener(FinalDrawListener listener) { finalGeoListener = listener; } public void setActivationListener(ActivationListener listener) { activationListener = listener; } public void setDeActivationListener(DeActivationListener listener) { deActivationListener = listener; } public String getName() { //Specify name explicitly, otherwise it will be "Draw Custom" return toolName; } public Icon getIcon() { if (icon == null) return new ImageIcon(getClass().getResource("DrawLine.gif")); else return icon; } protected void gestureFinished() throws Exception { reportNothingToUndoYet(); Geometry geo = getFinalGeometry(); if (geo == null) return; execute(featureDrawingUtil.createAddCommand(geo, isRollingBackInvalidEdits(), getPanel(), this)); } protected Shape getShape() throws NoninvertibleTransformException { List coords = new ArrayList(getCoordinates()); if (coords.size() >= fireClicks) { coords.add(tentativeCoordinate); coords = fireFeedbackEvent(coords); Point2D firstPoint = getPanel().getViewport().toViewPoint((Coordinate)coords.get(0)); GeneralPath path = new GeneralPath(); path.moveTo((float) firstPoint.getX(), (float) firstPoint.getY()); for (int i = 1; i < coords.size(); i++) { Coordinate nextCoordinate = (Coordinate) coords.get(i); Point2D nextPoint = getPanel().getViewport().toViewPoint(nextCoordinate); path.lineTo((int) nextPoint.getX(), (int) nextPoint.getY()); } return path; } else { return super.getShape(); } } protected Geometry getFinalGeometry() throws NoninvertibleTransformException { boolean goodGeo = true; Geometry geo = null; if (getCoordinates().size() < minClicks) { getPanel().getContext().warnUser("Must have at least " + minClicks + " points"); return null; } List coords = fireFinalGeoEvent(getCoordinates()); IsValidOp isValidOp = null; if (geoType.equalsIgnoreCase("POINT")) { if (coords.size() == 1) { geo = new GeometryFactory().createPoint((Coordinate)coords.get(0)); isValidOp = new IsValidOp((Point) geo); } else { geo = new GeometryFactory().createMultiPoint(toArray(coords)); isValidOp = new IsValidOp((MultiPoint) geo); } } else if (geoType.equalsIgnoreCase("LINESTRING")) { geo = new GeometryFactory().createLineString(toArray(coords)); isValidOp = new IsValidOp((LineString) geo); } else if (geoType.equalsIgnoreCase("POLYGON")) { geo = new GeometryFactory().createPolygon( new GeometryFactory().createLinearRing(toArray(coords)), null); isValidOp = new IsValidOp((Polygon) geo); } else { getPanel().getContext().warnUser(geoType + " not a valid type."); return null; } if (!isValidOp.isValid()) { getPanel().getContext().warnUser(isValidOp.getValidationError().getMessage()); if (getWorkbench().getBlackboard().get(EditTransaction.ROLLING_BACK_INVALID_EDITS_KEY, false)) { return null; } } return geo; } protected List fireFeedbackEvent(List coordsIn) { if (feedbackListener == null) { return fireFinalGeoEvent(coordsIn); } else { ArrayList coords = new ArrayList(); for (Iterator i = coordsIn.iterator(); i.hasNext();) coords.add(((Coordinate) i.next()).clone()); WorkbenchContext wc = this.getWorkbench().getContext(); CustomToolEvent toolEvent = new CustomToolEvent(this, coords, wc); feedbackListener.feedbackDraw(toolEvent); coords = (ArrayList)toolEvent.getCoords(); //statusMessage = toolEvent.getStatusMessage(); return coords; } } protected List fireFinalGeoEvent(List coordsIn) { if (finalGeoListener == null) { return coordsIn; } else { ArrayList coords = new ArrayList(); for (Iterator i = coordsIn.iterator(); i.hasNext();) coords.add(((Coordinate) i.next()).clone()); WorkbenchContext wc = this.getWorkbench().getContext(); CustomToolEvent toolEvent = new CustomToolEvent(this, coords, wc); finalGeoListener.finalDraw(toolEvent); coords = (ArrayList)toolEvent.getCoords(); //statusMessage = toolEvent.getStatusMessage(); return coords; } } public class CustomToolEvent extends EventObject { private List localCoords; private String statusMessage = ""; private WorkbenchContext wc; CustomToolEvent(Object source, List coords, WorkbenchContext wc) { super(source); localCoords = coords; this.wc = wc; } public WorkbenchContext getWc() { return wc; } public List getCoords() { return localCoords; } public void setCoords(List coords) { localCoords = coords; } public void setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; } public String getStatusMessage() { return statusMessage; } } }