[Schmitzm-commits] r511 - branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Nov 5 18:41:34 CET 2009
Author: alfonx
Date: 2009-11-05 18:41:33 +0100 (Thu, 05 Nov 2009)
New Revision: 511
Added:
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/GeomFilterGenerator.java
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/SelectXMapPaneMouseListener.java
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/ZoomXMapPaneMouseListener.java
Modified:
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java
Log:
compile error free ... XMapPane migration complete...
Added: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/GeomFilterGenerator.java
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/GeomFilterGenerator.java 2009-11-05 17:39:37 UTC (rev 510)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/GeomFilterGenerator.java 2009-11-05 17:41:33 UTC (rev 511)
@@ -0,0 +1,249 @@
+package gtmig.org.geotools.swing;
+
+import java.awt.geom.Point2D;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.geotools.data.FeatureSource;
+import org.geotools.filter.AbstractFilter;
+import org.geotools.filter.GeometryFilterImpl;
+import org.geotools.filter.spatial.DWithinImpl;
+import org.geotools.referencing.CRS;
+import org.geotools.resources.CRSUtilities;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.feature.type.GeometryDescriptor;
+import org.opengis.filter.expression.Expression;
+import org.opengis.filter.spatial.BinarySpatialOperator;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.geotools.FilterUtil;
+import schmitzm.geotools.JTSUtil;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.Geometry;
+
+/**
+ * The {@link GeomFilterGenerator} prepares a {@link BinarySpatialOperator}
+ * filter for multiple use. Only the "right" argument is prepared. The
+ * "left" argument (the geometry attribute of the {@link FeatureSource} to
+ * filter) is first set on calling {@link #adaptFilter(FeatureSource)} for a
+ * specific {@link FeatureSource}. This method also takes care to recreate
+ * the filter (or its "right" argument) if the given {@link FeatureSource}
+ * has another {@link CoordinateReferenceSystem} than the base constraint.<br>
+ * The type of filter (e.g. distance or bounding box) is specified by the
+ * subclass implemenation of
+ * {@link #prepareFilter(CoordinateReferenceSystem)} .
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+ public abstract class GeomFilterGenerator {
+ /**
+ * Holds the {@link CoordinateReferenceSystem} the filter constraint
+ * bases on.
+ */
+ protected CoordinateReferenceSystem baseCRS = null;
+ /**
+ * Caches the base filter constraint for several
+ * {@link CoordinateReferenceSystem CoordinateReferenceSystems}.
+ */
+ protected Map<CoordinateReferenceSystem, GeometryFilterImpl> filterCache = new HashMap<CoordinateReferenceSystem, GeometryFilterImpl>();
+
+ /**
+ * Creates a new filter generator
+ *
+ * @param crs
+ * {@link CoordinateReferenceSystem} the base constraint
+ * ("right" filter argument is relative to)
+ */
+ public GeomFilterGenerator(CoordinateReferenceSystem crs) {
+ this.baseCRS = crs;
+ }
+
+ /**
+ * Creates a filter containing the base constraint ("right" argument)
+ * transformed to the given {@link CoordinateReferenceSystem}.
+ *
+ * @param crs
+ * the {@link CoordinateReferenceSystem} the base constraint
+ * is transformed to
+ */
+ protected abstract GeometryFilterImpl prepareFilter(
+ CoordinateReferenceSystem crs);
+
+ /**
+ * Completes the filter with its "left" argument for a concrete
+ * {@link FeatureSource}. If the {@link FeatureSource FeatureSource's}
+ * CRS differs from the CRS the base constraint is specified in, first a
+ * new filter is created by calling
+ * {@link #prepareFilter(CoordinateReferenceSystem)}.
+ *
+ * @param fs
+ * {@link FeatureSource} the filter is adaped to
+ * @return
+ */
+ public GeometryFilterImpl adaptFilter(
+ FeatureSource<SimpleFeatureType, SimpleFeature> fs) {
+ GeometryDescriptor geomDescr = fs.getSchema()
+ .getGeometryDescriptor();
+ CoordinateReferenceSystem fsCRS = geomDescr
+ .getCoordinateReferenceSystem();
+ GeometryFilterImpl filter = filterCache.get(fsCRS);
+ if (filter == null) {
+ filter = prepareFilter(fsCRS);
+ filterCache.put(fsCRS, filter);
+ }
+ Expression geometry = FilterUtil.FILTER_FAC2.property(geomDescr.getLocalName());
+ filter.setExpression1(geometry);
+ return filter;
+ }
+
+ /**
+ * {@link GeomFilterGenerator} for a bounding box constraint.
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+ public static class BoundingBoxFilterGenerator extends GeomFilterGenerator {
+ /**
+ * Holds the base constraint (bounding box {@link Envelope}) relative to
+ * the {@linkplain GeomFilterGenerator#baseCRS base CRS}.
+ */
+ protected Envelope baseEnv = null;
+
+ /**
+ * Creates a new filter generator.
+ *
+ * @param baseEnv
+ * defines the bounding box
+ * @param baseCrs
+ * defines the CRS of the bounding box
+ */
+ public BoundingBoxFilterGenerator(Envelope baseEnv,
+ CoordinateReferenceSystem baseCrs) {
+ super(baseCrs);
+ this.baseEnv = baseEnv;
+ }
+
+ /**
+ * Prepares a filter with the bounding box transformed to the given
+ * {@link CoordinateReferenceSystem} as the "right" argument.
+ *
+ * @param crs
+ * the {@link CoordinateReferenceSystem} the bounding box is
+ * transformed to
+ */
+ protected GeometryFilterImpl prepareFilter(CoordinateReferenceSystem crs) {
+ Envelope bbEnv = baseEnv;
+ if (!CRS.equalsIgnoreMetadata(baseCRS,crs))
+ bbEnv = JTSUtil.transformEnvelope(baseEnv, baseCRS, crs);
+ // Filter fuer Envelope zusammenstellen
+ Expression bbox = FilterUtil.FILTER_FAC.createBBoxExpression(bbEnv);
+ GeometryFilterImpl bboxFilter = (GeometryFilterImpl) FilterUtil.FILTER_FAC
+ .createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
+ // GeometryFilterImpl bboxFilter =
+ // (GeometryFilterImpl)ff.createGeometryFilter(AbstractFilter.
+ // GEOMETRY_WITHIN);
+ bboxFilter.setExpression2(bbox);
+ return bboxFilter;
+ }
+ }
+
+ /**
+ * {@link GeomFilterGenerator} for a "near distance" constraint.
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+ public static class NearPointFilterGenerator extends GeomFilterGenerator {
+ /**
+ * Holds the base constraint (coordinate) relative to the
+ * {@linkplain GeomFilterGenerator#baseCRS base CRS}.
+ */
+ protected Coordinate basePoint = null;
+ /**
+ * Holds the distance "around" the base point relative to the
+ * {@linkplain GeomFilterGenerator#baseCRS base CRS}.
+ */
+ protected double baseDist = 0.0;
+ /**
+ * Holds a point which is in distance {@link #baseDist} to the
+ * {@link #basePoint}.
+ */
+ protected Coordinate basePoint2 = null;
+
+ /**
+ * Creates a new filter generator.
+ *
+ * @param basePoint
+ * defNearPointFilterGeneratorines the point for the "near point" constraint
+ * @param dist
+ * defines the distance around the base point
+ * @param crs
+ * defines the CRS of base point
+ */
+ public NearPointFilterGenerator(Coordinate basePoint, double dist,
+ CoordinateReferenceSystem crs) {
+ super(crs);
+ this.basePoint = basePoint;
+ this.baseDist = dist;
+ // Create a point which is in distance "dist" to the base point
+ this.basePoint2 = new Coordinate(basePoint.x + dist, basePoint.y);
+ }
+
+ /**
+ * Creates a new filter generator.
+ *
+ * @param basePoint
+ * defines the point for the "near point" constraint
+ * @param dist
+ * defines the distance around the base point
+ * @param crs
+ * defines the CRS of base point
+ */
+ public NearPointFilterGenerator(Point2D basePoint, double dist,
+ CoordinateReferenceSystem crs) {
+ this(new Coordinate(basePoint.getX(), basePoint.getY()), dist, crs);
+ }
+
+ /**
+ * Prepares a filter with the base point and distance transformed to the
+ * given {@link CoordinateReferenceSystem} as the "right" argument.
+ *
+ * @param crs
+ * the {@link CoordinateReferenceSystem} the point and
+ * distance is transformed to
+ */
+ protected GeometryFilterImpl prepareFilter(CoordinateReferenceSystem crs) {
+ Coordinate nearPoint = basePoint;
+ double nearDist = baseDist;
+ if (!baseCRS.equals(crs)) {
+ nearPoint = JTSUtil
+ .transformCoordinate(basePoint, baseCRS, crs);
+ // Transform the distance (maybe "dirty")
+ // --> transform the point2 and calculate the
+ // distance to the tranformed base point
+ Coordinate nearPoint2 = JTSUtil.transformCoordinate(basePoint2,
+ baseCRS, crs);
+
+ if (nearPoint == null || nearPoint2 == null)
+ throw new RuntimeException("Unable to transform CRS from "
+ + baseCRS + " to " + crs);
+
+ nearDist = Math.abs(nearPoint.x - nearPoint2.x);
+ }
+ // Filter fuer Point zusammenstellen
+ final Geometry geometry = FilterUtil.GEOMETRY_FAC
+ .createPoint(nearPoint);
+
+ final DWithinImpl dwithinFilter = new DWithinImpl(
+ FilterUtil.FILTER_FAC2, null, null);
+ dwithinFilter.setDistance(nearDist);
+ dwithinFilter.setExpression2(FilterUtil.FILTER_FAC2
+ .literal(geometry));
+
+ return dwithinFilter;
+ }
+
+ }
+
+}
\ No newline at end of file
Added: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/SelectXMapPaneMouseListener.java
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/SelectXMapPaneMouseListener.java 2009-11-05 17:39:37 UTC (rev 510)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/SelectXMapPaneMouseListener.java 2009-11-05 17:41:33 UTC (rev 511)
@@ -0,0 +1,268 @@
+package gtmig.org.geotools.swing;
+
+import gtmig.org.geotools.swing.GeomFilterGenerator.BoundingBoxFilterGenerator;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.geom.Point2D;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+import org.geotools.data.memory.MemoryFeatureCollection;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.map.MapLayer;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+
+import schmitzm.geotools.gui.SelectableXMapPane;
+import schmitzm.geotools.map.event.FeatureSelectedEvent;
+import sun.misc.PerformanceLogger;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryFactory;
+
+public class SelectXMapPaneMouseListener extends MouseAdapter {
+
+ private final SelectableXMapPane xMapPane;
+ private boolean enabled;
+
+ public boolean isEnabled() {
+ if (!xMapPane.isWellDefined())
+ return false;
+ if ((xMapPane.getState() == XMapPane.ZOOM_IN
+ || xMapPane.getState() == xMapPane.ZOOM_OUT || xMapPane
+ .getState() == xMapPane.PAN))
+ return false;
+ if (xMapPane.getState() == XMapPane.NONE)
+ ;
+ return enabled;
+ }
+
+ /**
+ * Reagiert auf Linksklick mit der ueber {@link #setState(int)}eingestellten
+ * Aktion und auf Rechtsklick mit Zoom-Out (sofern {@link #ZOOM_IN}-State
+ * fuer Linksklick eingestellt). Alle anderen Klicks werden ignoriert.
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ * (University of Bonn/Germany)
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (!isEnabled())
+ return;
+
+ xMapPane.setCursor(XMapPane.WAIT_CURSOR);
+ //
+ // int clickX = e.getX();
+ // int clickY = e.getY();
+ // selectionPerformed(clickX, clickY, clickX, clickY);}
+ //
+ int state = xMapPane.getState();
+
+ /**
+ * BEGIN StefanChange Dieser Block findet sichtbare Features im Umkreis
+ * des Mausklicks und kümmert sich selbst um das verschicken der Events.
+ * Dabei wird z.Zt. immer eine FeaterCollection mit nur einem
+ * SimpleFeature verschickt. Und zwar jenes SimpleFeature, welches am
+ * nächsten liegt.
+ */
+
+ // Fenster-Koordinate in Geo-Koordinate umwandelt
+ Point2D geoCoord = xMapPane.getScreenToWorld().transform(e.getPoint(),
+ null);
+
+ com.vividsolutions.jts.geom.Point mousePoint = new GeometryFactory()
+ .createPoint(new Coordinate(geoCoord.getX(), geoCoord.getY()));
+
+ // Rechnet 10 Pixel in die Einheit der Karte um.
+ final Point pAtDistance = new Point((int) e.getPoint().getX() + 10,
+ (int) e.getPoint().getY());
+ final Point2D geoCoordAtDistance = xMapPane.getScreenToWorld()
+ .transform(pAtDistance, null);
+ final Double dist = Math.abs(geoCoordAtDistance.getX()
+ - geoCoord.getX()) / 2;
+
+// final Envelope envelope = new Envelope(geoCoord.getX(),
+// geoCoord.getY(), geoCoord.getX(), geoCoord.getY());
+
+ //
+ // This is a tweak. The NearPointFilterGenerator doesn't work
+ // any more in GT2.6... So we use a small BBOX.
+ // Well, it's not the
+ // NearPointFilterGenerator, but GeoTools that fails. I already
+ // invested 3h in this... I guess the bug is in
+ // ExtractBoundsFilterVisitor.visit(ProperyName) retuning null.
+ // It should return the BBOX of value the named property.
+
+ // Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,
+ // SimpleFeature>> result = findVisibleFeatures(
+ // new NearPointFilterGenerator(geoCoord, dist,
+ // getContext().getCoordinateReferenceSystem()),
+ // state, envelope);
+
+// envelope.expandBy(dist);
+//
+ Envelope envelope = new Envelope(geoCoord.getX() - dist, geoCoord
+ .getY()
+ - dist, geoCoord.getX() + dist, geoCoord.getY() + dist);
+
+ Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = xMapPane
+ .findVisibleFeatures(new BoundingBoxFilterGenerator( envelope,
+ xMapPane.getContext().getCoordinateReferenceSystem()),
+ state, envelope);
+
+ // Ein Event auslösen für das jeweils nächste Feature pro Layer
+ for (Enumeration<MapLayer> element = result.keys(); element
+ .hasMoreElements();) {
+
+ MapLayer layer = element.nextElement();
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
+ .get(layer);
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fcOne;
+
+ if (fc != null && !fc.isEmpty()) {
+
+ if (fc.size() > 1) {
+ // Hier werden alle Features weggeschmissen, bis auf
+ // das raeumlich naechste.
+
+ SimpleFeature nearestFeature = null;
+ Double nearestDist = 0.0;
+
+ Iterator<SimpleFeature> fcIt = fc.iterator();
+ try {
+
+ while (fcIt.hasNext()) {
+ SimpleFeature f = fcIt.next();
+ Object obj = f.getAttribute(0);
+
+ if (obj instanceof Geometry) {
+ // Bei Punkten ja noch ganz einfach:
+ Geometry featureGeometry = (Geometry) obj;
+ double distance = featureGeometry
+ .distance(mousePoint);
+
+ if ((nearestFeature == null)
+ || (distance < nearestDist)) {
+ nearestFeature = f;
+ nearestDist = distance;
+ }
+ } else {
+ LOGGER
+ .info("!obj instanceof Geometry obj = "
+ + obj.getClass()
+ .getSimpleName());
+ }
+
+ }
+
+ } finally {
+ fc.close(fcIt);
+ }
+
+ fcOne = new MemoryFeatureCollection(fc.getSchema());
+ fc.clear();
+ fcOne.add(nearestFeature);
+ } else {
+ fcOne = fc;
+ }
+ xMapPane.fireMapPaneEvent(new FeatureSelectedEvent(xMapPane,
+ layer, envelope, fcOne));
+ }
+ }
+
+ xMapPane.updateCursorAndRepaintTimer();
+
+ }
+
+ /**
+ * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
+ *
+ * @param wheelEvt
+ * Mausrad-Event
+ */
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent wheelEvt) {
+ if (!isEnabled())
+ return;
+
+ final int units = wheelEvt.getUnitsToScroll();
+ if (units > 0)
+ xMapPane.zoomTo(wheelEvt.getPoint(), 1. + .11 * units);
+ else
+ xMapPane.zoomTo(wheelEvt.getPoint(), 2. / -units);
+ }
+
+ @Override
+ public void mouseDragged(final MouseEvent event) {
+ if (!isEnabled())
+ return;
+
+ xMapPane.mouseDragged(startPos, lastPos, event);
+
+ lastPos = event.getPoint();
+ }
+
+ /**
+ * Stores beginning of a drag event in window coordinates
+ */
+ protected Point startPos;
+
+ /**
+ * Stores last position of a drag event in window coordinates
+ */
+ protected Point lastPos;
+
+ public void mouseReleased(final MouseEvent event) {
+ if (!isEnabled())
+ return;
+
+ if (xMapPane.getState() == XMapPane.PAN
+ || event.getButton() == MouseEvent.BUTTON3) {
+ xMapPane.performPan();
+ } else if (xMapPane.getState() == XMapPane.SELECT_ALL
+ || xMapPane.getState() == XMapPane.SELECT_TOP) {
+ xMapPane.drawRectangle(xMapPane.getGraphics(), startPos, event
+ .getPoint());
+
+ Point mp = event.getPoint();
+
+ // keine wirkliche Selektion, sondern nur ein Klick
+ if (startPos.x == mp.x || startPos.y == mp.y) {
+ mouseClicked(event);
+ return;
+ }
+
+ // SELECTION!
+ xMapPane.performSelectionEvent(startPos.x, startPos.y, mp.x, mp.y);
+ }
+
+ }
+
+ public void mousePressed(final MouseEvent e) {
+ if (!isEnabled())
+ return;
+ startPos = new Point(e.getPoint());
+ lastPos = new Point(e.getPoint());
+ }
+
+ public SelectXMapPaneMouseListener(SelectableXMapPane xMapPane) {
+ this.xMapPane = xMapPane;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ private static Logger LOGGER = Logger
+ .getLogger(SelectXMapPaneMouseListener.class);
+
+}
Modified: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java 2009-11-05 17:39:37 UTC (rev 510)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java 2009-11-05 17:41:33 UTC (rev 511)
@@ -22,7 +22,6 @@
import java.awt.AlphaComposite;
import java.awt.Color;
-import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
@@ -69,6 +68,7 @@
import org.geotools.renderer.label.LabelCacheImpl;
import org.geotools.renderer.lite.LabelCache;
import org.geotools.swing.JMapPane;
+import org.geotools.swing.RenderingExecutor;
import org.geotools.swing.event.MapMouseEvent;
import org.geotools.swing.event.MapPaneEvent;
import org.geotools.swing.event.MapPaneListener;
@@ -85,7 +85,6 @@
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.geotools.map.event.MapLayerAdapter;
import schmitzm.swing.SwingUtil;
-import skrueger.geotools.RenderingExecutor;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
@@ -1089,7 +1088,7 @@
public static final int NONE = -123;
- private RenderingExecutor localExecuter;
+ private skrueger.geotools.RenderingExecutor localExecuter;
private BufferedImage finalImage;
@@ -1464,7 +1463,7 @@
*/
if (getBgContext() != null) {
- bgExecuter = new RenderingExecutor(this);
+ bgExecuter = new skrueger.geotools.RenderingExecutor(this);
LOGGER.debug("starting bg renderer:");
// /* System.out.println("rendering"); */
final GTRenderer createGTRenderer = GTUtil.createGTRenderer(
@@ -1475,7 +1474,7 @@
}
if (getContext() != null) {
- localExecuter = new RenderingExecutor(this);
+ localExecuter = new skrueger.geotools.RenderingExecutor(this);
LOGGER.debug("starting local renderer:");
final GTRenderer createGTRenderer = GTUtil.createGTRenderer(
localContext, getRendererHints());
Added: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/ZoomXMapPaneMouseListener.java
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/ZoomXMapPaneMouseListener.java 2009-11-05 17:39:37 UTC (rev 510)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/ZoomXMapPaneMouseListener.java 2009-11-05 17:41:33 UTC (rev 511)
@@ -0,0 +1,240 @@
+package gtmig.org.geotools.swing;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+
+import org.apache.log4j.Logger;
+
+import schmitzm.swing.SwingUtil;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Envelope;
+
+public class ZoomXMapPaneMouseListener extends MouseAdapter {
+
+ private static Logger LOGGER = Logger
+ .getLogger(ZoomXMapPaneMouseListener.class);
+
+
+ protected final XMapPane xMapPane;
+
+ protected boolean enabled = true;
+
+ public ZoomXMapPaneMouseListener(XMapPane xMapPane) {
+ if (xMapPane == null) throw new IllegalArgumentException("xMapPane may not be null");
+ this.xMapPane = xMapPane;
+ }
+
+ /**
+ * Stores beginning of a drag event in window coordinates
+ */
+ protected Point startPos;
+
+ /**
+ * Stores last position of a drag event in window coordinates
+ */
+ protected Point lastPos;
+
+ /**
+ * Draws a rectangle in XOR mode from the origin at {@link #startPos} to the
+ * given point. All in screen coordinates.
+ */
+ protected void drawRectangle(final Graphics graphics, Point e) {
+ // undraw last box/draw new box
+ final int left = Math.min(startPos.x, e.x);
+ final int right = Math.max(startPos.x, e.x);
+ final int top = Math.max(startPos.y, e.y);
+ final int bottom = Math.min(startPos.y, e.y);
+ final int width = right - left;
+ final int height = top - bottom;
+
+ if (width == 0 && height == 0)
+ return;
+
+ graphics.setXORMode(Color.WHITE);
+ graphics.drawRect(left, bottom, width, height);
+ }
+
+ public void mousePressed(final MouseEvent e) {
+ if (!isEnabled())
+ return;
+ startPos = new Point(e.getPoint());
+ lastPos = new Point(e.getPoint());
+ }
+
+ public void mouseReleased(final MouseEvent e) {
+ if (!isEnabled())
+ return;
+
+ final Rectangle bounds = xMapPane.getBounds();
+
+ Envelope mapArea = xMapPane.getMapArea();
+
+ // Replace with transform and translate
+ final double mapWidth = mapArea.getWidth();
+ final double mapHeight = mapArea.getHeight();
+
+ final double startX = ((startPos.x * mapWidth) / (double) bounds.width)
+ + mapArea.getMinX();
+ final double startY = (((bounds.getHeight() - startPos.y) * mapHeight) / (double) bounds.height)
+ + mapArea.getMinY();
+ final double endX = ((e.getPoint().x * mapWidth) / (double) bounds.width)
+ + mapArea.getMinX();
+ final double endY = (((bounds.getHeight() - e.getPoint().y) * mapHeight) / (double) bounds.height)
+ + mapArea.getMinY();
+
+ if ((xMapPane.getState() == XMapPane.PAN)
+ || (e.getButton() == MouseEvent.BUTTON3)) {
+ xMapPane.performPan();
+
+ } else if (xMapPane.getState() == XMapPane.ZOOM_IN) {
+
+ drawRectangle(xMapPane.getGraphics(), e.getPoint());
+
+ // Don't zoom too small areas
+ if ((Math.abs(startPos.x - e.getPoint().x) * Math.abs(e.getPoint().y - startPos.y)) < 160)
+ return;
+
+ final double left = Math.min(startX, endX);
+ final double right = Math.max(startX, endX);
+ final double bottom = Math.min(startY, endY);
+ final double top = Math.max(startY, endY);
+ final Coordinate ll = new Coordinate(left, bottom);
+ final Coordinate ur = new Coordinate(right, top);
+
+ xMapPane.setMapArea(new Envelope(ll, ur));
+
+ } else if (xMapPane.getState() == XMapPane.ZOOM_OUT) {
+
+ // Remove the rectangle
+ drawRectangle(xMapPane.getGraphics(), e.getPoint());
+
+ // make the dragged rectangle in screen coords the new map size?
+ final double left = Math.min(startX, endX);
+ final double right = Math.max(startX, endX);
+ final double bottom = Math.min(startY, endY);
+ final double top = Math.max(startY, endY);
+ final double nWidth = (mapWidth * mapWidth) / (right - left);
+ final double nHeight = (mapHeight * mapHeight) / (top - bottom);
+ final double deltaX1 = left - mapArea.getMinX();
+ final double nDeltaX1 = (deltaX1 * nWidth) / mapWidth;
+ final double deltaY1 = bottom - mapArea.getMinY();
+ final double nDeltaY1 = (deltaY1 * nHeight) / mapHeight;
+ final Coordinate ll = new Coordinate(mapArea.getMinX() - nDeltaX1,
+ mapArea.getMinY() - nDeltaY1);
+ final double deltaX2 = mapArea.getMaxX() - right;
+ final double nDeltaX2 = (deltaX2 * nWidth) / mapWidth;
+ final double deltaY2 = mapArea.getMaxY() - top;
+ final double nDeltaY2 = (deltaY2 * nHeight) / mapHeight;
+ final Coordinate ur = new Coordinate(mapArea.getMaxX() + nDeltaX2,
+ mapArea.getMaxY() + nDeltaY2);
+
+ xMapPane.setMapArea(new Envelope(ll, ur));
+ }
+
+
+ }
+
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ /**
+ * Returns <code>true</code> if the xMapPane is well defined and the
+ * listener is enabled.
+ */
+ public boolean isEnabled() {
+ return enabled && xMapPane.isWellDefined();
+ }
+
+ /**
+ * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
+ *
+ * @param wheelEvt
+ * Mausrad-Event
+ */
+ public void mouseWheelMoved(MouseWheelEvent wheelEvt) {
+ if (!isEnabled()) return;
+
+ final int units = wheelEvt.getUnitsToScroll();
+ if (units > 0)
+ xMapPane.zoomTo(wheelEvt.getPoint(), 1. + .11 * units);
+ else
+ xMapPane.zoomTo(wheelEvt.getPoint(), 2. / -units);
+ }
+
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+
+ if (!isEnabled())
+ return;
+
+ int state = xMapPane.getState();
+
+ // Nothing to do for panning
+ if (state == XMapPane.PAN)
+ return;
+
+ // double zoomFactor = 1.;
+ //
+ // final Envelope mapArea = xMapPane.getMapArea();
+ // if (mapArea == null)
+ // return;
+ //
+ // final Rectangle bounds = xMapPane.getVisibleRect();
+ //
+ // final double x = (double) (e.getX());
+ // final double y = (double) (e.getY());
+ // final double width = mapArea.getWidth();
+ // final double height = mapArea.getHeight();
+ // final double width2 = width / 2.0;
+ // final double height2 = height / 2.0;
+ // final double mapX = ((x * width) / (double) bounds.width)
+ // + mapArea.getMinX();
+ // final double mapY = (((bounds.getHeight() - y) * height) / (double)
+ // bounds.height)
+ // + mapArea.getMinY();
+ // double zlevel = 1.0;
+ //
+ if (state == XMapPane.ZOOM_IN && e.getButton() == MouseEvent.BUTTON1) {
+ xMapPane.zoomTo(e.getPoint(), 1 / 2.);
+ } else if (state == XMapPane.ZOOM_IN
+ && e.getButton() == MouseEvent.BUTTON3
+ || state == XMapPane.ZOOM_OUT) {
+ xMapPane.zoomTo(e.getPoint(), 2.);
+ }
+ //
+ // final Coordinate ll = new Coordinate(mapX - (width2 / zlevel), mapY
+ // - (height2 / zlevel));
+ // final Coordinate ur = new Coordinate(mapX + (width2 / zlevel), mapY
+ // + (height2 / zlevel));
+ // final Envelope newMapArea = new Envelope(ll, ur);
+ //
+ // xMapPane.setMapArea(newMapArea);
+
+ // xMapPane.repaint();
+
+ }
+
+ /**
+ * Constantly fired while the mouse is dragging
+ */
+ public void mouseDragged(final MouseEvent event) {
+ if (!isEnabled())
+ return;
+
+ xMapPane.mouseDragged(startPos, lastPos, event);
+
+
+ lastPos = event.getPoint();
+ }
+
+
+}
More information about the Schmitzm-commits
mailing list