/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, 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.gui.swing.map.map2d.stream.strategy; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import java.awt.Point; import java.awt.event.ComponentEvent; import java.awt.Rectangle; import java.awt.event.ComponentListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import javax.swing.JComponent; import javax.swing.event.EventListenerList; import org.geotools.gui.swing.map.map2d.stream.event.StrategyEvent; import org.geotools.gui.swing.map.map2d.stream.listener.StrategyListener; import org.geotools.map.DefaultMapContext; import org.geotools.map.MapContext; import org.geotools.map.MapLayer; import org.geotools.map.event.MapLayerListEvent; import org.geotools.map.event.MapLayerListListener; import org.geotools.referencing.crs.DefaultGeographicCRS; /** * Abstract rendering strategy * * @author Johann Sorel * * @source $URL$ */ public abstract class AbstractRenderingStrategy implements StreamingStrategy, MapLayerListListener { private final EventListenerList STRATEGY_LISTENERS = new EventListenerList(); protected MapContext context = new DefaultMapContext(DefaultGeographicCRS.WGS84); private Envelope oldMapArea = null; private Rectangle oldRect = null; private final JComponent comp; private boolean autorefresh = true; private boolean isPainting = false; protected Envelope mapArea = new Envelope(1, 10, 1, 10); protected AffineTransform affineTransform = null; /** * create a default AbstractStrategy */ public AbstractRenderingStrategy() { comp = init(); comp.addComponentListener(new ComponentListener() { public void componentResized(ComponentEvent arg0) { setMapArea(mapArea); } public void componentMoved(ComponentEvent arg0) { } public void componentShown(ComponentEvent arg0) { setMapArea(mapArea); } public void componentHidden(ComponentEvent arg0) { } }); } protected abstract JComponent init(); protected Envelope fixAspectRatio(Rectangle rect, Envelope area) { double mapWidth = area.getWidth(); /* get the extent of the map */ double mapHeight = area.getHeight(); double scaleX = rect.getWidth() / area.getWidth(); /* * calculate the new * scale */ double scaleY = rect.getHeight() / area.getHeight(); double scale = 1.0; // stupid compiler! if (scaleX < scaleY) { /* pick the smaller scale */ scale = scaleX; } else { scale = scaleY; } /* calculate the difference in width and height of the new extent */ double deltaX = /* Math.abs */ ((rect.getWidth() / scale) - mapWidth); double deltaY = /* Math.abs */ ((rect.getHeight() / scale) - mapHeight); /* create the new extent */ Coordinate ll = new Coordinate(area.getMinX() - (deltaX / 2.0), area.getMinY() - (deltaY / 2.0)); Coordinate ur = new Coordinate(area.getMaxX() + (deltaX / 2.0), area.getMaxY() + (deltaY / 2.0)); return new Envelope(ll, ur); } protected void fit() { if (checkAspect()) { testRefresh(); } } protected void testRefresh() { if (autorefresh) { refresh(); } } protected boolean checkAspect() { boolean changed = false; Rectangle newRect = comp.getBounds(); if (!newRect.equals(oldRect) || !mapArea.equals(oldMapArea)) { changed = true; oldRect = newRect; oldMapArea = mapArea; } return changed; } protected synchronized boolean isValidEnvelope(Envelope env) { boolean ok = false; if (env.isNull()) { ok = false; } else { if ( Double.isNaN(env.getMinX()) || Double.isNaN(env.getMinY()) || Double.isNaN(env.getMaxX()) || Double.isNaN(env.getMaxY()) ) { ok = false; }else{ ok = true; } } return ok; } protected void setPainting(boolean b) { isPainting = b; fireRenderingEvent(isPainting); } //------------------TRIGGERS------------------------------------------------ private void fireRenderingEvent(boolean isRendering) { StrategyListener[] lst = getStrategyListeners(); for (StrategyListener l : lst) { l.setRendering(isRendering); } } protected void fireMapAreaChanged(Envelope oldone, Envelope newone) { StrategyEvent mce = new StrategyEvent(this,context, oldone, newone); StrategyListener[] lst = getStrategyListeners(); for (StrategyListener l : lst) { l.mapAreaChanged(mce); } } protected void fireMapContextChanged(MapContext oldcontext, MapContext newContext) { StrategyEvent mce = new StrategyEvent(this, oldcontext, newContext,mapArea); StrategyListener[] lst = getStrategyListeners(); for (StrategyListener l : lst) { l.mapContextChanged(mce); } } //-----------------------RenderingStrategy---------------------------------- public Coordinate toMapCoord(int mx, int my) { Rectangle bounds = comp.getBounds(); double width = mapArea.getWidth(); double height = mapArea.getHeight(); return toMapCoord(mx, my, width, height, bounds); } public Point toComponentCoord(Coordinate coord){ Rectangle bounds = comp.getBounds(); double width = mapArea.getWidth(); double height = mapArea.getHeight(); double xval = bounds.width/width; double yval = bounds.height/height; double minX = coord.x - mapArea.getMinX(); double minY = mapArea.getMaxY() - coord.y; int x = (int)(minX*xval); int y = (int)(minY*yval); return new Point(x,y); } private Coordinate toMapCoord(double mx, double my, double width, double height, Rectangle bounds) { double mapX = ((mx * width) / (double) bounds.width) + mapArea.getMinX(); double mapY = (((bounds.getHeight() - my) * height) / (double) bounds.height) + mapArea.getMinY(); return new Coordinate(mapX, mapY); } public abstract BufferedImage createBufferImage(MapLayer layer); public abstract BufferedImage createBufferImage(MapContext context); public abstract BufferedImage getSnapShot(); public abstract void refresh(); public final JComponent getComponent() { return comp; } public final void setContext(MapContext newContext) { if (newContext == null) { throw new NullPointerException("Context can't be null"); } if (this.context != newContext) { this.context.removeMapLayerListListener(this); MapContext oldContext = this.context; this.context = newContext; this.context.addMapLayerListListener(this); refresh(); fireMapContextChanged(oldContext, newContext); } } public final MapContext getContext() { return context; } public final void setMapArea(Envelope area) { if (area == null) { throw new NullPointerException("Area can't be null."); } Envelope oldenv = mapArea; mapArea = fixAspectRatio(comp.getBounds(), area); fit(); fireMapAreaChanged(oldenv, mapArea); } public final Envelope getMapArea() { return mapArea; } public final void addStrategyListener(StrategyListener listener) { STRATEGY_LISTENERS.add(StrategyListener.class, listener); } public final void removeStrategyListener(StrategyListener listener) { STRATEGY_LISTENERS.remove(StrategyListener.class, listener); } public final StrategyListener[] getStrategyListeners() { return STRATEGY_LISTENERS.getListeners(StrategyListener.class); } public final void setAutoRefreshEnabled(boolean ref) { autorefresh = ref; } public final boolean isAutoRefresh() { return autorefresh; } public final boolean isPainting() { return isPainting; } public void dispose(){ this.context.removeMapLayerListListener(this); } //----------------------Layer events---------------------------------------- public abstract void layerAdded(MapLayerListEvent event); public abstract void layerRemoved(MapLayerListEvent event); public abstract void layerChanged(MapLayerListEvent event); public abstract void layerMoved(MapLayerListEvent event); public AffineTransform getAffineTransform() { return affineTransform; } public void setAffineTransform(AffineTransform affineTransform) { this.affineTransform = affineTransform; } }