/* * PenTool.java * * Created on April 21, 2005, 6:10 PM */ package ika.map.tools; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import ika.geo.*; import ika.gui.MapComponent; /** * A map tool to draw paths consisting of straight lines. * @author Bernhard Jenny, Institute of Cartography, ETH Zurich. */ abstract public class PolygonToolBase extends DoubleBufferedTool { /** * Location of the last mouse click. */ private Point2D.Double lastClickLoc; /** * Current position of the mouse cursor. */ private Point2D.Double currentMouseLoc; /** * The GeoPath that is currerntly drawn. */ protected GeoPath geoPath; /** * Time of the last mouse click in milliseconds. */ private long eventTimeMilliSec = 0; /** * Maximum time difference between two consecutive mouse clicks to form a double click. */ private static final long DOUBLE_CLICK_TIME_DIF = 500; /** * Create a new instance. * @param mapComponent The MapComponent for which this MapTool provides its services. */ public PolygonToolBase(MapComponent mapComponent) { super(mapComponent); } @Override public void deactivate() { finishPath(); releaseBackground(); } @Override public void mouseClicked(Point2D.Double point, MouseEvent evt) { if (geoPath == null) { geoPath = new GeoPath(); geoPath.setSelected(true); // deselect all currently selected objects in the destinationGeoSet if (destinationGeoSet != null) { destinationGeoSet.setSelected(false); } VectorSymbol symbol = new VectorSymbol(); symbol.setFilled(false); symbol.setStroked(true); symbol.setStrokeWidth(1); symbol.setStrokeColor(Color.green); symbol.setScaleInvariant(true); geoPath.setVectorSymbol(symbol); captureBackground(); } // add point to path if (evt.getClickCount() == 2) { // A double click generates two calls of mouseClicked. So we have // to remove the last added point. // Additionally make sure that the last click happened within a short // period of time. This way we are still safe, hould another virtual // machine generate only one call to mouseClicked after a double click. if (evt.getWhen() - eventTimeMilliSec < DOUBLE_CLICK_TIME_DIF) { geoPath.removeLastPoint(); } // close the path and pass it to the map geoPath.closePath(); finishPath(); } else { // add a straight line geoPath.moveOrLineTo(point.x, point.y); } mapComponent.repaint(); // remember where and when the last click happened. lastClickLoc = (Point2D.Double)point.clone(); eventTimeMilliSec = evt.getWhen(); } @Override public void mouseExited(Point2D.Double point, MouseEvent evt) { // don't draw a straight line from the last point to the current // mouse position if the mouse is not inside the map. this.currentMouseLoc = null; mapComponent.repaint(); } @Override public void mouseMoved(Point2D.Double point, MouseEvent evt) { // remember the current mouse position and repaint if their already is at // least one point. if (lastClickLoc != null) { this.currentMouseLoc = (Point2D.Double)point.clone(); mapComponent.repaint(); } } @Override public void draw(RenderParams rp) { if (geoPath == null) { return; } this.mapComponent.shiftGraphics2DByBorderWidth(rp.g2d); //this.mapComponent.setupGraphics2DForDrawingInWorldCoordinates(rp.g2d); FIXME final float scale = (float)this.mapComponent.getScaleFactor(); rp.g2d.setColor(Color.black); final double strokeWidth = 1. / mapComponent.getScaleFactor(); BasicStroke stroke = new BasicStroke((float)strokeWidth); rp.g2d.setStroke(stroke); // draw the GeoPath geoPath.drawNormalState(rp); // draw a line from last clicked point to current mouse position if (lastClickLoc != null && currentMouseLoc != null) { Line2D.Double line = new Line2D.Double(lastClickLoc, currentMouseLoc); rp.g2d.draw(line); } } /** * Utility method that is called when the user finishes drawing. * The captured background is released, and * variables reset, so that the next path can be drawn. */ protected void finishPath() { releaseBackground(); // init variables so that next drawing can start. geoPath = null; lastClickLoc = null; currentMouseLoc = null; } }