package org.geotools.map;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.event.MapBoundsEvent;
import org.geotools.map.event.MapBoundsListener;
import org.geotools.map.event.MapBoundsEvent.Type;
import org.geotools.util.logging.Logging;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
public class MapViewport {
static protected final Logger LOGGER = Logging.getLogger("org.geotools.map");
private Rectangle screenArea;
private ReferencedEnvelope bounds;
private CopyOnWriteArrayList<MapBoundsListener> boundsListeners;
public void addMapBoundsListener(MapBoundsListener listener) {
if (boundsListeners == null) {
boundsListeners = new CopyOnWriteArrayList<MapBoundsListener>();
}
if (!boundsListeners.contains(listener)) {
boundsListeners.add(listener);
}
}
public void removeMapBoundsListener(MapBoundsListener listener) {
if (boundsListeners != null) {
boundsListeners.remove(listener);
}
}
public ReferencedEnvelope getBounds() {
return bounds;
}
public CoordinateReferenceSystem getCoordianteReferenceSystem() {
return bounds == null ? null : bounds.getCoordinateReferenceSystem();
}
public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) {
if( bounds == null ){
bounds = new ReferencedEnvelope(crs);
}
else if (bounds.getCoordinateReferenceSystem() != crs) {
if (bounds != null) {
try {
ReferencedEnvelope old = bounds;
bounds = bounds.transform(crs, true);
fireMapBoundsListenerMapBoundsChanged(MapBoundsEvent.Type.BOUNDS, old, bounds);
} catch (Exception e) {
LOGGER.log(Level.FINE, "Difficulty transforming to {0}", crs);
}
}
}
}
protected void fireMapBoundsListenerMapBoundsChanged(Type type, ReferencedEnvelope oldBounds,
ReferencedEnvelope newBounds) {
if (boundsListeners == null) {
return;
}
if (newBounds == bounds) {
newBounds = new ReferencedEnvelope(bounds);
}
MapBoundsEvent event = new MapBoundsEvent(this, type, oldBounds, newBounds);
for (MapBoundsListener boundsListener : boundsListeners) {
try {
boundsListener.mapBoundsChanged(event);
} catch (Throwable t) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.logp(Level.FINE, boundsListener.getClass().getName(),
"mapBoundsChanged", t.getLocalizedMessage(), t);
}
}
}
}
public void setBounds(ReferencedEnvelope bounds) {
ReferencedEnvelope old = this.bounds;
this.bounds = bounds;
fireMapBoundsListenerMapBoundsChanged(Type.BOUNDS, old, bounds);
}
public Rectangle getScreenArea() {
return screenArea;
}
public void setScreenArea(Rectangle screenArea) {
this.screenArea = screenArea;
}
public void transform(AffineTransform transform) {
ReferencedEnvelope old = this.bounds;
double[] coords = new double[4];
coords[0] = bounds.getMinX();
coords[1] = bounds.getMinY();
coords[2] = bounds.getMaxX();
coords[3] = bounds.getMaxY();
transform.transform(coords, 0, coords, 0, 2);
this.bounds = new ReferencedEnvelope(coords[0], coords[2], coords[1], coords[3], bounds
.getCoordinateReferenceSystem());
fireMapBoundsListenerMapBoundsChanged(MapBoundsEvent.Type.BOUNDS, old, bounds);
}
}