/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2003-2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.swing.event;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.swing.MapPane;
/**
* A {@code MouseEvent} with methods to retrieve position in world coordinates.
*
* @author Michael Bedward (adapted from code by Cameron Shorter)
* @since 2.6
* @source $URL$
* @version $Id$
*/
public final class MapMouseEvent extends MouseEvent {
private final DirectPosition2D worldCoords;
private final boolean isWheelEvent;
private final int wheelAmount;
/**
* Creates a new event instance.
*
* @param pane the source map pane
* @param event the source mouse event
*/
public MapMouseEvent(MapPane pane, MouseEvent event) {
super((Component) pane, event.getID(), event.getWhen(), event.getModifiers(), event
.getX(), event.getY(), event.getClickCount(), event.isPopupTrigger(), event
.getButton());
worldCoords = calculateWorldPos(pane, event);
isWheelEvent = false;
wheelAmount = 0;
}
/**
* Creates a new event instance for a mouse wheel event.
*
* @param pane the source map pane
* @param event the source mouse wheel event
*/
public MapMouseEvent(MapPane pane, MouseWheelEvent event) {
super((Component) pane, event.getID(), event.getWhen(), event.getModifiers(), event
.getX(), event.getY(), event.getClickCount(), event.isPopupTrigger());
worldCoords = calculateWorldPos(pane, event);
isWheelEvent = true;
wheelAmount = event.getWheelRotation();
}
/**
* Gets the source map pane for this event.
*/
@Override
public MapPane getSource() {
return (MapPane) super.getSource();
}
/**
* Queries whether this event was generated by a mouse wheel action.
*
* @return {@codetrue} if a mouse event
*/
public boolean isWheelEvent() {
return isWheelEvent;
}
/**
* Gets the wheel travel amount for a mouse wheel event.
*
* @return wheel travel, or 0 if this is not a mouse wheel event
*/
public int getWheelAmount() {
return wheelAmount;
}
/**
* Gets the position, in map (world) coordinates of this mouse event
*
* @return a new DirectPosition2D object for the world coordinates
*
* @deprecated Please use {@link #getWorldPos} instead
*/
public DirectPosition2D getMapPosition() {
return getWorldPos();
}
/**
* Gets the mouse position in world coordinates.
*
* @return world position
*/
public DirectPosition2D getWorldPos() {
return new DirectPosition2D(
worldCoords.getCoordinateReferenceSystem(),
worldCoords.x, worldCoords.y);
}
/**
* Gets an envelope of specified width (in world distance units) which is
* centred on the mouse position.
*
* @param widthWorld envelope width in world units
* @return the envelope
*
* @throws IllegalArgumentException if {@code widthWorld} is less than zero
*/
public ReferencedEnvelope getEnvelopeByWorld(double widthWorld) {
if (widthWorld < 0) {
throw new IllegalArgumentException("invalid value for widthWorld: " + widthWorld);
}
double halfw = widthWorld / 2;
DirectPosition2D worldPos = getWorldPos();
return new ReferencedEnvelope(
worldPos.x - halfw, worldPos.x + halfw,
worldPos.y - halfw, worldPos.y + halfw,
worldPos.getCoordinateReferenceSystem());
}
/**
* Gets an envelope of specified width (in pixels) which is
* centred on the mouse position.
*
* @param widthPixels envelope width in pixels
* @return the envelope
*
* @throws IllegalArgumentException if {@code widthPixels} is less than zero
*/
public ReferencedEnvelope getEnvelopeByPixels(double widthPixels) {
if (widthPixels < 0) {
throw new IllegalArgumentException("invalid value for widthPixels: " + widthPixels);
}
Rectangle2D screenRect = new Rectangle2D.Double(
getX() - (widthPixels / 2),
getY() - (widthPixels / 2),
widthPixels, widthPixels);
MapPane pane = getSource();
Rectangle2D worldRect = pane.getScreenToWorldTransform().createTransformedShape(
screenRect).getBounds2D();
return new ReferencedEnvelope(worldRect,
pane.getMapContent().getCoordinateReferenceSystem());
}
/**
* Helper for constructors to calculate mouse position in world coordinates.
*
* @param pane source map pane
* @param event source mouse event
* @return position in world coordinates
*/
private DirectPosition2D calculateWorldPos(MapPane pane, MouseEvent event) {
AffineTransform tr = pane.getScreenToWorldTransform();
DirectPosition2D pos = new DirectPosition2D(event.getX(), event.getY());
tr.transform(pos, pos);
pos.setCoordinateReferenceSystem(pane.getMapContent().getCoordinateReferenceSystem());
return pos;
}
}