[Schmitzm-commits] r360 - branches/1.0-gt2-2.6/src/schmitzm/geotools/gui

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Aug 31 18:04:47 CEST 2009


Author: alfonx
Date: 2009-08-31 18:04:44 +0200 (Mon, 31 Aug 2009)
New Revision: 360

Modified:
   branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java
Log:
* getLayerSourceObject changed...

Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java	2009-08-31 14:42:58 UTC (rev 359)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java	2009-08-31 16:04:44 UTC (rev 360)
@@ -65,6 +65,8 @@
 import org.geotools.data.memory.MemoryFeatureCollection;
 import org.geotools.factory.GeoTools;
 import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
+import org.geotools.feature.NameImpl;
 import org.geotools.filter.AbstractFilter;
 import org.geotools.filter.GeometryFilterImpl;
 import org.geotools.filter.spatial.DWithinImpl;
@@ -166,2602 +168,2651 @@
  */
 public class JMapPane extends org.geotools.gui.swing.JMapPane {
 
-  /**
-   * SK: Nach dem Drag, soll die {@link GeoMapPane} erfahren, dass die Area
-   * veraendert wurde.
-   */
-  protected void processDrag(int x1, int y1, int x2, int y2, MouseEvent e) {
-    // MS, 26.05.2008: Zoom-Funktion der Oberklasse soll nur erfolgen, wenn
-    // diese auch fuer die WindowSelection-Aktion eingestellt ist!
-    // Wenn z.B. fuer Links-Klick ZOOM_IN eingestellt ist, fuer
-    // Links-Drag aber SELECT_TOP, dann soll kein Zoom beim
-    // Links-Drag erfolgen!!
-    // Ausnahme: Bei Rechts-Drag (Button 3) soll die Methode
-    // trotzdem aufgerufen werden fuer Pan!
-    if (getState() == ZOOM_IN && getWindowSelectionState() != ZOOM_IN
-        && e.getButton() != 3)
-      return;
-    super.processDrag(x1, y1, x2, y2, e);
+	private static final NameImpl GC_NAME = new NameImpl(
+			"http://www.opengis.net/gml", "GridCoverage");
 
-    // SK, 19.6.2009:
-    // Ein MapAreaChangedEvent soll nur geworfen werden, wenn auch gezoomt
-    // wurde! Irgendwie wird das auch aufgerufen, wenn man mit InfoClick
-    // tool nur click - also garkeit kein draggin gemacht hat.
-    if ((oldMapArea == null || !oldMapArea.equals(mapArea))
-        && (getState() == ZOOM_IN || getState() == ZOOM_OUT))
-      fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
-  }
+	/**
+	 * SK: Nach dem Drag, soll die {@link GeoMapPane} erfahren, dass die Area
+	 * veraendert wurde.
+	 */
+	protected void processDrag(int x1, int y1, int x2, int y2, MouseEvent e) {
+		// MS, 26.05.2008: Zoom-Funktion der Oberklasse soll nur erfolgen, wenn
+		// diese auch fuer die WindowSelection-Aktion eingestellt ist!
+		// Wenn z.B. fuer Links-Klick ZOOM_IN eingestellt ist, fuer
+		// Links-Drag aber SELECT_TOP, dann soll kein Zoom beim
+		// Links-Drag erfolgen!!
+		// Ausnahme: Bei Rechts-Drag (Button 3) soll die Methode
+		// trotzdem aufgerufen werden fuer Pan!
+		if (getState() == ZOOM_IN && getWindowSelectionState() != ZOOM_IN
+				&& e.getButton() != 3)
+			return;
+		super.processDrag(x1, y1, x2, y2, e);
 
-  private static final Cursor                                      WAIT_CURSOR               = Cursor
-                                                                                                 .getPredefinedCursor(Cursor.WAIT_CURSOR);
+		// SK, 19.6.2009:
+		// Ein MapAreaChangedEvent soll nur geworfen werden, wenn auch gezoomt
+		// wurde! Irgendwie wird das auch aufgerufen, wenn man mit InfoClick
+		// tool nur click - also garkeit kein draggin gemacht hat.
+		if ((oldMapArea == null || !oldMapArea.equals(mapArea))
+				&& (getState() == ZOOM_IN || getState() == ZOOM_OUT))
+			fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
+	}
 
-  /** Logger for debug messages. */
-  protected static final Logger                                    LOGGER                    = Logger
-                                                                                                 .getLogger(JMapPane.class
-                                                                                                     .getName());
+	private static final Cursor WAIT_CURSOR = Cursor
+			.getPredefinedCursor(Cursor.WAIT_CURSOR);
 
-  /** @deprecated ersetzt durch {@link #ZOOM_IN} */
-  public static final int                                          ZoomIn                    = org.geotools.gui.swing.JMapPane.ZoomIn;
-  /** @deprecated ersetzt durch {@link #ZOOM_OUT} */
-  public static final int                                          ZoomOut                   = org.geotools.gui.swing.JMapPane.ZoomOut;
-  /** @deprecated ersetzt durch {@link #PAN} */
-  public static final int                                          Pan                       = org.geotools.gui.swing.JMapPane.Pan;
-  /** @deprecated ersetzt durch {@link #RESET} */
-  public static final int                                          Reset                     = org.geotools.gui.swing.JMapPane.Reset;
-  /** @deprecated ersetzt durch {@link #SELECT_TOP} */
-  public static final int                                          Select                    = org.geotools.gui.swing.JMapPane.Select;
+	/** Logger for debug messages. */
+	protected static final Logger LOGGER = Logger.getLogger(JMapPane.class
+			.getName());
 
-  /**
-   * Flag fuer Modus "Nichts machen".
-   * 
-   * @see #setWindowSelectionState(int)
-   * @see #setState(int)
-   */
-  public static final int                                          NONE                      = 100;
-  /**
-   * Flag fuer Modus "Zuruecksetzen". Nicht fuer Window-Auswahl moeglich!
-   * 
-   * @see #setState(int)
-   */
-  public static final int                                          RESET                     = org.geotools.gui.swing.JMapPane.Reset;
-  /**
-   * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
-   * moeglich!
-   * 
-   * @see #setState(int)
-   */
-  public static final int                                          PAN                       = org.geotools.gui.swing.JMapPane.Pan;
-  /**
-   * Flag fuer Modus "Heran zoomen".
-   * 
-   * @see #setWindowSelectionState(int)
-   * @see #setState(int)
-   */
-  public static final int                                          ZOOM_IN                   = org.geotools.gui.swing.JMapPane.ZoomIn;
-  /**
-   * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
-   * 
-   * @see #setState(int)
-   */
-  public static final int                                          ZOOM_OUT                  = org.geotools.gui.swing.JMapPane.ZoomOut;
-  /**
-   * Flag fuer Modus
-   * "SimpleFeature-Auswahl auf dem obersten (sichtbaren) Layer".
-   * 
-   * @see #setWindowSelectionState(int)
-   * @see #setState(int)
-   */
-  public static final int                                          SELECT_TOP                = org.geotools.gui.swing.JMapPane.Select;
-  /**
-   * Flag fuer Modus "SimpleFeature-Auswahl auf allen (sichtbaren) Layern".
-   * 
-   * @see #setWindowSelectionState(int)
-   * @see #setState(int)
-   */
-  public static final int                                          SELECT_ALL                = 103;
-  /**
-   * Flag fuer Modus "Auswahl nur eines Features, das erste sichtbare von Oben".
-   * 
-   * @see #setWindowSelectionState(int)
-   * @see #setState(int)
-   */
-  public static final int                                          SELECT_ONE_FROM_TOP       = 104;
+	/** @deprecated ersetzt durch {@link #ZOOM_IN} */
+	public static final int ZoomIn = org.geotools.gui.swing.JMapPane.ZoomIn;
+	/** @deprecated ersetzt durch {@link #ZOOM_OUT} */
+	public static final int ZoomOut = org.geotools.gui.swing.JMapPane.ZoomOut;
+	/** @deprecated ersetzt durch {@link #PAN} */
+	public static final int Pan = org.geotools.gui.swing.JMapPane.Pan;
+	/** @deprecated ersetzt durch {@link #RESET} */
+	public static final int Reset = org.geotools.gui.swing.JMapPane.Reset;
+	/** @deprecated ersetzt durch {@link #SELECT_TOP} */
+	public static final int Select = org.geotools.gui.swing.JMapPane.Select;
 
-  /** Modus fuer Window-Selektion (Default: {@link #ZOOM_IN}). */
-  protected int                                                    selState                  = NONE;
+	/**
+	 * Flag fuer Modus "Nichts machen".
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 * @see #setState(int)
+	 */
+	public static final int NONE = 100;
+	/**
+	 * Flag fuer Modus "Zuruecksetzen". Nicht fuer Window-Auswahl moeglich!
+	 * 
+	 * @see #setState(int)
+	 */
+	public static final int RESET = org.geotools.gui.swing.JMapPane.Reset;
+	/**
+	 * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
+	 * moeglich!
+	 * 
+	 * @see #setState(int)
+	 */
+	public static final int PAN = org.geotools.gui.swing.JMapPane.Pan;
+	/**
+	 * Flag fuer Modus "Heran zoomen".
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 * @see #setState(int)
+	 */
+	public static final int ZOOM_IN = org.geotools.gui.swing.JMapPane.ZoomIn;
+	/**
+	 * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
+	 * 
+	 * @see #setState(int)
+	 */
+	public static final int ZOOM_OUT = org.geotools.gui.swing.JMapPane.ZoomOut;
+	/**
+	 * Flag fuer Modus
+	 * "SimpleFeature-Auswahl auf dem obersten (sichtbaren) Layer".
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 * @see #setState(int)
+	 */
+	public static final int SELECT_TOP = org.geotools.gui.swing.JMapPane.Select;
+	/**
+	 * Flag fuer Modus "SimpleFeature-Auswahl auf allen (sichtbaren) Layern".
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 * @see #setState(int)
+	 */
+	public static final int SELECT_ALL = 103;
+	/**
+	 * Flag fuer Modus
+	 * "Auswahl nur eines Features, das erste sichtbare von Oben".
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 * @see #setState(int)
+	 */
+	public static final int SELECT_ONE_FROM_TOP = 104;
 
-  /**
-   * Transformation zwischen Fenster-Koordinaten und Karten-Koordinaten
-   * (lat/lon)
-   */
-  protected AffineTransform                                        transform                 = null;
+	/** Modus fuer Window-Selektion (Default: {@link #ZOOM_IN}). */
+	protected int selState = NONE;
 
-  /**
-   * Liste der angeschlossenen Listener, die auf Aktionen des MapPanes lauschen.
-   */
-  protected Vector<JMapPaneListener>                               mapPaneListeners          = new Vector<JMapPaneListener>();
+	/**
+	 * Transformation zwischen Fenster-Koordinaten und Karten-Koordinaten
+	 * (lat/lon)
+	 */
+	protected AffineTransform transform = null;
 
-  protected MouseSelectionTracker_Public                           selTracker                = new MouseSelectionTracker_Public() {
-                                                                                               public void mouseDragged(
-                                                                                                   final MouseEvent event) {
-                                                                                                 // Wenn
-                                                                                                 // Fenster
-                                                                                                 // -
-                                                                                                 // Selektions
-                                                                                                 // -
-                                                                                                 // Modus
-                                                                                                 // auf
-                                                                                                 // NICHTS
-                                                                                                 // steht
-                                                                                                 // (
-                                                                                                 // z
-                                                                                                 // .
-                                                                                                 // B
-                                                                                                 // .
-                                                                                                 // Info
-                                                                                                 // -
-                                                                                                 // Tool
-                                                                                                 // )
-                                                                                                 // ,
-                                                                                                 // keinen
-                                                                                                 // Rahmen
-                                                                                                 // beim
-                                                                                                 // Draggen
-                                                                                                 // zeichnen
-                                                                                                 if (selState == NONE)
-                                                                                                   return;
-                                                                                                 // Wenn
-                                                                                                 // Zoom
-                                                                                                 // bereits
-                                                                                                 // durch
-                                                                                                 // Oberklasse
-                                                                                                 // aktiviert
-                                                                                                 // wird
-                                                                                                 // ,
-                                                                                                 // malt
-                                                                                                 // diese
-                                                                                                 // das
-                                                                                                 // Rectangle
-                                                                                                 if (getState() == ZOOM_IN
-                                                                                                     || getState() == ZOOM_OUT)
-                                                                                                   return;
+	/**
+	 * Liste der angeschlossenen Listener, die auf Aktionen des MapPanes
+	 * lauschen.
+	 */
+	protected Vector<JMapPaneListener> mapPaneListeners = new Vector<JMapPaneListener>();
 
-                                                                                                 super
-                                                                                                     .mouseDragged(event);
-                                                                                               }
+	protected MouseSelectionTracker_Public selTracker = new MouseSelectionTracker_Public() {
+		public void mouseDragged(final MouseEvent event) {
+			// Wenn
+			// Fenster
+			// -
+			// Selektions
+			// -
+			// Modus
+			// auf
+			// NICHTS
+			// steht
+			// (
+			// z
+			// .
+			// B
+			// .
+			// Info
+			// -
+			// Tool
+			// )
+			// ,
+			// keinen
+			// Rahmen
+			// beim
+			// Draggen
+			// zeichnen
+			if (selState == NONE)
+				return;
+			// Wenn
+			// Zoom
+			// bereits
+			// durch
+			// Oberklasse
+			// aktiviert
+			// wird
+			// ,
+			// malt
+			// diese
+			// das
+			// Rectangle
+			if (getState() == ZOOM_IN || getState() == ZOOM_OUT)
+				return;
 
-                                                                                               protected void selectionPerformed(
-                                                                                                   int ox,
-                                                                                                   int oy,
-                                                                                                   int px,
-                                                                                                   int py) {
-                                                                                                 // MS
-                                                                                                 // ,
-                                                                                                 // 20.05
-                                                                                                 // .2008
-                                                                                                 // :
-                                                                                                 // In
-                                                                                                 // performSelectionEvent
-                                                                                                 // (
-                                                                                                 // .
-                                                                                                 // .
-                                                                                                 // )
-                                                                                                 // wurde
-                                                                                                 // das
-                                                                                                 // Zoomen
-                                                                                                 // wieder
-                                                                                                 // reingenommen
-                                                                                                 // ,
-                                                                                                 // damit
-                                                                                                 // bei
-                                                                                                 // Fenster
-                                                                                                 // -
-                                                                                                 // Auswahl
-                                                                                                 // auch
-                                                                                                 // gezoomt
-                                                                                                 // wird
-                                                                                                 // ,
-                                                                                                 // wenn
-                                                                                                 // der
-                                                                                                 // Klick
-                                                                                                 // -
-                                                                                                 // Zoom
-                                                                                                 // (
-                                                                                                 // setState
-                                                                                                 // (
-                                                                                                 // .
-                                                                                                 // )
-                                                                                                 // )
-                                                                                                 // deaktiviert
-                                                                                                 // ist
-                                                                                                 // .
-                                                                                                 // Wenn
-                                                                                                 // dieser
-                                                                                                 // jedoch
-                                                                                                 // ebenfalls
-                                                                                                 // aktiviert
-                                                                                                 // ist
-                                                                                                 // ,
-                                                                                                 // darf
-                                                                                                 // an
-                                                                                                 // dieser
-                                                                                                 // Stelle
-                                                                                                 // nicht
-                                                                                                 // nochmal
-                                                                                                 // gezoomt
-                                                                                                 // werden
-                                                                                                 // ,
-                                                                                                 // da
-                                                                                                 // sonst
-                                                                                                 // 2
-                                                                                                 // x
-                                                                                                 // gezoomt
-                                                                                                 // wird
-                                                                                                 // !
-                                                                                                 // !
-                                                                                                 if (getState() != ZOOM_IN)
-                                                                                                   performSelectionEvent(
-                                                                                                       ox,
-                                                                                                       oy,
-                                                                                                       px,
-                                                                                                       py);
-                                                                                               }
-                                                                                             };
+			super.mouseDragged(event);
+		}
 
-  private static final FilterFactory                           ff                        = FilterUtil.FILTER_FAC;
-  private static final GeometryFactory                             gf                        = FilterUtil.GEOMETRY_FAC;
+		protected void selectionPerformed(int ox, int oy, int px, int py) {
+			// MS
+			// ,
+			// 20.05
+			// .2008
+			// :
+			// In
+			// performSelectionEvent
+			// (
+			// .
+			// .
+			// )
+			// wurde
+			// das
+			// Zoomen
+			// wieder
+			// reingenommen
+			// ,
+			// damit
+			// bei
+			// Fenster
+			// -
+			// Auswahl
+			// auch
+			// gezoomt
+			// wird
+			// ,
+			// wenn
+			// der
+			// Klick
+			// -
+			// Zoom
+			// (
+			// setState
+			// (
+			// .
+			// )
+			// )
+			// deaktiviert
+			// ist
+			// .
+			// Wenn
+			// dieser
+			// jedoch
+			// ebenfalls
+			// aktiviert
+			// ist
+			// ,
+			// darf
+			// an
+			// dieser
+			// Stelle
+			// nicht
+			// nochmal
+			// gezoomt
+			// werden
+			// ,
+			// da
+			// sonst
+			// 2
+			// x
+			// gezoomt
+			// wird
+			// !
+			// !
+			if (getState() != ZOOM_IN)
+				performSelectionEvent(ox, oy, px, py);
+		}
+	};
 
-  /**
-   * A flag indicating if dispose() was already called. If true, then further
-   * use of this {@link JMapPane} is undefined.
-   */
-  private boolean                                                  disposed                  = false;
+	private static final FilterFactory ff = FilterUtil.FILTER_FAC;
+	private static final GeometryFactory gf = FilterUtil.GEOMETRY_FAC;
 
-  /** Listener, der auf das Mausrad lauscht und mit Zoom reagiert */
-  private MouseWheelListener                                       mouseWheelZoomListener;
+	/**
+	 * A flag indicating if dispose() was already called. If true, then further
+	 * use of this {@link JMapPane} is undefined.
+	 */
+	private boolean disposed = false;
 
-  // /** Wenn true, dann werden RasterLayer waehrend des Panning auf
-  // setVisible(false) gesetzt **/
-  // protected boolean hideRasterLayersDuringPan = false;
-  // /** Remebers the layers that are hidden during a PAN action **/
-  // protected List<MapLayer> hiddenForPanning = new LinkedList<MapLayer>();
+	/** Listener, der auf das Mausrad lauscht und mit Zoom reagiert */
+	private MouseWheelListener mouseWheelZoomListener;
 
-  /**
-   * Wenn true, dann wird der Cursor waehrend des naechsten Repaint auf die WAIT
-   * gesetzt.
-   **/
-  private boolean                                                  setWaitCursorDuringNextRepaint;
-  /**
-   * Defines which Component to change the MouseCursor if in WAIT STATE. If
-   * unset, only THIS component is used
-   **/
-  private Component                                                mouseWaitCursorComponent;
+	// /** Wenn true, dann werden RasterLayer waehrend des Panning auf
+	// setVisible(false) gesetzt **/
+	// protected boolean hideRasterLayersDuringPan = false;
+	// /** Remebers the layers that are hidden during a PAN action **/
+	// protected List<MapLayer> hiddenForPanning = new LinkedList<MapLayer>();
 
-  /** Cursor wenn kein Mausbutton gedrueckt wird. default oder SwingUtil.PAN **/
-  private Cursor                                                   normalCursor              = Cursor
-                                                                                                 .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
+	/**
+	 * Wenn true, dann wird der Cursor waehrend des naechsten Repaint auf die
+	 * WAIT gesetzt.
+	 **/
+	private boolean setWaitCursorDuringNextRepaint;
+	/**
+	 * Defines which Component to change the MouseCursor if in WAIT STATE. If
+	 * unset, only THIS component is used
+	 **/
+	private Component mouseWaitCursorComponent;
 
-  /**
-   * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen
-   * MapPane-Funktion
-   */
-  protected Cursor                                                 staticCursor              = null;
+	/** Cursor wenn kein Mausbutton gedrueckt wird. default oder SwingUtil.PAN **/
+	private Cursor normalCursor = Cursor
+			.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
 
-  private MouseInputAdapter                                        dragWaitCursorListener;
+	/**
+	 * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen
+	 * MapPane-Funktion
+	 */
+	protected Cursor staticCursor = null;
 
-  /** An (transparent) image to paint over the map in the lower right corner **/
-  private BufferedImage                                            mapImage                  = null;
+	private MouseInputAdapter dragWaitCursorListener;
 
-  /** A cache to optionally supply AttributeMetaData to the {@link JMapPane}. */
-  final protected HashMap<String, Map<Integer, AttributeMetaData>> attributeMetaDataMapCache = new HashMap<String, Map<Integer, AttributeMetaData>>();
+	/** An (transparent) image to paint over the map in the lower right corner **/
+	private BufferedImage mapImage = null;
 
-  /**
-   * Erzeugt ein neues MapPane.
-   * 
-   * @param layout
-   *          Layout-Manager fuer die GUI-Komponente (z.B. {@link BorderLayout})
-   * @param isDoubleBuffered
-   *          siehe Konstruktor der
-   *          {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
-   *          Oberklasse}
-   * @param renderer
-   *          Renderer fuer die graphische Darestellung (z.B.
-   *          {@link StreamingRenderer})
-   * @param context
-   *          Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext} ).
-   */
-  public JMapPane() {
-    this(null, true, null, null);
-  }
+	/** A cache to optionally supply AttributeMetaData to the {@link JMapPane}. */
+	final protected HashMap<String, Map<Integer, AttributeMetaData>> attributeMetaDataMapCache = new HashMap<String, Map<Integer, AttributeMetaData>>();
 
-  /**
-   * Erzeugt ein neues MapPane. Benutzt einen
-   * {@link TransitionShapefileRenderer} als default!
-   * 
-   * @param layout
-   *          Layout-Manager fuer die GUI-Komponente (z.B. {@link BorderLayout})
-   * @param isDoubleBuffered
-   *          siehe Konstruktor der
-   *          {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
-   *          Oberklasse}. Bei <code>null</code> wird <code>true</code>
-   *          andgenommen.
-   * @param renderer
-   *          Renderer fuer die graphische Darestellung (z.B.
-   *          {@link StreamingRenderer})
-   * @param context
-   *          Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext} ).
-   */
-  public JMapPane(LayoutManager layout, Boolean isDoubleBuffered,
-      GTRenderer renderer, MapContext context) {
-    super(layout != null ? layout : new BorderLayout(),
-        isDoubleBuffered != null ? isDoubleBuffered : true,
-        renderer != null ? renderer : new ShapefileRenderer(context),
-        // renderer != null ? renderer : new StreamingRenderer(),
-        context != null ? context : new DefaultMapContext(GTUtil.WGS84));
+	/**
+	 * Erzeugt ein neues MapPane.
+	 * 
+	 * @param layout
+	 *            Layout-Manager fuer die GUI-Komponente (z.B.
+	 *            {@link BorderLayout})
+	 * @param isDoubleBuffered
+	 *            siehe Konstruktor der
+	 *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+	 *            Oberklasse}
+	 * @param renderer
+	 *            Renderer fuer die graphische Darestellung (z.B.
+	 *            {@link StreamingRenderer})
+	 * @param context
+	 *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+	 *            ).
+	 */
+	public JMapPane() {
+		this(null, true, null, null);
+	}
 
-    // Dieser Hint sorgt wohl dafuer, dass die Rasterpixel nicht
-    // interpoliert werden
-    // Ueber die Methode enableAntiAliasing(boolean) kann das
-    // rechenintensive AntiAliasing fuer Text un Vectoren eingeschaltet
-    // werden
-    RenderingHints hints = ImageUtilities.NN_INTERPOLATION_HINT;
-    getRenderer().setJava2DHints(hints);
+	/**
+	 * Erzeugt ein neues MapPane. Benutzt einen
+	 * {@link TransitionShapefileRenderer} als default!
+	 * 
+	 * @param layout
+	 *            Layout-Manager fuer die GUI-Komponente (z.B.
+	 *            {@link BorderLayout})
+	 * @param isDoubleBuffered
+	 *            siehe Konstruktor der
+	 *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+	 *            Oberklasse}. Bei <code>null</code> wird <code>true</code>
+	 *            andgenommen.
+	 * @param renderer
+	 *            Renderer fuer die graphische Darestellung (z.B.
+	 *            {@link StreamingRenderer})
+	 * @param context
+	 *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+	 *            ).
+	 */
+	public JMapPane(LayoutManager layout, Boolean isDoubleBuffered,
+			GTRenderer renderer, MapContext context) {
+		super(layout != null ? layout : new BorderLayout(),
+				isDoubleBuffered != null ? isDoubleBuffered : true,
+				renderer != null ? renderer : new ShapefileRenderer(context),
+				// renderer != null ? renderer : new StreamingRenderer(),
+				context != null ? context : new DefaultMapContext(GTUtil.WGS84));
 
-    // hints.add( new RenderingHints(RenderingHints.KEY_ANTIALIASING,
-    // RenderingHints.VALUE_ANTIALIAS_OFF ) );
-    // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-    // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ) );
-    // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-    // RenderingHints.VALUE_INTERPOLATION_BICUBIC ) );
-    // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-    // RenderingHints.VALUE_INTERPOLATION_BILINEAR ) );
-    // hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
-    // RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED ) );
-    // hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
-    // RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY ) );
-    // Map rendererParams = new HashMap();
-    // rendererParams.put("optimizedDataLoadingEnabled",new Boolean(true) );
-    // renderer.setRendererHints( rendererParams );
+		// Dieser Hint sorgt wohl dafuer, dass die Rasterpixel nicht
+		// interpoliert werden
+		// Ueber die Methode enableAntiAliasing(boolean) kann das
+		// rechenintensive AntiAliasing fuer Text un Vectoren eingeschaltet
+		// werden
+		RenderingHints hints = ImageUtilities.NN_INTERPOLATION_HINT;
+		getRenderer().setJava2DHints(hints);
 
-    setWindowSelectionState(ZOOM_IN);
-    setState(ZOOM_IN);
+		// hints.add( new RenderingHints(RenderingHints.KEY_ANTIALIASING,
+		// RenderingHints.VALUE_ANTIALIAS_OFF ) );
+		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+		// RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ) );
+		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+		// RenderingHints.VALUE_INTERPOLATION_BICUBIC ) );
+		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+		// RenderingHints.VALUE_INTERPOLATION_BILINEAR ) );
+		// hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
+		// RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED ) );
+		// hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
+		// RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY ) );
+		// Map rendererParams = new HashMap();
+		// rendererParams.put("optimizedDataLoadingEnabled",new Boolean(true) );
+		// renderer.setRendererHints( rendererParams );
 
-    // Listener, der auf das Mausrad lauscht und mit Zoom reagiert
-    mouseWheelZoomListener = new MouseWheelListener() {
-      public void mouseWheelMoved(MouseWheelEvent e) {
-        performMouseWheelEvent(e);
-      }
-    };
-    this.addMouseWheelListener(mouseWheelZoomListener);
+		setWindowSelectionState(ZOOM_IN);
+		setState(ZOOM_IN);
 
-    // Listener, der auf das Mausrad lauscht und mit Zoom reagiert
-    mouseWheelZoomListener = new MouseWheelListener() {
-      public void mouseWheelMoved(MouseWheelEvent e) {
-        performMouseWheelEvent(e);
-      }
-    };
-    this.addMouseWheelListener(mouseWheelZoomListener);
+		// Listener, der auf das Mausrad lauscht und mit Zoom reagiert
+		mouseWheelZoomListener = new MouseWheelListener() {
+			public void mouseWheelMoved(MouseWheelEvent e) {
+				performMouseWheelEvent(e);
+			}
+		};
+		this.addMouseWheelListener(mouseWheelZoomListener);
 
-    /**
-     * Dieser Listener setzt nach dem Panning (aka Drag) den Maus-Cursor auf
-     * Wait. Der Rest des Panning wird in der Uberklasse abgewickelt
-     */
-    dragWaitCursorListener = new MouseInputAdapter() {
-      public void mouseReleased(MouseEvent e) {
-        setWaitCursorDuringNextRepaint = true;
-      };
-    };
-    this.addMouseListener(dragWaitCursorListener);
-//
-//    // Hightlight immer auf dem obersten sichtbaren Nicht-Raster-Layer
-//    // MS-01.sc: Der GT-Highlight-Manager arbeitet zu langsam und ohnehin
-//    // nur fuer unprojizierte Layer korrekt
-//    // this.setHighlight(true);
-//    this.setHighlight(false);
-//    // MS-01.ec
+		// Listener, der auf das Mausrad lauscht und mit Zoom reagiert
+		mouseWheelZoomListener = new MouseWheelListener() {
+			public void mouseWheelMoved(MouseWheelEvent e) {
+				performMouseWheelEvent(e);
+			}
+		};
+		this.addMouseWheelListener(mouseWheelZoomListener);
 
-    getContext().addMapLayerListListener(
-        new schmitzm.geotools.map.event.MapLayerListAdapter() {
-          private void resetHighlightLayer() {
-//            if (isHighlight())
-//              setHighlightLayer(getTopVisibleNonGridCoverageLayer());
-          }
+		/**
+		 * Dieser Listener setzt nach dem Panning (aka Drag) den Maus-Cursor auf
+		 * Wait. Der Rest des Panning wird in der Uberklasse abgewickelt
+		 */
+		dragWaitCursorListener = new MouseInputAdapter() {
+			public void mouseReleased(MouseEvent e) {
+				setWaitCursorDuringNextRepaint = true;
+			};
+		};
+		this.addMouseListener(dragWaitCursorListener);
+		//
+		// // Hightlight immer auf dem obersten sichtbaren Nicht-Raster-Layer
+		// // MS-01.sc: Der GT-Highlight-Manager arbeitet zu langsam und ohnehin
+		// // nur fuer unprojizierte Layer korrekt
+		// // this.setHighlight(true);
+		// this.setHighlight(false);
+		// // MS-01.ec
 
-          public void layerAdded(org.geotools.map.event.MapLayerListEvent e) {
-            resetHighlightLayer();
-          }
+		getContext().addMapLayerListListener(
+				new schmitzm.geotools.map.event.MapLayerListAdapter() {
+					private void resetHighlightLayer() {
+						// if (isHighlight())
+						// setHighlightLayer(getTopVisibleNonGridCoverageLayer());
+					}
 
-          public void layerChanged(org.geotools.map.event.MapLayerListEvent e) {
-            resetHighlightLayer();
-          }
+					public void layerAdded(
+							org.geotools.map.event.MapLayerListEvent e) {
+						resetHighlightLayer();
+					}
 
-          public void layerMoved(org.geotools.map.event.MapLayerListEvent e) {
-            resetHighlightLayer();
-          }
+					public void layerChanged(
+							org.geotools.map.event.MapLayerListEvent e) {
+						resetHighlightLayer();
+					}
 
-          public void layerRemoved(org.geotools.map.event.MapLayerListEvent e) {
-            resetHighlightLayer();
-          }
-        });
+					public void layerMoved(
+							org.geotools.map.event.MapLayerListEvent e) {
+						resetHighlightLayer();
+					}
 
-    // CRS wird immer vom ersten in die Karte eingefuegten Layer uebernommen
-    // Wenn noch keine MapArea gesetzt wurde, wird diese vom Layer
-    // uebernommen
-    getContext().addMapLayerListListener(
-        new schmitzm.geotools.map.event.MapLayerListAdapter() {
-          public void layerAdded(org.geotools.map.event.MapLayerListEvent e) {
-            if (getContext().getLayerCount() == 1) {
-              CoordinateReferenceSystem crs = null;
-              // CRS aus Layer ermitteln
-              try {
-                crs = e.getLayer().getFeatureSource().getSchema()
-                    .getGeometryDescriptor().getCoordinateReferenceSystem();
-                // wenn noch keine MapArea gesetzt wurde, den
-                // Ausdehnungsbereich des ersten Layers
-                // verwenden, so dass die erste
-                // Karte komplett angezeigt wird
-                if (getMapArea() == null) {
-                  Envelope newMapArea = new Envelope(e.getLayer()
-                      .getFeatureSource().getBounds());
-                  // Kartenbereich um 10% vergroessern, damit
-                  // z.B. auch ein Punkt-Layer, welches nur
-                  // aus 2 Punnkten
-                  // besteht, sichtbar ist (Punkte liegen
-                  // sonst
-                  // genau auf dem Rand der angezeigten
-                  // Flaeche)
-                  newMapArea.expandBy(newMapArea.getWidth() * 0.1, newMapArea
-                      .getHeight() * 0.1);
-                  setMapArea(newMapArea);
-                  // in layerAdded(.) der Oberklasse wird
-                  // mapArea nochmal neu gesetzt, wenn das
-                  // erste Layer
-                  // eingefuegt wird
-                  // >> hier nur die AreaOfInterest setzen
-                  getContext().setAreaOfInterest(newMapArea, crs);
-                }
-              } catch (Exception err) {
-                LOGGER
-                    .warn("CRS could not be determined from map layer. WGS84 used.");
-                // err.printStackTrace();
-                crs = DefaultGeographicCRS.WGS84;
-              }
-              // CRS dem MapContext zuweisen
-              try {
-                getContext().setCoordinateReferenceSystem(crs);
-                // LOGGER.debug("MapContext-CRS set to: "+crs);
-              } catch (Exception err) {
-                LOGGER.error("CRS could not be assigned to map context.", err);
-              }
-            }
-          }
-        });
-  }
+					public void layerRemoved(
+							org.geotools.map.event.MapLayerListEvent e) {
+						resetHighlightLayer();
+					}
+				});
 
-  /**
-   * Get the BufferedImage to use as a flaoting icon in the lower right corner.
-   * 
-   * @return <code>null</code> if the feature is deactivated.
-   */
-  public BufferedImage getMapImage() {
-    return mapImage;
-  }
+		// CRS wird immer vom ersten in die Karte eingefuegten Layer uebernommen
+		// Wenn noch keine MapArea gesetzt wurde, wird diese vom Layer
+		// uebernommen
+		getContext().addMapLayerListListener(
+				new schmitzm.geotools.map.event.MapLayerListAdapter() {
+					public void layerAdded(
+							org.geotools.map.event.MapLayerListEvent e) {
+						if (getContext().getLayerCount() == 1) {
+							CoordinateReferenceSystem crs = null;
+							// CRS aus Layer ermitteln
+							try {
+								crs = e.getLayer().getFeatureSource()
+										.getSchema().getGeometryDescriptor()
+										.getCoordinateReferenceSystem();
+								// wenn noch keine MapArea gesetzt wurde, den
+								// Ausdehnungsbereich des ersten Layers
+								// verwenden, so dass die erste
+								// Karte komplett angezeigt wird
+								if (getMapArea() == null) {
+									Envelope newMapArea = new Envelope(e
+											.getLayer().getFeatureSource()
+											.getBounds());
+									// Kartenbereich um 10% vergroessern, damit
+									// z.B. auch ein Punkt-Layer, welches nur
+									// aus 2 Punnkten
+									// besteht, sichtbar ist (Punkte liegen
+									// sonst
+									// genau auf dem Rand der angezeigten
+									// Flaeche)
+									newMapArea.expandBy(
+											newMapArea.getWidth() * 0.1,
+											newMapArea.getHeight() * 0.1);
+									setMapArea(newMapArea);
+									// in layerAdded(.) der Oberklasse wird
+									// mapArea nochmal neu gesetzt, wenn das
+									// erste Layer
+									// eingefuegt wird
+									// >> hier nur die AreaOfInterest setzen
+									getContext().setAreaOfInterest(newMapArea,
+											crs);
+								}
+							} catch (Exception err) {
+								LOGGER
+										.warn("CRS could not be determined from map layer. WGS84 used.");
+								// err.printStackTrace();
+								crs = DefaultGeographicCRS.WGS84;
+							}
+							// CRS dem MapContext zuweisen
+							try {
+								getContext().setCoordinateReferenceSystem(crs);
+								// LOGGER.debug("MapContext-CRS set to: "+crs);
+							} catch (Exception err) {
+								LOGGER
+										.error(
+												"CRS could not be assigned to map context.",
+												err);
+							}
+						}
+					}
+				});
+	}
 
-  /**
-   * Set the BufferedImage to use as a flaoting icon in the lower right corner
-   * 
-   * @param mapImageIcon
-   *          <code>null</code> is allowed and deactivates this icon.
-   */
-  public void setMapImage(BufferedImage mapImage) {
-    this.mapImage = mapImage;
-  }
+	/**
+	 * Get the BufferedImage to use as a flaoting icon in the lower right
+	 * corner.
+	 * 
+	 * @return <code>null</code> if the feature is deactivated.
+	 */
+	public BufferedImage getMapImage() {
+		return mapImage;
+	}
 
-  /**
-   * Gibt die optional gesetzte {@link Component} zurueck, deren Cursor auch auf
-   * WAIT gesetzt werden soll
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   * 
-   * @return null oder {@link Component}
-   */
-  public Component getWaitCursorComponent() {
-    return mouseWaitCursorComponent;
-  }
+	/**
+	 * Set the BufferedImage to use as a flaoting icon in the lower right corner
+	 * 
+	 * @param mapImageIcon
+	 *            <code>null</code> is allowed and deactivates this icon.
+	 */
+	public void setMapImage(BufferedImage mapImage) {
+		this.mapImage = mapImage;
+	}
 
-  /**
-   * Setzt eine Componente, deren Cursor zusaetzlich zu THIS noch auf WAIT
-   * gesetzt wird falls durch dies ueberhaupt durch
-   * setSetWaitCursorDuringNextRepaint(true) veranlasst wurde
-   * 
-   * @param parentComponent
-   *          z.b. der Frame, der diese {@link JMapPane} enhaelt
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void setWaitCursorComponent(Component parentComponent) {
-    this.mouseWaitCursorComponent = parentComponent;
-  }
+	/**
+	 * Gibt die optional gesetzte {@link Component} zurueck, deren Cursor auch
+	 * auf WAIT gesetzt werden soll
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 * 
+	 * @return null oder {@link Component}
+	 */
+	public Component getWaitCursorComponent() {
+		return mouseWaitCursorComponent;
+	}
 
-  /**
-   * Aktualisiert die Karten-Anzeige vollstaendig. Ruft
-   * {@link JMapPane#setReset(boolean) JMapPane#setReset(true)} auf und
-   * anschliessend {@link #repaint()}.
-   * 
-   * <br>
-   * SK: Der Mauszeiger wird waehrend des repaints auf WAIT gesetzt mittels
-   * {@link #setWaitCursorDuringNextRepaint(boolean)}
-   * 
-   * @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&uuml;ger</a>
-   */
-  public void refresh() {
+	/**
+	 * Setzt eine Componente, deren Cursor zusaetzlich zu THIS noch auf WAIT
+	 * gesetzt wird falls durch dies ueberhaupt durch
+	 * setSetWaitCursorDuringNextRepaint(true) veranlasst wurde
+	 * 
+	 * @param parentComponent
+	 *            z.b. der Frame, der diese {@link JMapPane} enhaelt
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void setWaitCursorComponent(Component parentComponent) {
+		this.mouseWaitCursorComponent = parentComponent;
+	}
 
-    // SK: Added by SK, 27.09.2007
-    // Durch den reset ist das repaint immer etwas aufwaendiger. Der Cursor
-    // wechselt dann auf WAIT
-    setWaitCursorDuringNextRepaint(true);
+	/**
+	 * Aktualisiert die Karten-Anzeige vollstaendig. Ruft
+	 * {@link JMapPane#setReset(boolean) JMapPane#setReset(true)} auf und
+	 * anschliessend {@link #repaint()}.
+	 * 
+	 * <br>
+	 * SK: Der Mauszeiger wird waehrend des repaints auf WAIT gesetzt mittels
+	 * {@link #setWaitCursorDuringNextRepaint(boolean)}
+	 * 
+	 * @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&uuml;ger</a>
+	 */
+	public void refresh() {
 
-    setReset(true);
-    repaint();
-  }
+		// SK: Added by SK, 27.09.2007
+		// Durch den reset ist das repaint immer etwas aufwaendiger. Der Cursor
+		// wechselt dann auf WAIT
+		setWaitCursorDuringNextRepaint(true);
 
-  /**
-   * Aktiviert oder deaktiviert das AntiAliasing for diese {@link JMapPane}.
-   * AntiALiasing ist besonders fuer Textbeschriftung sehr schoen, verbraucht
-   * aber auch mehr Performance.
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void setAntiAliasing(final boolean aa) {
-    // LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
-    RenderingHints java2DHints = getRenderer().getJava2DHints();
-    if (java2DHints == null)
-      java2DHints = GeoTools.getDefaultHints();
-    java2DHints.put(RenderingHints.KEY_ANTIALIASING,
-        aa ? RenderingHints.VALUE_ANTIALIAS_ON
-            : RenderingHints.VALUE_ANTIALIAS_OFF);
-    java2DHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
-        aa ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
-            : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-    java2DHints.put(RenderingHints.KEY_RENDERING,
-        aa ? RenderingHints.VALUE_RENDER_QUALITY
-            : RenderingHints.VALUE_RENDER_SPEED);
-    getRenderer().setJava2DHints(java2DHints);
-  }
+		setReset(true);
+		repaint();
+	}
 
-  /**
-   * Setzt den Kartenausschnitt auf die Ausdehnung eines bestimmten Layers.
-   * Macht nichts, wenn {@code null} uebergeben wird.
-   * 
-   * <br>
-   * A refresh of the map is NOT called.
-   * 
-   * @param layer
-   *          ein Layer
-   */
-  public void zoomToLayer(MapLayer layer) {
-    if (layer == null)
-      return;
-    // This action ususally takes some time..
-    setWaitCursorDuringNextRepaint = true;
-    try {
+	/**
+	 * Aktiviert oder deaktiviert das AntiAliasing for diese {@link JMapPane}.
+	 * AntiALiasing ist besonders fuer Textbeschriftung sehr schoen, verbraucht
+	 * aber auch mehr Performance.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void setAntiAliasing(final boolean aa) {
+		// LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
+		RenderingHints java2DHints = getRenderer().getJava2DHints();
+		if (java2DHints == null)
+			java2DHints = GeoTools.getDefaultHints();
+		java2DHints.put(RenderingHints.KEY_ANTIALIASING,
+				aa ? RenderingHints.VALUE_ANTIALIAS_ON
+						: RenderingHints.VALUE_ANTIALIAS_OFF);
+		java2DHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
+				aa ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
+						: RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+		java2DHints.put(RenderingHints.KEY_RENDERING,
+				aa ? RenderingHints.VALUE_RENDER_QUALITY
+						: RenderingHints.VALUE_RENDER_SPEED);
+		getRenderer().setJava2DHints(java2DHints);
+	}
 
-      // BB umrechnen von Layer-CRS in Map-CRS
-      final Envelope mapAreaNew = JTSUtil.transformEnvelope(layer
-          .getFeatureSource().getBounds(), layer.getFeatureSource().getSchema()
-          .getGeometryDescriptor().getCoordinateReferenceSystem(), getContext()
-          .getCoordinateReferenceSystem());
-      // Kartenbereich um 10% vergroessern, damit z.B. auch ein
-      // Punkt-Layer,
-      // welches nur aus 2 Punnkten besteht, sichtbar ist (Punkte liegen
-      // sonst
-      // genau auf dem Rand der angezeigten Flaeche)
+	/**
+	 * Setzt den Kartenausschnitt auf die Ausdehnung eines bestimmten Layers.
+	 * Macht nichts, wenn {@code null} uebergeben wird.
+	 * 
+	 * <br>
+	 * A refresh of the map is NOT called.
+	 * 
+	 * @param layer
+	 *            ein Layer
+	 */
+	public void zoomToLayer(MapLayer layer) {
+		if (layer == null)
+			return;
+		// This action ususally takes some time..
+		setWaitCursorDuringNextRepaint = true;
+		try {
 
-      if (mapAreaNew != null) {
-        mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1,
-            mapAreaNew.getHeight() * 0.1);
-        setMapArea(mapAreaNew);
-      } else {
-        LOGGER.warn("Couldn't transformEnvelope when zooming to the layer");
-      }
-    } catch (Exception err) {
-      LOGGER.warn("Zoom to layer did not terminate correctly", err);
-    }
-  }
+			// BB umrechnen von Layer-CRS in Map-CRS
+			final Envelope mapAreaNew = JTSUtil.transformEnvelope(layer
+					.getFeatureSource().getBounds(), layer.getFeatureSource()
+					.getSchema().getGeometryDescriptor()
+					.getCoordinateReferenceSystem(), getContext()
+					.getCoordinateReferenceSystem());
+			// Kartenbereich um 10% vergroessern, damit z.B. auch ein
+			// Punkt-Layer,
+			// welches nur aus 2 Punnkten besteht, sichtbar ist (Punkte liegen
+			// sonst
+			// genau auf dem Rand der angezeigten Flaeche)
 
-  /**
-   * Zooms the {@link JMapPane} to the {@link Envelope} of a layer.
-   * 
-   * <br>
-   * A refresh of the map is not done automatically
-   * 
-   * @param index
-   *          Index of the {@link MapLayer} in the {@link MapContext} (from back
-   *          to top)
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void zoomToLayer(int index) {
-    final MapContext context = getContext();
-    if (context != null)
-      zoomToLayer(context.getLayer(index));
-  }
+			if (mapAreaNew != null) {
+				mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew
+						.getHeight() * 0.1);
+				setMapArea(mapAreaNew);
+			} else {
+				LOGGER
+						.warn("Couldn't transformEnvelope when zooming to the layer");
+			}
+		} catch (Exception err) {
+			LOGGER.warn("Zoom to layer did not terminate correctly", err);
+		}
+	}
 
-  /**
-   * Zooms the {@link JMapPane} to the {@link Envelope} of the selected layer.
-   * The layer is selected by the idx, counting from front to back, like humans
-   * would expect in a {@link JList}
-   * 
-   * <br>
-   * A refresh of the map is not done automatically
-   * 
-   * 
-   * 
-   * @param index
-   *          Reverse index of the {@link MapLayer} in the {@link MapContext}
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void zoomToLayerIdxReverse(int index) {
-    zoomToLayer(getContext().getLayerCount() - 1 - index);
-  }
+	/**
+	 * Zooms the {@link JMapPane} to the {@link Envelope} of a layer.
+	 * 
+	 * <br>
+	 * A refresh of the map is not done automatically
+	 * 
+	 * @param index
+	 *            Index of the {@link MapLayer} in the {@link MapContext} (from
+	 *            back to top)
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void zoomToLayer(int index) {
+		final MapContext context = getContext();
+		if (context != null)
+			zoomToLayer(context.getLayer(index));
+	}
 
-  /**
-   * Liefert die Anzahl der Einheiten, die ein Bildschirm-Pixel darstellt. Die
-   * Einheit ist die Grundeinheit des CRS
-   */
-  public double getScale() {
-    if (getWidth() == 0 || getMapArea() == null)
-      return 0.0;
-    return getMapArea().getWidth() / getWidth();
-  }
+	/**
+	 * Zooms the {@link JMapPane} to the {@link Envelope} of the selected layer.
+	 * The layer is selected by the idx, counting from front to back, like
+	 * humans would expect in a {@link JList}
+	 * 
+	 * <br>
+	 * A refresh of the map is not done automatically
+	 * 
+	 * 
+	 * 
+	 * @param index
+	 *            Reverse index of the {@link MapLayer} in the
+	 *            {@link MapContext}
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void zoomToLayerIdxReverse(int index) {
+		zoomToLayer(getContext().getLayerCount() - 1 - index);
+	}
 
-  /**
-   * Liefert oberste Layer (sichtbar oder unsichtbar).
-   */
-  public MapLayer getTopLayer() {
-    int count = getContext().getLayerCount();
-    return count > 0 ? getContext().getLayer(count - 1) : null;
-  }
+	/**
+	 * Liefert die Anzahl der Einheiten, die ein Bildschirm-Pixel darstellt. Die
+	 * Einheit ist die Grundeinheit des CRS
+	 */
+	public double getScale() {
+		if (getWidth() == 0 || getMapArea() == null)
+			return 0.0;
+		return getMapArea().getWidth() / getWidth();
+	}
 
-  /**
-   * Liefert oberste sichtbare Layer.
-   */
-  public MapLayer getTopVisibleLayer() {
-    for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-      MapLayer layer = getContext().getLayer(i);
-      if (layer.isVisible())
-        return layer;
-    }
-    return null;
-  }
+	/**
+	 * Liefert oberste Layer (sichtbar oder unsichtbar).
+	 */
+	public MapLayer getTopLayer() {
+		int count = getContext().getLayerCount();
+		return count > 0 ? getContext().getLayer(count - 1) : null;
+	}
 
-  /**
-   * Liefert oberste sichtbare Raster-Layer.
-   */
-  public MapLayer getTopVisibleGridCoverageLayer() {
-    for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-      MapLayer layer = getContext().getLayer(i);
-      if (layer.isVisible() && isGridCoverageLayer(layer))
-        return layer;
-    }
-    return null;
-  }
+	/**
+	 * Liefert oberste sichtbare Layer.
+	 */
+	public MapLayer getTopVisibleLayer() {
+		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+			MapLayer layer = getContext().getLayer(i);
+			if (layer.isVisible())
+				return layer;
+		}
+		return null;
+	}
 
-  /**
-   * Liefert oberste sichtbare Nicht-Raster-Layer.
-   */
-  public MapLayer getTopVisibleNonGridCoverageLayer() {
-    for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-      MapLayer layer = getContext().getLayer(i);
-      if (layer.isVisible() && !isGridCoverageLayer(layer))
-        return layer;
-    }
-    return null;
-  }
+	/**
+	 * Liefert oberste sichtbare Raster-Layer.
+	 */
+	public MapLayer getTopVisibleGridCoverageLayer() {
+		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+			MapLayer layer = getContext().getLayer(i);
+			if (layer.isVisible() && isGridCoverageLayer(layer))
+				return layer;
+		}
+		return null;
+	}
 
-  /**
-   * Liefert unterste Layer (sichtbar oder unsichtbar).
-   */
-  public MapLayer getBottomLayer() {
-    return getContext().getLayerCount() > 0 ? getContext().getLayer(0) : null;
-  }
+	/**
+	 * Liefert oberste sichtbare Nicht-Raster-Layer.
+	 */
+	public MapLayer getTopVisibleNonGridCoverageLayer() {
+		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+			MapLayer layer = getContext().getLayer(i);
+			if (layer.isVisible() && !isGridCoverageLayer(layer))
+				return layer;
+		}
+		return null;
+	}
 
-  /**
-   * Setzt den Modus fuer Window-Selektion. Default ist {@link #ZOOM_IN}.
-   * 
-   * 
-   * <ul>
-   * <li>{@link #ZOOM_IN}: Zoom auf selektierten Bereich</li>
-   * <li>{@link #SELECT_TOP}: Auswahl der Features im selektierten Bereich des
-   * <b>obersten</b> (sichtbaren) Layers</li>
-   * <li>{@link #SELECT_ALL} Auswahl der Features im selektierten ueber alle
-   * Layer</li>
-   * <li>{@link #NONE} Nichts machen</li>
-   * </ul>
-   * 
-   * @param newSelState
-   *          Modus fuer Window-Selektion
-   */
-  public void setWindowSelectionState(final int newSelState) {
-    if (newSelState != NONE && newSelState != ZOOM_IN
-        && newSelState != SELECT_TOP && newSelState != SELECT_ALL
-        && newSelState != SELECT_ONE_FROM_TOP)
-      throw new IllegalArgumentException(
-          "Unknown selection state for window selection!");
+	/**
+	 * Liefert unterste Layer (sichtbar oder unsichtbar).
+	 */
+	public MapLayer getBottomLayer() {
+		return getContext().getLayerCount() > 0 ? getContext().getLayer(0)
+				: null;
+	}
 
-    // Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
-    // Selektionsfenster beim Draggen nicht mehr gezeichnet wird
-    if ((newSelState == NONE) && (selState != NONE)) {
-      this.removeMouseListener(selTracker);
-    } else
-    // Den selTracker bei Wechsel von NONE aktivieren (SK)
-    if ((newSelState != NONE) && (selState == NONE)) {
-      this.addMouseListener(selTracker);
-    }
+	/**
+	 * Setzt den Modus fuer Window-Selektion. Default ist {@link #ZOOM_IN}.
+	 * 
+	 * 
+	 * <ul>
+	 * <li>{@link #ZOOM_IN}: Zoom auf selektierten Bereich</li>
+	 * <li>{@link #SELECT_TOP}: Auswahl der Features im selektierten Bereich des
+	 * <b>obersten</b> (sichtbaren) Layers</li>
+	 * <li>{@link #SELECT_ALL} Auswahl der Features im selektierten ueber alle
+	 * Layer</li>
+	 * <li>{@link #NONE} Nichts machen</li>
+	 * </ul>
+	 * 
+	 * @param newSelState
+	 *            Modus fuer Window-Selektion
+	 */
+	public void setWindowSelectionState(final int newSelState) {
+		if (newSelState != NONE && newSelState != ZOOM_IN
+				&& newSelState != SELECT_TOP && newSelState != SELECT_ALL
+				&& newSelState != SELECT_ONE_FROM_TOP)
+			throw new IllegalArgumentException(
+					"Unknown selection state for window selection!");
 
-    this.selState = newSelState;
+		// Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
+		// Selektionsfenster beim Draggen nicht mehr gezeichnet wird
+		if ((newSelState == NONE) && (selState != NONE)) {
+			this.removeMouseListener(selTracker);
+		} else
+		// Den selTracker bei Wechsel von NONE aktivieren (SK)
+		if ((newSelState != NONE) && (selState == NONE)) {
+			this.addMouseListener(selTracker);
+		}
 
-    // Je nach Aktion den Cursor umsetzen
-    updateCursor();
-  }
+		this.selState = newSelState;
 
-  /**
-   * Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion (Zoom,
-   * Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor
-   * gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion
-   * beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann
-   * {@code null} als Parameter uebergeben werden
-   * 
-   * @param cursor
-   *          Cursor
-   */
-  public void setStaticCursor(Cursor cursor) {
-    this.staticCursor = cursor;
-    if (cursor != null)
-      super.setCursor(cursor);
-  }
+		// Je nach Aktion den Cursor umsetzen
+		updateCursor();
+	}
 
-  /**
-   * Liefert den statisch eingestellten Cursor, der unabhaengig von der
-   * eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird.
-   * 
-   * @return {@code null}, wenn kein statischer Cursor verwendet, sondern der
-   *         Cursor automatisch je nach MapPane-Aktion eingestellt wird.
-   */
-  public Cursor getStaticCursor() {
-    return this.staticCursor;
-  }
+	/**
+	 * Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion (Zoom,
+	 * Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor
+	 * gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion
+	 * beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann
+	 * {@code null} als Parameter uebergeben werden
+	 * 
+	 * @param cursor
+	 *            Cursor
+	 */
+	public void setStaticCursor(Cursor cursor) {
+		this.staticCursor = cursor;
+		if (cursor != null)
+			super.setCursor(cursor);
+	}
 
-  /**
-   * Abhaengig von selState wird der Cursor gesetzt
-   */
-  public void updateCursor() {
-    // wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig
-    // von der aktuellen Aktion
-    if (this.staticCursor != null) {
-      setCursor(staticCursor);
-      return;
-    }
-    // Je nach Aktion den Cursor umsetzen
-    switch (this.selState) {
-    case SELECT_TOP:
-    case SELECT_ONE_FROM_TOP:
-    case SELECT_ALL:
-      setCursor(SwingUtil.CROSSHAIR_CURSOR);
-      break;
-    case ZOOM_IN:
-      setCursor(SwingUtil.ZOOMIN_CURSOR);
-      break;
-    case ZOOM_OUT:
-      setCursor(SwingUtil.ZOOMOUT_CURSOR);
-      break;
-    default:
-      setCursor(getNormalCursor());
-      break;
-    }
-  }
+	/**
+	 * Liefert den statisch eingestellten Cursor, der unabhaengig von der
+	 * eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird.
+	 * 
+	 * @return {@code null}, wenn kein statischer Cursor verwendet, sondern der
+	 *         Cursor automatisch je nach MapPane-Aktion eingestellt wird.
+	 */
+	public Cursor getStaticCursor() {
+		return this.staticCursor;
+	}
 
-  /**
-   * Liefert den Modus fuer Window-Selektion.
-   * 
-   * @see #setWindowSelectionState(int)
-   */
-  public int getWindowSelectionState() {
-    return this.selState;
-  }
+	/**
+	 * Abhaengig von selState wird der Cursor gesetzt
+	 */
+	public void updateCursor() {
+		// wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig
+		// von der aktuellen Aktion
+		if (this.staticCursor != null) {
+			setCursor(staticCursor);
+			return;
+		}
+		// Je nach Aktion den Cursor umsetzen
+		switch (this.selState) {
+		case SELECT_TOP:
+		case SELECT_ONE_FROM_TOP:
+		case SELECT_ALL:
+			setCursor(SwingUtil.CROSSHAIR_CURSOR);
+			break;
+		case ZOOM_IN:
+			setCursor(SwingUtil.ZOOMIN_CURSOR);
+			break;
+		case ZOOM_OUT:
+			setCursor(SwingUtil.ZOOMOUT_CURSOR);
+			break;
+		default:
+			setCursor(getNormalCursor());
+			break;
+		}
+	}
 
-  /**
-   * Fuegt der Map einen Listener hinzu.
-   * 
-   * @param l
-   *          neuer Listener
-   */
-  public void addMapPaneListener(JMapPaneListener l) {
-    mapPaneListeners.add(l);
-  }
+	/**
+	 * Liefert den Modus fuer Window-Selektion.
+	 * 
+	 * @see #setWindowSelectionState(int)
+	 */
+	public int getWindowSelectionState() {
+		return this.selState;
+	}
 
-  /**
-   * Entfernt einen Listener von der Map.
-   * 
-   * @param l
-   *          zu entfernender Listener
-   */
-  public void removeMapPaneListener(JMapPaneListener l) {
-    mapPaneListeners.remove(l);
-  }
+	/**
+	 * Fuegt der Map einen Listener hinzu.
+	 * 
+	 * @param l
+	 *            neuer Listener
+	 */
+	public void addMapPaneListener(JMapPaneListener l) {
+		mapPaneListeners.add(l);
+	}
 
-  /**
-   * Propagiert ein Ereignis an alle angeschlossenen Listener.
-   * 
-   * @param e
-   *          Ereignis
-   */
-  protected void fireMapPaneEvent(JMapPaneEvent e) {
-    for (JMapPaneListener l : mapPaneListeners)
-      l.performMapPaneEvent(e);
-  }
+	/**
+	 * Entfernt einen Listener von der Map.
+	 * 
+	 * @param l
+	 *            zu entfernender Listener
+	 */
+	public void removeMapPaneListener(JMapPaneListener l) {
+		mapPaneListeners.remove(l);
+	}
 
-  /**
-   * Konvertiert die Maus-Koordinaten (relativ zum <code>JMapPane</code>) in
-   * Karten-Koordinaten.
-   * 
-   * @param e
-   *          Maus-Ereignis
-   */
-  public static Point2D getMapCoordinatesFromEvent(MouseEvent e) {
-    // aktuelle Geo-Position aus GeoMouseEvent ermitteln
-    if (e != null && e instanceof MapMouseEvent)
-      try {
-        return ((MapMouseEvent) e).getMapPosition().toPoint2D();
-      } catch (Exception err) {
-        LOGGER.error(
-            "return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();",
-            err);
-      }
+	/**
+	 * Propagiert ein Ereignis an alle angeschlossenen Listener.
+	 * 
+	 * @param e
+	 *            Ereignis
+	 */
+	protected void fireMapPaneEvent(JMapPaneEvent e) {
+		for (JMapPaneListener l : mapPaneListeners)
+			l.performMapPaneEvent(e);
+	}
 
-    // aktuelle Geo-Position ueber Transformation des JMapPane berechnen
-    if (e != null && e.getSource() instanceof JMapPane) {
-      AffineTransform at = ((JMapPane) e.getSource()).getTransform();
-      if (at != null)
-        return at.transform(e.getPoint(), null);
-    }
+	/**
+	 * Konvertiert die Maus-Koordinaten (relativ zum <code>JMapPane</code>) in
+	 * Karten-Koordinaten.
+	 * 
+	 * @param e
+	 *            Maus-Ereignis
+	 */
+	public static Point2D getMapCoordinatesFromEvent(MouseEvent e) {
+		// aktuelle Geo-Position aus GeoMouseEvent ermitteln
+		if (e != null && e instanceof MapMouseEvent)
+			try {
+				return ((MapMouseEvent) e).getMapPosition().toPoint2D();
+			} catch (Exception err) {
+				LOGGER
+						.error(
+								"return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();",
+								err);
+			}
 
-    return null;
-  }
+		// aktuelle Geo-Position ueber Transformation des JMapPane berechnen
+		if (e != null && e.getSource() instanceof JMapPane) {
+			AffineTransform at = ((JMapPane) e.getSource()).getTransform();
+			if (at != null)
+				return at.transform(e.getPoint(), null);
+		}
 
-  /**
-   * Verarbeitet die Selektion eines Karten-Ausschnitts. Erzeugt immer ein
-   * {@link GeneralSelectionEvent} fuer den ausgewaehlten Bereich. Wurden
-   * Features oder Raster selektiert, werden zudem {@link FeatureSelectedEvent
-   * FeatureSelectedEvents} (bzw. GridCoverageSelectedEvents
-   * GridCoverageSelectedEvents) ausgeloest.
-   * 
-   * @param ox
-   *          X-Koordinate der VON-Position
-   * @param oy
-   *          Y-Koordinate der VON-Position
-   * @param px
-   *          X-Koordinate der BIS-Position
-   * @param py
-   *          Y-Koordinate der BIS-Position
-   */
-  protected void performSelectionEvent(int ox, int oy, int px, int py) {
-    if (getContext().getLayerCount() == 0)
-      return;
+		return null;
+	}
 
-    // keine wirkliche Selektion, sondern nur ein Klick
-    if (ox == px || oy == py)
-      return;
+	/**
+	 * Verarbeitet die Selektion eines Karten-Ausschnitts. Erzeugt immer ein
+	 * {@link GeneralSelectionEvent} fuer den ausgewaehlten Bereich. Wurden
+	 * Features oder Raster selektiert, werden zudem
+	 * {@link FeatureSelectedEvent FeatureSelectedEvents} (bzw.
+	 * GridCoverageSelectedEvents GridCoverageSelectedEvents) ausgeloest.
+	 * 
+	 * @param ox
+	 *            X-Koordinate der VON-Position
+	 * @param oy
+	 *            Y-Koordinate der VON-Position
+	 * @param px
+	 *            X-Koordinate der BIS-Position
+	 * @param py
+	 *            Y-Koordinate der BIS-Position
+	 */
+	protected void performSelectionEvent(int ox, int oy, int px, int py) {
+		if (getContext().getLayerCount() == 0)
+			return;
 
-    // Fenster-Koordinaten in Map-Koordinaten umwandeln
-    Envelope env = tranformWindowToGeo(ox, oy, px, py);
+		// keine wirkliche Selektion, sondern nur ein Klick
+		if (ox == px || oy == py)
+			return;
 
-    // Generelles Event ausloesen
-    fireMapPaneEvent(new GeneralSelectionEvent(this, env));
+		// Fenster-Koordinaten in Map-Koordinaten umwandeln
+		Envelope env = tranformWindowToGeo(ox, oy, px, py);
 
-    int selectState = getWindowSelectionState();
-    switch (selectState) {
-    case ZOOM_IN: // Karte neu setzen
-      this.setMapArea(env);
-      refresh(); // WICHTIG!! Damit die veraenderte Form beruecksichtigt
-      // wird!?
-      break;
-    case SELECT_TOP:
-    case SELECT_ONE_FROM_TOP:
-    case SELECT_ALL: // Features selektieren
-      boolean featuresFound = findFeaturesAndFireEvents(
-          new BoundingBoxFilterGenerator(env, getContext()
-              .getCoordinateReferenceSystem()), selectState, env);
-      if (selectState == SELECT_ALL || !featuresFound)
-        findGridCoverageSubsetsAndFireEvents(env, selectState);
-      break;
-    }
-  }
+		// Generelles Event ausloesen
+		fireMapPaneEvent(new GeneralSelectionEvent(this, env));
 
-  /**
-   * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
-   * 
-   * @param e
-   *          Mausrad-Event
-   */
-  protected void performMouseWheelEvent(MouseWheelEvent e) {
-    if (getContext().getLayerCount() == 0)
-      return;
+		int selectState = getWindowSelectionState();
+		switch (selectState) {
+		case ZOOM_IN: // Karte neu setzen
+			this.setMapArea(env);
+			refresh(); // WICHTIG!! Damit die veraenderte Form beruecksichtigt
+			// wird!?
+			break;
+		case SELECT_TOP:
+		case SELECT_ONE_FROM_TOP:
+		case SELECT_ALL: // Features selektieren
+			boolean featuresFound = findFeaturesAndFireEvents(
+					new BoundingBoxFilterGenerator(env, getContext()
+							.getCoordinateReferenceSystem()), selectState, env);
+			if (selectState == SELECT_ALL || !featuresFound)
+				findGridCoverageSubsetsAndFireEvents(env, selectState);
+			break;
+		}
+	}
 
-    int units = e.getUnitsToScroll();
-    // Positiver Wert --> Zoom in --> Faktor < 1
-    // Negativer Wert --> Zoom out --> Faktir > 1
+	/**
+	 * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
+	 * 
+	 * @param e
+	 *            Mausrad-Event
+	 */
+	protected void performMouseWheelEvent(MouseWheelEvent e) {
+		if (getContext().getLayerCount() == 0)
+			return;
 
-    // SK: 9.9.2007 zoom jetzt wie bei GoogleEarth
-    double zFactor = units > 0 ? 1.3 : 1 / 1.3;
-    // vorher double zFactor = units > 0 ? 1/1.2 : 1.2;
+		int units = e.getUnitsToScroll();
+		// Positiver Wert --> Zoom in --> Faktor < 1
+		// Negativer Wert --> Zoom out --> Faktir > 1
 
-    // Fenster-Koordinaten zu Karten-Koordinaten transformieren
-    Point2D mapCoord = getTransform().transform(e.getPoint(), null);
-    // Relative Position des Mauszeigers zum Kartenausschnitt
-    // -> Nach Zoom soll dieselbe Kartenposition unterhalb des Mauszeigers
-    // erscheinen, wie vor dem Zoom
-    double relX = (mapCoord.getX() - getMapArea().getMinX())
-        / getMapArea().getWidth();
-    double relY = (mapCoord.getY() - getMapArea().getMinY())
-        / getMapArea().getHeight();
+		// SK: 9.9.2007 zoom jetzt wie bei GoogleEarth
+		double zFactor = units > 0 ? 1.3 : 1 / 1.3;
+		// vorher double zFactor = units > 0 ? 1/1.2 : 1.2;
 
-    // Neuen Karten-Ausschnitt berechnen
-    Coordinate ll = new Coordinate(mapCoord.getX() - getMapArea().getWidth()
-        * relX * zFactor, mapCoord.getY() - getMapArea().getHeight() * relY
-        * zFactor);
-    Coordinate ur = new Coordinate(mapCoord.getX() + getMapArea().getWidth()
-        * (1 - relX) * zFactor, mapCoord.getY() + getMapArea().getHeight()
-        * (1 - relY) * zFactor);
-    setMapArea(new Envelope(ll, ur));
+		// Fenster-Koordinaten zu Karten-Koordinaten transformieren
+		Point2D mapCoord = getTransform().transform(e.getPoint(), null);
+		// Relative Position des Mauszeigers zum Kartenausschnitt
+		// -> Nach Zoom soll dieselbe Kartenposition unterhalb des Mauszeigers
+		// erscheinen, wie vor dem Zoom
+		double relX = (mapCoord.getX() - getMapArea().getMinX())
+				/ getMapArea().getWidth();
+		double relY = (mapCoord.getY() - getMapArea().getMinY())
+				/ getMapArea().getHeight();
 
-    setWaitCursorDuringNextRepaint(true);
-    repaint();
-  }
+		// Neuen Karten-Ausschnitt berechnen
+		Coordinate ll = new Coordinate(mapCoord.getX()
+				- getMapArea().getWidth() * relX * zFactor, mapCoord.getY()
+				- getMapArea().getHeight() * relY * zFactor);
+		Coordinate ur = new Coordinate(mapCoord.getX()
+				+ getMapArea().getWidth() * (1 - relX) * zFactor, mapCoord
+				.getY()
+				+ getMapArea().getHeight() * (1 - relY) * zFactor);
+		setMapArea(new Envelope(ll, ur));
 
-  /**
-   * Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten.
-   * 
-   * @param ox
-   *          X-Koordinate der VON-Position
-   * @param oy
-   *          Y-Koordinate der VON-Position
-   * @param px
-   *          X-Koordinate der BIS-Position
-   * @param py
-   *          Y-Koordinate der BIS-Position
-   */
-  public Envelope tranformWindowToGeo(int ox, int oy, int px, int py) {
-    AffineTransform at = getTransform();
-    Point2D geoO = at.transform(new Point2D.Double(ox, oy), null);
-    Point2D geoP = at.transform(new Point2D.Double(px, py), null);
-    return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP.getY());
-  }
+		setWaitCursorDuringNextRepaint(true);
+		repaint();
+	}
 
-  /**
-   * Transformiert eine Fenster-Koordinate in eine Geo-Koordinate.
-   * 
-   * @param x
-   *          X-Koordinate
-   * @param y
-   *          Y-Koordinate
-   */
-  public Point2D tranformWindowToGeo(int x, int y) {
-    AffineTransform at = getTransform();
-    return at.transform(new Point2D.Double(x, y), null);
-  }
+	/**
+	 * Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten.
+	 * 
+	 * @param ox
+	 *            X-Koordinate der VON-Position
+	 * @param oy
+	 *            Y-Koordinate der VON-Position
+	 * @param px
+	 *            X-Koordinate der BIS-Position
+	 * @param py
+	 *            Y-Koordinate der BIS-Position
+	 */
+	public Envelope tranformWindowToGeo(int ox, int oy, int px, int py) {
+		AffineTransform at = getTransform();
+		Point2D geoO = at.transform(new Point2D.Double(ox, oy), null);
+		Point2D geoP = at.transform(new Point2D.Double(px, py), null);
+		return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP.getY());
+	}
 
-  /**
-   * Berechnet die Transformation zwischen Fenster- und Karten-Koordinaten neu.
-   */
-  protected void resetTransform() {
-    if (getMapArea() == null || getWidth() == 0 || getHeight() == 0)
-      return;
-    this.transform = new AffineTransform(
-    // Genauso wie die Fenster-Koordinaten, werden die Longitude-Koordinaten
-        // nach rechts (Osten) hin groesser
-        // --> positive Verschiebung
-        getMapArea().getWidth() / getWidth(),
-        // keine Verzerrung
-        0.0, 0.0,
-        // Waehrend die Fenster-Koordinaten nach unten hin groesser
-        // werden,
-        // werden Latitude-Koordinaten nach Sueden hin keiner
-        // --> negative Verschiebung
-        -getMapArea().getHeight() / getHeight(),
-        // Die Longitude-Koordinaten werden nach Osten hin groesser
-        // --> obere linke Ecke des Fensters hat also den Minimalwert
-        getMapArea().getMinX(),
-        // Die Latitude-Koordinaten werden nach Norden hin groesser
-        // --> obere linke Ecke des Fensters hat also den Maximalwert
-        getMapArea().getMaxY());
-  }
+	/**
+	 * Transformiert eine Fenster-Koordinate in eine Geo-Koordinate.
+	 * 
+	 * @param x
+	 *            X-Koordinate
+	 * @param y
+	 *            Y-Koordinate
+	 */
+	public Point2D tranformWindowToGeo(int x, int y) {
+		AffineTransform at = getTransform();
+		return at.transform(new Point2D.Double(x, y), null);
+	}
 
-  /**
-   * Liefert eine affine Transformation, um von den Fenster-Koordinaten in die
-   * Karten-Koordinaten (Lat/Lon) umzurechnen.
-   * 
-   * @return eine Kopie der aktuellen Transformation; <code>null</code> wenn
-   *         noch keine Karte angezeigt wird
-   */
-  public AffineTransform getTransform() {
-    // Workaround: Obwohl eine Karte gesetzt ist, kann es sein, dass die
-    // Transformation noch nicht gesetzt ist (da noch kein
-    // setMapArea(.)-Aufruf stattgefunden hat!)
-    if (transform == null)
-      resetTransform();
-    // nur Kopie der Transformation zurueckgeben!
-    if (transform != null)
-      return new AffineTransform(transform);
-    return null;
-  }
+	/**
+	 * Berechnet die Transformation zwischen Fenster- und Karten-Koordinaten
+	 * neu.
+	 */
+	protected void resetTransform() {
+		if (getMapArea() == null || getWidth() == 0 || getHeight() == 0)
+			return;
+		this.transform = new AffineTransform(
+		// Genauso wie die Fenster-Koordinaten, werden die Longitude-Koordinaten
+				// nach rechts (Osten) hin groesser
+				// --> positive Verschiebung
+				getMapArea().getWidth() / getWidth(),
+				// keine Verzerrung
+				0.0, 0.0,
+				// Waehrend die Fenster-Koordinaten nach unten hin groesser
+				// werden,
+				// werden Latitude-Koordinaten nach Sueden hin keiner
+				// --> negative Verschiebung
+				-getMapArea().getHeight() / getHeight(),
+				// Die Longitude-Koordinaten werden nach Osten hin groesser
+				// --> obere linke Ecke des Fensters hat also den Minimalwert
+				getMapArea().getMinX(),
+				// Die Latitude-Koordinaten werden nach Norden hin groesser
+				// --> obere linke Ecke des Fensters hat also den Maximalwert
+				getMapArea().getMaxY());
+	}
 
-  /**
-   * Setzt die sichtbare Karte. Danach wird die {@linkplain AffineTransform
-   * Transformation} zwischen Fenster-Koordinaten und Karten-Koordinaten neu
-   * berechnet.<br>
-   * Loest ein {@link ScaleChangedEvent aus}
-   * 
-   * {@link #setMapArea(Envelope)} wird ignoriert, falls durch die neue MapArea
-   * ein nicht gueltiger Massstab entstehen wuerde UND die bisherige maparea !=
-   * null ist
-   * 
-   * @param env
-   *          neuer Kartenausschnitt
-   * @see #resetTransform()
-   * @see #getTransform()
-   * 
-   * @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&uuml;ger</a>
-   */
-  @Override
-  public void setMapArea(Envelope env) {
-    // **********************************************************************
-    // Ueber die Funktionen setMaxZoomScale und setMinZoomScale kann der
-    // geotools JMapPane ein gueltiger Massstabsbereich gesetzt werden.
-    // Dieser
-    // wird hier ueberprueft. (SK)
-    // **********************************************************************
-    if (super.getMapArea() != null) {
-      env = bestAllowedMapArea(env);
-    }
+	/**
+	 * Liefert eine affine Transformation, um von den Fenster-Koordinaten in die
+	 * Karten-Koordinaten (Lat/Lon) umzurechnen.
+	 * 
+	 * @return eine Kopie der aktuellen Transformation; <code>null</code> wenn
+	 *         noch keine Karte angezeigt wird
+	 */
+	public AffineTransform getTransform() {
+		// Workaround: Obwohl eine Karte gesetzt ist, kann es sein, dass die
+		// Transformation noch nicht gesetzt ist (da noch kein
+		// setMapArea(.)-Aufruf stattgefunden hat!)
+		if (transform == null)
+			resetTransform();
+		// nur Kopie der Transformation zurueckgeben!
+		if (transform != null)
+			return new AffineTransform(transform);
+		return null;
+	}
 
-    double oldScale = getScale();
-    Envelope oldEnv = getMapArea();
+	/**
+	 * Setzt die sichtbare Karte. Danach wird die {@linkplain AffineTransform
+	 * Transformation} zwischen Fenster-Koordinaten und Karten-Koordinaten neu
+	 * berechnet.<br>
+	 * Loest ein {@link ScaleChangedEvent aus}
+	 * 
+	 * {@link #setMapArea(Envelope)} wird ignoriert, falls durch die neue
+	 * MapArea ein nicht gueltiger Massstab entstehen wuerde UND die bisherige
+	 * maparea != null ist
+	 * 
+	 * @param env
+	 *            neuer Kartenausschnitt
+	 * @see #resetTransform()
+	 * @see #getTransform()
+	 * 
+	 * @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&uuml;ger</a>
+	 */
+	@Override
+	public void setMapArea(Envelope env) {
+		// **********************************************************************
+		// Ueber die Funktionen setMaxZoomScale und setMinZoomScale kann der
+		// geotools JMapPane ein gueltiger Massstabsbereich gesetzt werden.
+		// Dieser
+		// wird hier ueberprueft. (SK)
+		// **********************************************************************
+		if (super.getMapArea() != null) {
+			env = bestAllowedMapArea(env);
+		}
 
-    super.setMapArea(env);
+		double oldScale = getScale();
+		Envelope oldEnv = getMapArea();
 
-    resetTransform();
-    double newScale = getScale();
-    Envelope newEnv = getMapArea();
+		super.setMapArea(env);
 
-    if (oldScale != newScale)
-      fireMapPaneEvent(new ScaleChangedEvent(this, oldScale, newScale));
-    if (oldEnv == null && newEnv != null || oldEnv != null
-        && !oldEnv.equals(newEnv))
-      fireMapPaneEvent(new MapAreaChangedEvent(this, oldEnv, newEnv));
-  }
+		resetTransform();
+		double newScale = getScale();
+		Envelope newEnv = getMapArea();
 
-  /**
-   * 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&uuml;ger</a>
-   */
-  public void mouseClicked(MouseEvent e) {
-    // wenn noch kein Layer dargestellt wird, nichts machen
-    if (getContext().getLayerCount() == 0)
-      return;
+		if (oldScale != newScale)
+			fireMapPaneEvent(new ScaleChangedEvent(this, oldScale, newScale));
+		if (oldEnv == null && newEnv != null || oldEnv != null
+				&& !oldEnv.equals(newEnv))
+			fireMapPaneEvent(new MapAreaChangedEvent(this, oldEnv, newEnv));
+	}
 
-    // double oldScale = getScale();
-    // Envelope oldEnv = getMapArea();
+	/**
+	 * 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&uuml;ger</a>
+	 */
+	public void mouseClicked(MouseEvent e) {
+		// wenn noch kein Layer dargestellt wird, nichts machen
+		if (getContext().getLayerCount() == 0)
+			return;
 
-    switch (e.getButton()) {
-    // Linksklick --> Eingestellte Funktion
-    case MouseEvent.BUTTON1: // SimpleFeature-Auswahl nicht ueber die
-      // super-Funktion
-      int state = getState();
+		// double oldScale = getScale();
+		// Envelope oldEnv = getMapArea();
 
-      if (state == SELECT_TOP || state == SELECT_ONE_FROM_TOP
-          || state == SELECT_ALL) {
+		switch (e.getButton()) {
+		// Linksklick --> Eingestellte Funktion
+		case MouseEvent.BUTTON1: // SimpleFeature-Auswahl nicht ueber die
+			// super-Funktion
+			int state = 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.
-         */
+			if (state == SELECT_TOP || state == SELECT_ONE_FROM_TOP
+					|| state == SELECT_ALL) {
 
-        // Fenster-Koordinate in Geo-Koordinate umwandelt
-        Point2D geoCoord = getTransform().transform(e.getPoint(), null);
-        com.vividsolutions.jts.geom.Point mousePoint = new GeometryFactory()
-            .createPoint(new Coordinate(geoCoord.getX(), geoCoord.getY()));
+				/**
+				 * 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.
+				 */
 
-        // 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 = getTransform().transform(
-            pAtDistance, null);
-        final Double dist = Math.abs(geoCoordAtDistance.getX()
-            - geoCoord.getX());
+				// Fenster-Koordinate in Geo-Koordinate umwandelt
+				Point2D geoCoord = getTransform().transform(e.getPoint(), null);
+				com.vividsolutions.jts.geom.Point mousePoint = new GeometryFactory()
+						.createPoint(new Coordinate(geoCoord.getX(), geoCoord
+								.getY()));
 
-        final Envelope envelope = new Envelope(geoCoord.getX(),
-            geoCoord.getX(), geoCoord.getY(), 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 = getTransform().transform(
+						pAtDistance, null);
+				final Double dist = Math.abs(geoCoordAtDistance.getX()
+						- geoCoord.getX());
 
-        Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> result = findVisibleFeatures(
-            new NearPointFilterGenerator(geoCoord, dist, getContext()
-                .getCoordinateReferenceSystem()), state, envelope);
+				final Envelope envelope = new Envelope(geoCoord.getX(),
+						geoCoord.getX(), geoCoord.getY(), geoCoord.getY());
 
-        boolean featuresFound = false;
-        // Events ausloesen fuer jedes Layer
-        for (Enumeration<MapLayer> element = result.keys(); element
-            .hasMoreElements();) {
+				Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = findVisibleFeatures(
+						new NearPointFilterGenerator(geoCoord, dist,
+								getContext().getCoordinateReferenceSystem()),
+						state, envelope);
 
-          MapLayer layer = element.nextElement();
-          FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
-              .get(layer);
-          FeatureCollection<SimpleFeatureType, SimpleFeature> fcOne;
+				boolean featuresFound = false;
+				// Events ausloesen fuer jedes Layer
+				for (Enumeration<MapLayer> element = result.keys(); element
+						.hasMoreElements();) {
 
-          if (fc != null && !fc.isEmpty()) {
+					MapLayer layer = element.nextElement();
+					FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
+							.get(layer);
+					FeatureCollection<SimpleFeatureType, SimpleFeature> fcOne;
 
-            if (fc.size() > 1) {
-              // Hier werden alle Features weggeschmissen, bis auf
-              // das raeumlich naechste.
+					if (fc != null && !fc.isEmpty()) {
 
-              SimpleFeature nearestFeature = null;
-              Double nearestDist = 0.0;
+						if (fc.size() > 1) {
+							// Hier werden alle Features weggeschmissen, bis auf
+							// das raeumlich naechste.
 
-              Iterator<SimpleFeature> fcIt = fc.iterator();
-              while (fcIt.hasNext()) {
-                SimpleFeature f = fcIt.next();
-                Object obj = f.getAttribute(0);
+							SimpleFeature nearestFeature = null;
+							Double nearestDist = 0.0;
 
-                if (obj instanceof Geometry) {
-                  // Bei Punkten ja noch ganz einfach:
-                  Geometry featureGeometry = (Geometry) obj;
-                  double distance = featureGeometry.distance(mousePoint);
+							Iterator<SimpleFeature> fcIt = fc.iterator();
+							while (fcIt.hasNext()) {
+								SimpleFeature f = fcIt.next();
+								Object obj = f.getAttribute(0);
 
-                  if ((nearestFeature == null) || (distance < nearestDist)) {
-                    nearestFeature = f;
-                    nearestDist = distance;
-                  }
-                } else {
-                  LOGGER.info("!obj instanceof Geometry      obj = "
-                      + obj.getClass().getSimpleName());
-                }
+								if (obj instanceof Geometry) {
+									// Bei Punkten ja noch ganz einfach:
+									Geometry featureGeometry = (Geometry) obj;
+									double distance = featureGeometry
+											.distance(mousePoint);
 
-              }
-              fc.close(fcIt);
+									if ((nearestFeature == null)
+											|| (distance < nearestDist)) {
+										nearestFeature = f;
+										nearestDist = distance;
+									}
+								} else {
+									LOGGER
+											.info("!obj instanceof Geometry      obj = "
+													+ obj.getClass()
+															.getSimpleName());
+								}
 
-              fcOne = new MemoryFeatureCollection(fc.getSchema());
-              fc.clear();
-              fcOne.add(nearestFeature);
-            } else {
-              fcOne = fc;
-            }
-            fireMapPaneEvent(new FeatureSelectedEvent(JMapPane.this, layer,
-                envelope, fcOne));
-            featuresFound = true;
-          }
-        }
+							}
+							fc.close(fcIt);
 
-        // TODO TODO TODO SK: DIese trennung: erst SimpleFeature layers, dann
-        // grid layers check ist doof!
-        // if (state == SELECT_ALL || !result.isEmpty())
+							fcOne = new MemoryFeatureCollection(fc.getSchema());
+							fc.clear();
+							fcOne.add(nearestFeature);
+						} else {
+							fcOne = fc;
+						}
+						fireMapPaneEvent(new FeatureSelectedEvent(
+								JMapPane.this, layer, envelope, fcOne));
+						featuresFound = true;
+					}
+				}
 
-        // LOGGER.info("state= "+state+"     featuresFound = "+
-        // featuresFound);
-        if (state == SELECT_ALL || !featuresFound) {
-          // LOGGER.info("   findGridCoverageValuesAndFireEvents");
-          findGridCoverageValuesAndFireEvents(geoCoord, state);
-        }
+				// TODO TODO TODO SK: DIese trennung: erst SimpleFeature layers,
+				// dann
+				// grid layers check ist doof!
+				// if (state == SELECT_ALL || !result.isEmpty())
 
-        break;
-      }
-      super.mouseClicked(e);
-      return; // was: breka, aber wir brauchen ja nicht das
-      // setMapArea(mapArea)
+				// LOGGER.info("state= "+state+"     featuresFound = "+
+				// featuresFound);
+				if (state == SELECT_ALL || !featuresFound) {
+					// LOGGER.info("   findGridCoverageValuesAndFireEvents");
+					findGridCoverageValuesAndFireEvents(geoCoord, state);
+				}
 
-      // Rechtsklick --> Zoom-Out
-    case MouseEvent.BUTTON3:
-      int oldState = getState();
-      // MS: ist doch eleganter, wenn IMMER mit Rechtsklick raus-gezoomt
-      // werden kann!
-      // // ZOOM_OUT nur wenn Links-Klick auf ZOOM_IN eingestellt ist)
-      // if ( oldState != ZOOM_IN )
-      // return;
-      setState(ZOOM_OUT);
-      super.mouseClicked(e);
-      setState(oldState);
-      break;
-    // Sonst nix
-    default:
-      return;
-    }
+				break;
+			}
+			super.mouseClicked(e);
+			return; // was: breka, aber wir brauchen ja nicht das
+			// setMapArea(mapArea)
 
-    // In super.mouseClicked(.) wird (nach Zoom) die MapArea neu gesetzt,
-    // aber
-    // leider ohne setMapArea(.) aufzurufen, sondern indem einfach die
-    // Variable
-    // 'mapArea' neu belegt wird
-    // --> Transform muss neu berechnet werden
-    // --> Aenderung der Aufloesung propagieren
+			// Rechtsklick --> Zoom-Out
+		case MouseEvent.BUTTON3:
+			int oldState = getState();
+			// MS: ist doch eleganter, wenn IMMER mit Rechtsklick raus-gezoomt
+			// werden kann!
+			// // ZOOM_OUT nur wenn Links-Klick auf ZOOM_IN eingestellt ist)
+			// if ( oldState != ZOOM_IN )
+			// return;
+			setState(ZOOM_OUT);
+			super.mouseClicked(e);
+			setState(oldState);
+			break;
+		// Sonst nix
+		default:
+			return;
+		}
 
-    setMapArea(mapArea);
-    // resetTransform();
-    // double newScale = getScale();
-    // Envelope newEnv = getMapArea();
-    // if ( oldScale != newScale )
-    // fireMapPaneEvent( new ScaleChangedEvent(this,oldScale,newScale) );
-    // if ( oldEnv == null && newEnv != null || oldEnv != null &&
-    // !oldEnv.equals( newEnv ) )
-    // fireMapPaneEvent( new MapAreaChangedEvent(this,oldEnv,newEnv) );
-  }
+		// In super.mouseClicked(.) wird (nach Zoom) die MapArea neu gesetzt,
+		// aber
+		// leider ohne setMapArea(.) aufzurufen, sondern indem einfach die
+		// Variable
+		// 'mapArea' neu belegt wird
+		// --> Transform muss neu berechnet werden
+		// --> Aenderung der Aufloesung propagieren
 
-  /**
-   * In <code>super.paintComponent(.)</code> wird unter gewissen Umstaenden die
-   * MapArea neu gesetzt, aber leider ohne {@link #setMapArea(Envelope)}
-   * aufzurufen, sondern indem einfach die Variable <code>mapArea</code> neu
-   * belegt wird. Damit auch die Transformation an den neuen Kartenbereich
-   * angepasst wird, muss diese Methode ueberschrieben werden.
-   * <p>
-   * Neu von SK: Ich habe in der Geotools
-   * {@link org.geotools.gui.swing.JMapPane} die noetigen variablen protected
-   * gemacht, um hier schon festzustellen, ob der aufruf von
-   * super.paintComponent das eigentliche aussehen der Karte veraendern wird.
-   * Die Methode paintComponent wird naemlich bei jeder Bewegung der Maus
-   * aufgerufen, und meistens wird super.paintComponent nur ein gebufferted
-   * Image auf den Ausschnitt zeichnen. Falls die "seriouseChange" zu erwarten
-   * ist, wird evt. der Mauscursor auf WAIT gesetzt, und auf jeden Fall die
-   * Methode {@link #resetTransform()} aufgerufen.<br>
-   * Sinn des Ganzen? Ich habe versucht etwas Performance zu gewinnen, da sonst
-   * bei jeder Mausbewegung die die {@link AffineTransform} durch
-   * {@link #resetTransform()} neu berechnet wurde.
-   * 
-   * @param g
-   *          Graphics
-   * @see #resetTransform()
-   * 
-   * @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&uuml;ger</a>
-   */
-  protected void paintComponent(Graphics g) {
+		setMapArea(mapArea);
+		// resetTransform();
+		// double newScale = getScale();
+		// Envelope newEnv = getMapArea();
+		// if ( oldScale != newScale )
+		// fireMapPaneEvent( new ScaleChangedEvent(this,oldScale,newScale) );
+		// if ( oldEnv == null && newEnv != null || oldEnv != null &&
+		// !oldEnv.equals( newEnv ) )
+		// fireMapPaneEvent( new MapAreaChangedEvent(this,oldEnv,newEnv) );
+	}
 
-    // if (!reset) return; // TEST TEST TETS ONLY REMOVE!!
+	/**
+	 * In <code>super.paintComponent(.)</code> wird unter gewissen Umstaenden
+	 * die MapArea neu gesetzt, aber leider ohne {@link #setMapArea(Envelope)}
+	 * aufzurufen, sondern indem einfach die Variable <code>mapArea</code> neu
+	 * belegt wird. Damit auch die Transformation an den neuen Kartenbereich
+	 * angepasst wird, muss diese Methode ueberschrieben werden.
+	 * <p>
+	 * Neu von SK: Ich habe in der Geotools
+	 * {@link org.geotools.gui.swing.JMapPane} die noetigen variablen protected
+	 * gemacht, um hier schon festzustellen, ob der aufruf von
+	 * super.paintComponent das eigentliche aussehen der Karte veraendern wird.
+	 * Die Methode paintComponent wird naemlich bei jeder Bewegung der Maus
+	 * aufgerufen, und meistens wird super.paintComponent nur ein gebufferted
+	 * Image auf den Ausschnitt zeichnen. Falls die "seriouseChange" zu erwarten
+	 * ist, wird evt. der Mauscursor auf WAIT gesetzt, und auf jeden Fall die
+	 * Methode {@link #resetTransform()} aufgerufen.<br>
+	 * Sinn des Ganzen? Ich habe versucht etwas Performance zu gewinnen, da
+	 * sonst bei jeder Mausbewegung die die {@link AffineTransform} durch
+	 * {@link #resetTransform()} neu berechnet wurde.
+	 * 
+	 * @param g
+	 *            Graphics
+	 * @see #resetTransform()
+	 * 
+	 * @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&uuml;ger</a>
+	 */
+	protected void paintComponent(Graphics g) {
 
-    Cursor oldCursor = null;
-    boolean seriouseChange = false;
+		// if (!reset) return; // TEST TEST TETS ONLY REMOVE!!
 
-    if (!getBounds().equals(oldRect) || reset)
-      seriouseChange = true;
-    else if (!mapArea.equals(oldMapArea))
-      seriouseChange = true;
+		Cursor oldCursor = null;
+		boolean seriouseChange = false;
 
-    if (seriouseChange) {
-      if (setWaitCursorDuringNextRepaint) {
+		if (!getBounds().equals(oldRect) || reset)
+			seriouseChange = true;
+		else if (!mapArea.equals(oldMapArea))
+			seriouseChange = true;
 
-        if (getWaitCursorComponent() != null) {
-          // Der Cursor soll auch in einer anderen Component geaendert
-          // werden..
-          oldCursor = getWaitCursorComponent().getCursor();
-          getWaitCursorComponent().setCursor(WAIT_CURSOR);
-        }
+		if (seriouseChange) {
+			if (setWaitCursorDuringNextRepaint) {
 
-        // Den Cursor extra nochmal in dieser COmponente aendern
-        setCursor(WAIT_CURSOR);
-      }
-    }
+				if (getWaitCursorComponent() != null) {
+					// Der Cursor soll auch in einer anderen Component geaendert
+					// werden..
+					oldCursor = getWaitCursorComponent().getCursor();
+					getWaitCursorComponent().setCursor(WAIT_CURSOR);
+				}
 
-    try {
-      // if (!seriouseChange) {
-      // LOGGER.info("No seriouse Change => reset = false");
-      // reset= false;
-      // }
-      super.paintComponent(g);
-    } catch (Exception e) {
-      /**
-       * I only need to catch UnknownHostException.. well...
-       */
-      LOGGER
-          .info(
-              "Error during JMapPane printComponent. Probably we are offline and reference some online SVGs?",
-              e);
-    }
-    if (seriouseChange) {
-      resetTransform();
-      if (setWaitCursorDuringNextRepaint) {
-        setWaitCursorDuringNextRepaint = false;
-        if (oldCursor != null)
-          getWaitCursorComponent().setCursor(oldCursor);
-        updateCursor(); // Den Cursor in dieser Componente immer wieder
-        // herstellen
-      }
+				// Den Cursor extra nochmal in dieser COmponente aendern
+				setCursor(WAIT_CURSOR);
+			}
+		}
 
-      /**
-       * Paint an icon in the lower right corner. FeatureRequest: [#717] MapIcon
-       * has long been disabled and should come back
-       */
-      if (mapImage != null && baseImage != null) {
-        baseImage.getGraphics().drawImage(mapImage,
-            baseImage.getWidth() - mapImage.getWidth() - 10,
-            baseImage.getHeight() - mapImage.getHeight() - 10, this);
-        // Repaint with the cached image (fast) which now contains the
-        // logo
-        super.paintComponent(g);
-      }
-    }
+		try {
+			// if (!seriouseChange) {
+			// LOGGER.info("No seriouse Change => reset = false");
+			// reset= false;
+			// }
+			super.paintComponent(g);
+		} catch (Exception e) {
+			/**
+			 * I only need to catch UnknownHostException.. well...
+			 */
+			LOGGER
+					.info(
+							"Error during JMapPane printComponent. Probably we are offline and reference some online SVGs?",
+							e);
+		}
+		if (seriouseChange) {
+			resetTransform();
+			if (setWaitCursorDuringNextRepaint) {
+				setWaitCursorDuringNextRepaint = false;
+				if (oldCursor != null)
+					getWaitCursorComponent().setCursor(oldCursor);
+				updateCursor(); // Den Cursor in dieser Componente immer wieder
+				// herstellen
+			}
 
-  }
+			/**
+			 * Paint an icon in the lower right corner. FeatureRequest: [#717]
+			 * MapIcon has long been disabled and should come back
+			 */
+			if (mapImage != null && baseImage != null) {
+				baseImage
+						.getGraphics()
+						.drawImage(
+								mapImage,
+								baseImage.getWidth() - mapImage.getWidth() - 10,
+								baseImage.getHeight() - mapImage.getHeight()
+										- 10, this);
+				// Repaint with the cached image (fast) which now contains the
+				// logo
+				super.paintComponent(g);
+			}
+		}
 
-  /**
-   * Testet (anhand der Bounding-Box), ob das Objekt eines Layers eine andere
-   * Bounding-Box schneidet. Die Bounding-Box des Layer-Objekts wird zunaechst
-   * in das CRS des MapPanes umgerechnets.
-   * 
-   * @param layer
-   *          ein Layer
-   * @param env
-   *          Bounding-Box in CRS des MapPane
-   */
-  private boolean gridLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
-    try {
-      // BB des Layers umrechnen von Layer-CRS in Map-CRS
-      Envelope bounds_MapCRS = JTSUtil.transformEnvelope(layer
-          .getFeatureSource().getBounds(), layer.getFeatureSource().getSchema()
-          .getGeometryDescriptor().getCoordinateReferenceSystem(), getContext()
-          .getCoordinateReferenceSystem());
+	}
 
-      // TODO warum kann bounds_MapCRS == null sein ?? ?SK fragt martin???
-      if (bounds_MapCRS == null)
-        return false;
+	/**
+	 * Testet (anhand der Bounding-Box), ob das Objekt eines Layers eine andere
+	 * Bounding-Box schneidet. Die Bounding-Box des Layer-Objekts wird zunaechst
+	 * in das CRS des MapPanes umgerechnets.
+	 * 
+	 * @param layer
+	 *            ein Layer
+	 * @param env
+	 *            Bounding-Box in CRS des MapPane
+	 */
+	private boolean gridLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
+		try {
+			// BB des Layers umrechnen von Layer-CRS in Map-CRS
+			Envelope bounds_MapCRS = JTSUtil.transformEnvelope(layer
+					.getFeatureSource().getBounds(), layer.getFeatureSource()
+					.getSchema().getGeometryDescriptor()
+					.getCoordinateReferenceSystem(), getContext()
+					.getCoordinateReferenceSystem());
 
-      return bounds_MapCRS.intersects(env);
-    } catch (Exception err) {
-      return false;
-    }
-  }
+			// TODO warum kann bounds_MapCRS == null sein ?? ?SK fragt martin???
+			if (bounds_MapCRS == null)
+				return false;
 
-  /**
-   * Testet (anhand der Features), ob das Objekt eines Layers eine Bounding-Box
-   * schneidet.
-   * 
-   * @param layer
-   *          ein Layer
-   * @param env
-   *          Bounding-Box in CRS des MapPane
-   */
-  private boolean featureLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
-    try {
-      // // BB umrechnen von Map-CRS in Layer-CRS
-      // Envelope env_LayerCRS = JTSUtil.transformEnvelope(env,
-      // getContext()
-      // .getCoordinateReferenceSystem(), layer.getFeatureSource()
-      // .getSchema().getDefaultGeometry().getCoordinateSystem());
-      // GeometryFilterImpl filter =
-      // createBoundingBoxFilter(env_LayerCRS);
-      // Expression geometry = ff.createAttributeExpression(layer
-      // .getFeatureSource().getSchema().getDefaultGeometry()
-      // .getLocalName());
-      // filter.setExpression1(geometry);
-      FeatureSource<SimpleFeatureType,SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType,SimpleFeature>)layer.getFeatureSource();
-      GeometryFilterImpl filter = new BoundingBoxFilterGenerator(env,
-          getContext().getCoordinateReferenceSystem()).adaptFilter(featureSource);
-      return !layer.getFeatureSource().getFeatures(filter).isEmpty();
-    } catch (Exception err) {
-      return false;
-    }
-  }
+			return bounds_MapCRS.intersects(env);
+		} catch (Exception err) {
+			return false;
+		}
+	}
 
-  /**
-   * Ermittelt alle sichtbaren Features, die einen Filter erfuellen. Beim Modus
-   * {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht. Beim
-   * Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
-   * 
-   * @see #findFeatures(GeometryFilterImpl, int, Envelope)
-   * 
-   * @param filterGenerator
-   *          adapts the filter to a concrete FeatureSource
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
-   */
-  protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> findVisibleFeatures(
-      GeomFilterGenerator filterGenerator, int mode, Envelope env) {
-    Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>>();
-    if (filterGenerator == null)
-      return result;
+	/**
+	 * Testet (anhand der Features), ob das Objekt eines Layers eine
+	 * Bounding-Box schneidet.
+	 * 
+	 * @param layer
+	 *            ein Layer
+	 * @param env
+	 *            Bounding-Box in CRS des MapPane
+	 */
+	private boolean featureLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
+		try {
+			// // BB umrechnen von Map-CRS in Layer-CRS
+			// Envelope env_LayerCRS = JTSUtil.transformEnvelope(env,
+			// getContext()
+			// .getCoordinateReferenceSystem(), layer.getFeatureSource()
+			// .getSchema().getDefaultGeometry().getCoordinateSystem());
+			// GeometryFilterImpl filter =
+			// createBoundingBoxFilter(env_LayerCRS);
+			// Expression geometry = ff.createAttributeExpression(layer
+			// .getFeatureSource().getSchema().getDefaultGeometry()
+			// .getLocalName());
+			// filter.setExpression1(geometry);
+			FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+					.getFeatureSource();
+			GeometryFilterImpl filter = new BoundingBoxFilterGenerator(env,
+					getContext().getCoordinateReferenceSystem())
+					.adaptFilter(featureSource);
+			return !layer.getFeatureSource().getFeatures(filter).isEmpty();
+		} catch (Exception err) {
+			return false;
+		}
+	}
 
-    // Je nach Modus: Alle oder nur das oberste Layer
-    MapContext context = getContext();
-    MapLayer[] layerList = context.getLayers();
-    for (int i = layerList.length - 1; i >= 0; i--) {
-      MapLayer layer = layerList[i];
-      if (!layer.isVisible())
-        continue;
+	/**
+	 * Ermittelt alle sichtbaren Features, die einen Filter erfuellen. Beim
+	 * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+	 * durchsucht.
+	 * 
+	 * @see #findFeatures(GeometryFilterImpl, int, Envelope)
+	 * 
+	 * @param filterGenerator
+	 *            adapts the filter to a concrete FeatureSource
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
+	 */
+	protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> findVisibleFeatures(
+			GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+		Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
+		if (filterGenerator == null)
+			return result;
 
-      if (attributeMetaDataMapCache.containsKey(layer.getTitle())) {
-        /* AttributeMetaData is available... */
-        Map<Integer, AttributeMetaData> amdMap = attributeMetaDataMapCache
-            .get(layer.getTitle());
+		// Je nach Modus: Alle oder nur das oberste Layer
+		MapContext context = getContext();
+		MapLayer[] layerList = context.getLayers();
+		for (int i = layerList.length - 1; i >= 0; i--) {
+			MapLayer layer = layerList[i];
+			if (!layer.isVisible())
+				continue;
 
-        if (StyledLayerUtil.getVisibleAttributeMetaData(amdMap, true).size() == 0) {
-          LOGGER.debug("Ignoring layer " + layer.getTitle()
-              + " because it has no visible attributes");
-          continue;
-        }
-      }
+			if (attributeMetaDataMapCache.containsKey(layer.getTitle())) {
+				/* AttributeMetaData is available... */
+				Map<Integer, AttributeMetaData> amdMap = attributeMetaDataMapCache
+						.get(layer.getTitle());
 
-      LOGGER.debug("mode = " + mode);
+				if (StyledLayerUtil.getVisibleAttributeMetaData(amdMap, true)
+						.size() == 0) {
+					LOGGER.debug("Ignoring layer " + layer.getTitle()
+							+ " because it has no visible attributes");
+					continue;
+				}
+			}
 
-      /*
-       * SK: Change! If AttributeMetadata is provided, we check whether any
-       * attribute is
-       */
+			LOGGER.debug("mode = " + mode);
 
-      // Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
-      // im obersten (sichtbaren) Layer gesucht wird.
-      // Ansonsten Raster-Layer einfach uebergehen.
-      if (isGridCoverageLayer(layer)) {
-        if (mode == SELECT_TOP && gridLayerIntersectsEnvelope(layer, env))
-          break;
-        continue;
-      }
+			/*
+			 * SK: Change! If AttributeMetadata is provided, we check whether
+			 * any attribute is
+			 */
 
-      // Filter an Layer koppeln
-      // WICHTIG: Dies darf erst geschehen, NACHDEM das
-      // Schleifen-Abbruch-Kriterium
-      // fuer die Raster-Layer geprueft wurde!!
-      // Werden folgende Zeilen naemlich auf das FeatureSource des
-      // Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
-      // zusammen und auch die ZUVOR gefilterten FeatureCollections,
-      // sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
-      final FeatureSource<SimpleFeatureType,SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType,SimpleFeature>)layer.getFeatureSource();
-      final GeometryFilterImpl distancefilter = filterGenerator
-          .adaptFilter(featureSource);
+			// Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
+			// im obersten (sichtbaren) Layer gesucht wird.
+			// Ansonsten Raster-Layer einfach uebergehen.
+			if (isGridCoverageLayer(layer)) {
+				if (mode == SELECT_TOP
+						&& gridLayerIntersectsEnvelope(layer, env))
+					break;
+				continue;
+			}
 
-      /**
-       * 8.8.2008: SK Wenn für das Layer auch ein Filter aktiv ist, dann soll
-       * dieser mit AND an den distanceFilter gebunden werden. "Filter filter"
-       * ist entweder der distanceFilter oder (distanceFilter AND layerFilter)
-       */
-      Filter filter = distancefilter;
-      if (layer.getQuery() != null) {
-        final Filter layerFilter = layer.getQuery().getFilter();
-        if (layerFilter != null) {
-          filter = distancefilter.and(layerFilter);
-        }
-      }
+			// Filter an Layer koppeln
+			// WICHTIG: Dies darf erst geschehen, NACHDEM das
+			// Schleifen-Abbruch-Kriterium
+			// fuer die Raster-Layer geprueft wurde!!
+			// Werden folgende Zeilen naemlich auf das FeatureSource des
+			// Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
+			// zusammen und auch die ZUVOR gefilterten FeatureCollections,
+			// sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+					.getFeatureSource();
+			final GeometryFilterImpl distancefilter = filterGenerator
+					.adaptFilter(featureSource);
 
-      try {
-        // Filter auf Layer des Features anwenden
-        // FeatureCollection fc = layer.getFeatureSource().getFeatures(
-        // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
-        // FeatureCollection fc = featureSource.getFeatures(
-        // distancefilter );
-        FeatureCollection<SimpleFeatureType,SimpleFeature> fc = featureSource.getFeatures(filter);
+			/**
+			 * 8.8.2008: SK Wenn für das Layer auch ein Filter aktiv ist, dann
+			 * soll dieser mit AND an den distanceFilter gebunden werden.
+			 * "Filter filter" ist entweder der distanceFilter oder
+			 * (distanceFilter AND layerFilter)
+			 */
+			Filter filter = distancefilter;
+			if (layer.getQuery() != null) {
+				final Filter layerFilter = layer.getQuery().getFilter();
+				if (layerFilter != null) {
+					filter = distancefilter.and(layerFilter);
+				}
+			}
 
-        LOGGER.info("Crazy finsvisible features position reached");
+			try {
+				// Filter auf Layer des Features anwenden
+				// FeatureCollection fc = layer.getFeatureSource().getFeatures(
+				// FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
+				// FeatureCollection fc = featureSource.getFeatures(
+				// distancefilter );
+				FeatureCollection<SimpleFeatureType, SimpleFeature> fc = featureSource
+						.getFeatures(filter);
 
-        // Liefert eine FeatureCollection zurück, in welcher nur
-        // Features enthalten sind, welche bei der aktuellen
-        // Anzeigeskala aufgrund des Styles gerendert werden.
-        if (layer.getTitle().equals("vector_afrikan_countries_00040984322")) {
-          LOGGER
-              .warn("Cancelling here to avoid infinite loop in ShapefileReader.ensureCapacity(ByteBuffer, int, boolean) line: 203.");
-          LOGGER
-              .warn("Calling isEmpty() or getSize() in GT2.4.5 the ShapefileReader-Class enters infinite loop here for the here for layer vector_afrikan_countries_00040984322. It seems to be specific for this special ShapeFile. Canelling the operation here is a very ugly and very static work-arround. Hopefully this problem vanishes with GT 2.5");
-          continue;
-        }
+				LOGGER.info("Crazy finsvisible features position reached");
 
-        // @Martin Using size() produces the same problem
-        if (!fc.isEmpty()) {
-          fc = filterSLDVisibleOnly(fc, layer.getStyle());
+				// Liefert eine FeatureCollection zurück, in welcher nur
+				// Features enthalten sind, welche bei der aktuellen
+				// Anzeigeskala aufgrund des Styles gerendert werden.
+				if (layer.getTitle().equals(
+						"vector_afrikan_countries_00040984322")) {
+					LOGGER
+							.warn("Cancelling here to avoid infinite loop in ShapefileReader.ensureCapacity(ByteBuffer, int, boolean) line: 203.");
+					LOGGER
+							.warn("Calling isEmpty() or getSize() in GT2.4.5 the ShapefileReader-Class enters infinite loop here for the here for layer vector_afrikan_countries_00040984322. It seems to be specific for this special ShapeFile. Canelling the operation here is a very ugly and very static work-arround. Hopefully this problem vanishes with GT 2.5");
+					continue;
+				}
 
-          if (!fc.isEmpty()) {
-            result.put(layer, fc);
-            // Beim Modus "oberstes Layer selektieren" die Schleife
-            // beenden
-            if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-              break;
-          }
+				// @Martin Using size() produces the same problem
+				if (!fc.isEmpty()) {
+					fc = filterSLDVisibleOnly(fc, layer.getStyle());
 
-        }
-      } catch (IOException err) {
-        LOGGER.error("applying the distanceWithin filter", err);
-      }
+					if (!fc.isEmpty()) {
+						result.put(layer, fc);
+						// Beim Modus "oberstes Layer selektieren" die Schleife
+						// beenden
+						if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+							break;
+					}
 
-      // for ( FeatureCollection fc1 : result.values() )
-      // LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
-    }
-    // for ( FeatureCollection fc1 : result.values() )
-    // LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
+				}
+			} catch (IOException err) {
+				LOGGER.error("applying the distanceWithin filter", err);
+			}
 
-    return result;
-  }
+			// for ( FeatureCollection fc1 : result.values() )
+			// LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
+		}
+		// for ( FeatureCollection fc1 : result.values() )
+		// LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
 
-  /**
-   * Ermittelt alle Features, die einen Filter erfuellen. Beim Modus
-   * {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht. Beim
-   * Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
-   * 
-   * 17.4.08, Stefan
-   * 
-   * @param filter
-   *          Filter
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
-   */
-  protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> findFeatures(
-      GeomFilterGenerator filterGenerator, int mode, Envelope env) {
-    Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>>();
-    if (filterGenerator == null)
-      return result;
+		return result;
+	}
 
-    // Je nach Modus: Alle oder nur das oberste Layer
-    MapContext context = getContext();
-    MapLayer[] layerList = context.getLayers();
-    for (int i = layerList.length - 1; i >= 0; i--) {
-      MapLayer layer = layerList[i];
-      if (!layer.isVisible())
-        continue;
+	/**
+	 * Ermittelt alle Features, die einen Filter erfuellen. Beim Modus
+	 * {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht. Beim
+	 * Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
+	 * 
+	 * 17.4.08, Stefan
+	 * 
+	 * @param filter
+	 *            Filter
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
+	 */
+	protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> findFeatures(
+			GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+		Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
+		if (filterGenerator == null)
+			return result;
 
-      // Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
-      // im
-      // obersten (sichtbaren) Layer gesucht
-      // wird.AbstractGridCoverage2DReader
-      // Ansonsten Raster-Layer einfach uebergehen.
-      if (isGridCoverageLayer(layer)) {
-        if (mode == SELECT_TOP && gridLayerIntersectsEnvelope(layer, env))
-          break;
-        continue;
-      }
+		// Je nach Modus: Alle oder nur das oberste Layer
+		MapContext context = getContext();
+		MapLayer[] layerList = context.getLayers();
+		for (int i = layerList.length - 1; i >= 0; i--) {
+			MapLayer layer = layerList[i];
+			if (!layer.isVisible())
+				continue;
 
-      // Filter an Layer koppeln
-      // WICHTIG: Dies darf erst geschehen, NACHDEM das
-      // Schleifen-Abbruch-Kriterium
-      // fuer die Raster-Layer geprueft wurde!!
-      // Werden folgende Zeilen naemlich auf das FeatureSource des
-      // Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
-      // zusammen und auch die ZUVOR gefilterten FeatureCollections,
-      // sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
-      final FeatureSource<SimpleFeatureType,SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType,SimpleFeature>)layer.getFeatureSource();
-      final GeometryFilterImpl filter = filterGenerator
-          .adaptFilter(featureSource);
+			// Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
+			// im
+			// obersten (sichtbaren) Layer gesucht
+			// wird.AbstractGridCoverage2DReader
+			// Ansonsten Raster-Layer einfach uebergehen.
+			if (isGridCoverageLayer(layer)) {
+				if (mode == SELECT_TOP
+						&& gridLayerIntersectsEnvelope(layer, env))
+					break;
+				continue;
+			}
 
-      try {
-        // Filter auf Layer des Features anwenden
-        // FeatureCollection fc = layer.getFeatureSource().getFeatures(
-        // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
-        FeatureCollection<SimpleFeatureType,SimpleFeature> fc = featureSource.getFeatures(filter);
+			// Filter an Layer koppeln
+			// WICHTIG: Dies darf erst geschehen, NACHDEM das
+			// Schleifen-Abbruch-Kriterium
+			// fuer die Raster-Layer geprueft wurde!!
+			// Werden folgende Zeilen naemlich auf das FeatureSource des
+			// Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
+			// zusammen und auch die ZUVOR gefilterten FeatureCollections,
+			// sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+					.getFeatureSource();
+			final GeometryFilterImpl filter = filterGenerator
+					.adaptFilter(featureSource);
 
-        // Liefert eine FeatureCollection zurück, in welcher nur
-        // Features enthalten sind, welche bei der aktuellen
-        // Anzeigeskala aufgrund des Styles gerendert werden.
-        fc = filterSLDVisibleOnly(fc, layer.getStyle());
+			try {
+				// Filter auf Layer des Features anwenden
+				// FeatureCollection fc = layer.getFeatureSource().getFeatures(
+				// FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
+				FeatureCollection<SimpleFeatureType, SimpleFeature> fc = featureSource
+						.getFeatures(filter);
 
-        if (!fc.isEmpty()) {
-          result.put(layer, fc);
-          // Beim Modus "oberstes Layer selektieren" die Schleife
-          // jetzt beenden, da wir sichtbare Features gefunden haben.
-          if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-            break;
-        }
-      } catch (Exception err) {
-        LOGGER.error("Looking for features:", err);
-      }
+				// Liefert eine FeatureCollection zurück, in welcher nur
+				// Features enthalten sind, welche bei der aktuellen
+				// Anzeigeskala aufgrund des Styles gerendert werden.
+				fc = filterSLDVisibleOnly(fc, layer.getStyle());
 
-      // for ( FeatureCollection fc1 : result.values() )
-      // LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
-    }
-    // for ( FeatureCollection fc1 : result.values() )
-    // LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
+				if (!fc.isEmpty()) {
+					result.put(layer, fc);
+					// Beim Modus "oberstes Layer selektieren" die Schleife
+					// jetzt beenden, da wir sichtbare Features gefunden haben.
+					if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+						break;
+				}
+			} catch (Exception err) {
+				LOGGER.error("Looking for features:", err);
+			}
 
-    return result;
-  }
+			// for ( FeatureCollection fc1 : result.values() )
+			// LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
+		}
+		// for ( FeatureCollection fc1 : result.values() )
+		// LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
 
-  /**
-   * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
-   * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
-   * werden.
-   * 
-   * @param fc
-   *          Die zu filternde FeatureCollection. Diese wird nicht verändert.
-   * @param style
-   *          Der Style, mit dem die Features gerendert werden (z.b.
-   *          layer.getStyle() )
-   * 
-   * @return Eine FeatureCollection in welcher nur die Features enthalten sind,
-   *         welche bei aktuellen Scale mit dem übergebenen Style gerendert
-   *         werden.
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  private MemoryFeatureCollection filterSLDVisibleOnly(
-      final FeatureCollection<SimpleFeatureType,SimpleFeature> fc, final Style style) {
+		return result;
+	}
 
-    // Der "scaleDenominator" der aktuellen JMapPane
-    Double scaleDenominator = RendererUtilities.calculateOGCScale(
-        new ReferencedEnvelope(getMapArea(), getContext()
-            .getCoordinateReferenceSystem()), getSize().width, null);
+	/**
+	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
+	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
+	 * werden.
+	 * 
+	 * @param fc
+	 *            Die zu filternde FeatureCollection. Diese wird nicht
+	 *            verändert.
+	 * @param style
+	 *            Der Style, mit dem die Features gerendert werden (z.b.
+	 *            layer.getStyle() )
+	 * 
+	 * @return Eine FeatureCollection in welcher nur die Features enthalten
+	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
+	 *         gerendert werden.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	private MemoryFeatureCollection filterSLDVisibleOnly(
+			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+			final Style style) {
 
-    return StylingUtil.filterSLDVisibleOnly(fc, style, scaleDenominator);
-  }
+		// Der "scaleDenominator" der aktuellen JMapPane
+		Double scaleDenominator = RendererUtilities
+				.calculateOGCScale(new ReferencedEnvelope(getMapArea(),
+						getContext().getCoordinateReferenceSystem()),
+						getSize().width, null);
 
-  /**
-   * Ermittelt alle Features, die in einem Bereich liegen und erzeugt
-   * entsprechende {@link FeatureSelectedEvent FeatureSelectedEvents}. Beim
-   * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht.
-   * Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
-   * 
-   * @param filterGenerator
-   *          adapts a filter to a concrete {@link FeatureSource}
-   * @param mode
-   *          Suchmodus
-   * @param env
-   *          Bereich der durchsucht wird (fuer das Filtern irrelevant; wird nur
-   *          fuer Events benoetigt!)
-   */
-  protected boolean findFeaturesAndFireEvents(
-      GeomFilterGenerator filterGenerator, int mode, Envelope env) {
-    Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,SimpleFeature>> result = findVisibleFeatures(
-        filterGenerator, mode, env);
+		return StylingUtil.filterSLDVisibleOnly(fc, style, scaleDenominator);
+	}
 
-    // Events ausloesen fuer jedes Layer
-    for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-      final MapLayer layer = e.nextElement();
-      final FeatureCollection<SimpleFeatureType,SimpleFeature> fc = result.get(layer);
-      if (fc != null && !fc.isEmpty())
-        fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
-    }
-    return !result.isEmpty();
-  }
+	/**
+	 * Ermittelt alle Features, die in einem Bereich liegen und erzeugt
+	 * entsprechende {@link FeatureSelectedEvent FeatureSelectedEvents}. Beim
+	 * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+	 * durchsucht.
+	 * 
+	 * @param filterGenerator
+	 *            adapts a filter to a concrete {@link FeatureSource}
+	 * @param mode
+	 *            Suchmodus
+	 * @param env
+	 *            Bereich der durchsucht wird (fuer das Filtern irrelevant; wird
+	 *            nur fuer Events benoetigt!)
+	 */
+	protected boolean findFeaturesAndFireEvents(
+			GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+		Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = findVisibleFeatures(
+				filterGenerator, mode, env);
 
-  /**
-   * Ermittelt alle Teil-Raster, die in einem Bereich liegen.
-   * BefindFeaturesAndFireEventsim Modus {@link #SELECT_TOP} wird nur das
-   * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
-   * alle sichtbaren Layer durchsucht.
-   * 
-   * @param env
-   *          Bounding-Box
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
-   *         ist
-   */
-  protected Hashtable<MapLayer, GridCoverage2D> findGridCoverageSubsets(
-      Envelope env, int mode) {
-    Hashtable<MapLayer, GridCoverage2D> result = new Hashtable<MapLayer, GridCoverage2D>();
-    if (env == null)
-      return result;
+		// Events ausloesen fuer jedes Layer
+		for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+			final MapLayer layer = e.nextElement();
+			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
+					.get(layer);
+			if (fc != null && !fc.isEmpty())
+				fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
+		}
+		return !result.isEmpty();
+	}
 
-    MapContext context = getContext();
-    // Je nach Modus: Alle oder nur das oberste Layer
-    MapLayer[] layerList = context.getLayers();
-    for (int i = layerList.length - 1; i >= 0; i--) {
-      MapLayer layer = layerList[i];
-      Object layerObj = getLayerSourceObject(layer);
-      if (!layer.isVisible())
-        continue;
+	/**
+	 * Ermittelt alle Teil-Raster, die in einem Bereich liegen.
+	 * BefindFeaturesAndFireEventsim Modus {@link #SELECT_TOP} wird nur das
+	 * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
+	 * alle sichtbaren Layer durchsucht.
+	 * 
+	 * @param env
+	 *            Bounding-Box
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
+	 *         ist
+	 */
+	protected Hashtable<MapLayer, GridCoverage2D> findGridCoverageSubsets(
+			Envelope env, int mode) {
+		Hashtable<MapLayer, GridCoverage2D> result = new Hashtable<MapLayer, GridCoverage2D>();
+		if (env == null)
+			return result;
 
-      // Bei einem Nicht-Raster-Layer, das die BB schneidet, abbrechen,
-      // wenn nur im obersten (sichtbaren) Layer gesucht wird.
-      // Ansonsten Nicht-Raster-Layer einfach uebergehen.
-      if (!(layerObj instanceof GridCoverage2D)) {
-        if ((mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-            && featureLayerIntersectsEnvelope(layer, env))
-          break;
-        continue;
-      }
+		MapContext context = getContext();
+		// Je nach Modus: Alle oder nur das oberste Layer
+		MapLayer[] layerList = context.getLayers();
+		for (int i = layerList.length - 1; i >= 0; i--) {
+			MapLayer layer = layerList[i];
+			Object layerObj = getLayerSourceObject(layer);
+			if (!layer.isVisible())
+				continue;
 
-      GridCoverage2D sourceGrid = (GridCoverage2D) layerObj;
-      com.vividsolutions.jts.geom.Envelope jtsEnv = env;
-      org.geotools.geometry.Envelope2D gtEnv2D = JTS.getEnvelope2D(jtsEnv,
-          sourceGrid.getCoordinateReferenceSystem());
-      // org.opengis.spatialschema.geometry.Envelope gtGenEnv = new
-      // GeneralEnvelope
-      // ((org.opengis.spatialschema.geometry.Envelope)gtEnv2D); //
-      // gt2-2.3.4
-      org.opengis.geometry.Envelope gtGenEnv = new GeneralEnvelope(
-          (org.opengis.geometry.Envelope) gtEnv2D); // gt2-2.4.2
+			// Bei einem Nicht-Raster-Layer, das die BB schneidet, abbrechen,
+			// wenn nur im obersten (sichtbaren) Layer gesucht wird.
+			// Ansonsten Nicht-Raster-Layer einfach uebergehen.
+			if (!(layerObj instanceof GridCoverage2D)) {
+				if ((mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+						&& featureLayerIntersectsEnvelope(layer, env))
+					break;
+				continue;
+			}
 
-      // GridCoverage2D subsetGrid =
-      // (GridCoverage2D)Operations.DEFAULT.crop(sourceGrid,gtGenEnv);
-      GridCoverage2D subsetGrid = GridUtil.createGridCoverage(sourceGrid,
-          gtGenEnv);
-      if (subsetGrid != null)
-        result.put(layer, subsetGrid);
-      // Beim Modus "oberstes Layer selektieren" die Schleife beenden
-      if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-        break;
-    }
-    return result;
-  }
+			GridCoverage2D sourceGrid = (GridCoverage2D) layerObj;
+			com.vividsolutions.jts.geom.Envelope jtsEnv = env;
+			org.geotools.geometry.Envelope2D gtEnv2D = JTS.getEnvelope2D(
+					jtsEnv, sourceGrid.getCoordinateReferenceSystem());
+			// org.opengis.spatialschema.geometry.Envelope gtGenEnv = new
+			// GeneralEnvelope
+			// ((org.opengis.spatialschema.geometry.Envelope)gtEnv2D); //
+			// gt2-2.3.4
+			org.opengis.geometry.Envelope gtGenEnv = new GeneralEnvelope(
+					(org.opengis.geometry.Envelope) gtEnv2D); // gt2-2.4.2
 
-  /**
-   * Ermittelt alle Teil-Raster, die in einem Bereich liegen und erzeugt
-   * entsprechende {@link GridCoverageSelectedEvent GridCoverageSelectedEvents}.
-   * Beim Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
-   * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
-   * durchsucht.
-   * 
-   * @param env
-   *          Bounding-Box
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
-   *         ist
-   */
-  protected boolean findGridCoverageSubsetsAndFireEvents(final Envelope env,
-      final int mode) {
-    final Hashtable<MapLayer, GridCoverage2D> result = findGridCoverageSubsets(
-        env, mode);
-    // Events ausloesen fuer jedes Layer
-    for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-      final MapLayer layer = e.nextElement();
-      final GridCoverage2D subset = result.get(layer);
-      if (subset != null)
-        fireMapPaneEvent(new GridCoverageSelectedEvent(this, layer, env, subset));
-    }
-    return !result.isEmpty();
-  }
+			// GridCoverage2D subsetGrid =
+			// (GridCoverage2D)Operations.DEFAULT.crop(sourceGrid,gtGenEnv);
+			GridCoverage2D subsetGrid = GridUtil.createGridCoverage(sourceGrid,
+					gtGenEnv);
+			if (subsetGrid != null)
+				result.put(layer, subsetGrid);
+			// Beim Modus "oberstes Layer selektieren" die Schleife beenden
+			if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+				break;
+		}
+		return result;
+	}
 
-  /**
-   * Ermittelt alle Raster-Werte, die an einer bestimmten Geo-Position liegen.
-   * Beim Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
-   * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
-   * durchsucht.
-   * <p>
-   * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
-   * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
-   * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
-   * 
-   * @param point
-   *          Geo-Referenzgeop
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls keine Werte ermittelt werden
-   *         konnten
-   * 
-   * @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&uuml;ger</a>
-   */
-  protected Hashtable<MapLayer, double[]> findGridCoverageValues(Point2D point,
-      int mode) {
-    Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
+	/**
+	 * Ermittelt alle Teil-Raster, die in einem Bereich liegen und erzeugt
+	 * entsprechende {@link GridCoverageSelectedEvent
+	 * GridCoverageSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur das
+	 * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
+	 * alle sichtbaren Layer durchsucht.
+	 * 
+	 * @param env
+	 *            Bounding-Box
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
+	 *         ist
+	 */
+	protected boolean findGridCoverageSubsetsAndFireEvents(final Envelope env,
+			final int mode) {
+		final Hashtable<MapLayer, GridCoverage2D> result = findGridCoverageSubsets(
+				env, mode);
+		// Events ausloesen fuer jedes Layer
+		for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+			final MapLayer layer = e.nextElement();
+			final GridCoverage2D subset = result.get(layer);
+			if (subset != null)
+				fireMapPaneEvent(new GridCoverageSelectedEvent(this, layer,
+						env, subset));
+		}
+		return !result.isEmpty();
+	}
 
-    if (point == null)
-      return result;
+	/**
+	 * Ermittelt alle Raster-Werte, die an einer bestimmten Geo-Position liegen.
+	 * Beim Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+	 * durchsucht.
+	 * <p>
+	 * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
+	 * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
+	 * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
+	 * 
+	 * @param point
+	 *            Geo-Referenzgeop
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls keine Werte ermittelt werden
+	 *         konnten
+	 * 
+	 * @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&uuml;ger</a>
+	 */
+	protected Hashtable<MapLayer, double[]> findGridCoverageValues(
+			Point2D point, int mode) {
+		Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
 
-    MapContext context = getContext();
-    // Je nach Modus: Alle oder nur das oberste Layer
-    MapLayer[] layerList = context.getLayers();
-    for (int i = layerList.length - 1; i >= 0; i--) {
-      MapLayer layer = layerList[i];
-      if (!layer.isVisible())
-        continue;
-      Object layerObj = getLayerSourceObject(layer);
+		if (point == null)
+			return result;
 
-      // LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
+		MapContext context = getContext();
+		// Je nach Modus: Alle oder nur das oberste Layer
+		MapLayer[] layerList = context.getLayers();
+		for (int i = layerList.length - 1; i >= 0; i--) {
+			MapLayer layer = layerList[i];
+			if (!layer.isVisible())
+				continue;
+			Object layerObj = getLayerSourceObject(layer);
 
-      // SK 29.9.2007 Vorher:
-      // // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
-      // abbrechen, wenn nur im
-      // // obersten (sichtbaren) Layer gesucht wird.
-      // // Ansonsten Nicht-Raster-Layer einfach uebergehen.
-      // if ( !(layerObj instanceof GridCoverage2D) ) {
-      // if ( mode == SELECT_TOP &&
-      // featureLayerIntersectsEnvelope(layer,new
-      // Envelope(point.getX(),point.getX(),point.getY(),point.getY())) )
-      // break;
-      // continue;
-      // }
+			// LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
 
-      // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
-      // abbrechen, wenn nur im
-      // obersten (sichtbaren) Layer gesucht wird.
-      // Ansonsten Nicht-Raster-Layer einfach uebergehen.
-      // SK 29.9.07: Ein AbstractGridCoverage2DReader ist auch ein Raster
-      if (!(layerObj instanceof GridCoverage2D || layerObj instanceof AbstractGridCoverage2DReader)) {
-        final Envelope pointAsEnvelope = new Envelope(point.getX(), point
-            .getX(), point.getY(), point.getY());
-        if (mode == SELECT_TOP
-            && featureLayerIntersectsEnvelope(layer, pointAsEnvelope)) {
-        }
-        continue;
-      }
+			// SK 29.9.2007 Vorher:
+			// // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
+			// abbrechen, wenn nur im
+			// // obersten (sichtbaren) Layer gesucht wird.
+			// // Ansonsten Nicht-Raster-Layer einfach uebergehen.
+			// if ( !(layerObj instanceof GridCoverage2D) ) {
+			// if ( mode == SELECT_TOP &&
+			// featureLayerIntersectsEnvelope(layer,new
+			// Envelope(point.getX(),point.getX(),point.getY(),point.getY())) )
+			// break;
+			// continue;
+			// }
 
-      GridCoverage2D sourceGrid;
+			// Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
+			// abbrechen, wenn nur im
+			// obersten (sichtbaren) Layer gesucht wird.
+			// Ansonsten Nicht-Raster-Layer einfach uebergehen.
+			// SK 29.9.07: Ein AbstractGridCoverage2DReader ist auch ein Raster
+			if (!(layerObj instanceof GridCoverage2D || layerObj instanceof AbstractGridCoverage2DReader)) {
+				final Envelope pointAsEnvelope = new Envelope(point.getX(),
+						point.getX(), point.getY(), point.getY());
+				if (mode == SELECT_TOP
+						&& featureLayerIntersectsEnvelope(layer,
+								pointAsEnvelope)) {
+				}
+				continue;
+			}
 
-      if (layerObj instanceof AbstractGridCoverage2DReader) {
-        // LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
-        // );
-        AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
-        Parameter readGG = new Parameter(AbstractGridFormat.READ_GRIDGEOMETRY2D);
+			GridCoverage2D sourceGrid;
 
-        ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
-            mapArea, context.getCoordinateReferenceSystem());
+			if (layerObj instanceof AbstractGridCoverage2DReader) {
+				// LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
+				// );
+				AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
+				Parameter readGG = new Parameter(
+						AbstractGridFormat.READ_GRIDGEOMETRY2D);
 
-        readGG.setValue(new GridGeometry2D(
-            new GeneralGridEnvelope(getBounds()), mapExtend));
+				ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
+						mapArea, context.getCoordinateReferenceSystem());
 
-        try {
-          sourceGrid = (GridCoverage2D) reader
-              .read(new GeneralParameterValue[] { readGG });
-        } catch (Exception e) {
-          LOGGER.error("read(new GeneralParameterValue[] { readGG })", e);
-          continue;
-        }
-      } else {
-        // Ein instanceof ist nicht noetig, da sonst schon break oder
-        // continue aufgerufen worden waere
-        sourceGrid = (GridCoverage2D) layerObj;
-      }
+				readGG.setValue(new GridGeometry2D(new GeneralGridEnvelope(
+						getBounds()), mapExtend));
 
-      // vorher: double[] value = new double[2];
+				try {
+					sourceGrid = (GridCoverage2D) reader
+							.read(new GeneralParameterValue[] { readGG });
+				} catch (Exception e) {
+					LOGGER.error(
+							"read(new GeneralParameterValue[] { readGG })", e);
+					continue;
+				}
+			} else {
+				// Ein instanceof ist nicht noetig, da sonst schon break oder
+				// continue aufgerufen worden waere
+				sourceGrid = (GridCoverage2D) layerObj;
+			}
 
-      // getNumSampleDimensions gibt die Anzahl der Baender des Rasters
-      // zurueck.
-      double[] values = new double[sourceGrid.getNumSampleDimensions()];
+			// vorher: double[] value = new double[2];
 
-      try {
-        // Grid an Geo-Position auswerten
-        sourceGrid.evaluate(point, values);
-      } catch (CannotEvaluateException err) {
-        // z.B. Punkt ausserhalb des Rasters --> Layer uebergehen
-        continue;
-      } catch (Exception e) {
-        LOGGER.error("sourceGrid.evaluate(point, values);", e);
-        continue;
-      }
+			// getNumSampleDimensions gibt die Anzahl der Baender des Rasters
+			// zurueck.
+			double[] values = new double[sourceGrid.getNumSampleDimensions()];
 
-      // SK: voher wurde nur der erste Wert zurueckgegeben
-      // result.put(layer,value[0]);
-      // jetzt werden alle werte zueuckgegeben
+			try {
+				// Grid an Geo-Position auswerten
+				sourceGrid.evaluate(point, values);
+			} catch (CannotEvaluateException err) {
+				// z.B. Punkt ausserhalb des Rasters --> Layer uebergehen
+				continue;
+			} catch (Exception e) {
+				LOGGER.error("sourceGrid.evaluate(point, values);", e);
+				continue;
+			}
 
-      result.put(layer, values);
-      // Beim Modus "oberstes Layer selektieren" die Schleife beenden
-      if (mode == SELECT_TOP)
-        break;
-    }
-    return result;
-  }
+			// SK: voher wurde nur der erste Wert zurueckgegeben
+			// result.put(layer,value[0]);
+			// jetzt werden alle werte zueuckgegeben
 
-  /**
-   * Ermittelt die Raster-Werte, die an einem Punkt liegen und erzeugt
-   * entsprechende {@link GridCoverageValueSelectedEvent
-   * GridCoverageValueSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur
-   * das oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL}
-   * werden alle sichtbaren Layer durchsucht.
-   * <p>
-   * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
-   * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
-   * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
-   * 
-   * @param point
-   *          Geo-Referenz
-   * @param mode
-   *          Suchmodus
-   * @return eine leere {@link Hashtable} falls der Punkt {@code null} ist
-   * 
-   * @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&uuml;ger</a>
-   */
-  protected boolean findGridCoverageValuesAndFireEvents(Point2D point, int mode) {
-    Hashtable<MapLayer, double[]> result = findGridCoverageValues(point, mode);
+			result.put(layer, values);
+			// Beim Modus "oberstes Layer selektieren" die Schleife beenden
+			if (mode == SELECT_TOP)
+				break;
+		}
+		return result;
+	}
 
-    // Events ausloesen fuer jedes Layer
-    for (Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-      MapLayer layer = e.nextElement();
-      double[] values = result.get(layer);
-      fireMapPaneEvent(new GridCoverageValueSelectedEvent(this, layer, point,
-          values));
-    }
-    return !result.isEmpty();
-  }
+	/**
+	 * Ermittelt die Raster-Werte, die an einem Punkt liegen und erzeugt
+	 * entsprechende {@link GridCoverageValueSelectedEvent
+	 * GridCoverageValueSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur
+	 * das oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL}
+	 * werden alle sichtbaren Layer durchsucht.
+	 * <p>
+	 * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
+	 * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
+	 * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
+	 * 
+	 * @param point
+	 *            Geo-Referenz
+	 * @param mode
+	 *            Suchmodus
+	 * @return eine leere {@link Hashtable} falls der Punkt {@code null} ist
+	 * 
+	 * @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&uuml;ger</a>
+	 */
+	protected boolean findGridCoverageValuesAndFireEvents(Point2D point,
+			int mode) {
+		Hashtable<MapLayer, double[]> result = findGridCoverageValues(point,
+				mode);
 
-  // /**
-  // * Bereitet einen BoundingBox-Filter vor. Das "linke" Attribut der
-  // * Expression (das SimpleFeature-Attribut, auf das der Filter angewendet
-  // wird),
-  // * wird dabei noch nicht belegt. Dies geschieht erst bei der Auswertung
-  // * entsprechend des jeweiligen Layers
-  // *
-  // * @param env
-  // * Bounding-Box
-  // */
-  // private static GeometryFilterImpl createBoundingBoxFilter(Envelope env) {
-  // // Filter fuer Envelope zusammenstellen
-  // Expression bbox = ff.createBBoxExpression(env);
-  // GeometryFilterImpl bboxFilter = (GeometryFilterImpl) ff
-  // .createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
-  // // GeometryFilterImpl bboxFilter =
-  // // (GeometryFilterImpl)ff.createGeometryFilter
-  // // (AbstractFilter.GEOMETRY_WITHIN);
-  // bboxFilter.setExpression2(bbox);
-  // return bboxFilter;
-  // }
-  //
-  // /**
-  // * Bereitet einen Punkt-Filter vor. Das "linke" Attribut der Expression
-  // (das
-  // * SimpleFeature-Attribut, auf das der Filter angewendet wird), wird dabei
-  // noch
-  // * nicht belegt. Dies geschieht erst bei der Auswertung entsprechend des
-  // * jeweiligen Layers
-  // *
-  // * @param point
-  // * Geo-Koordinate
-  // */
-  // private static GeometryFilterImpl createPointFilter(Point2D point) {
-  // // Filter fuer Envelope zusammenstellen
-  // Geometry geometry = gf.createPoint(new Coordinate(point.getX(), point
-  // .getY()));
-  // GeometryFilterImpl pointFilter = (GeometryFilterImpl) ff
-  // .createGeometryFilter(GeometryFilterImpl.GEOMETRY_CONTAINS);
-  // pointFilter.setExpression2(ff.createLiteralExpression(geometry));
-  // return pointFilter;
-  // }
-  //
-  // /**
-  // * Bereitet einen "InDerNaehe von" Distance-Filter vor. Das "linke"
-  // Attribut
-  // * der Expression (das SimpleFeature-Attribut, auf das der Filter angewendet
-  // * wird), wird dabei noch nicht belegt. Dies geschieht erst bei der
-  // * Auswertung entsprechend des jeweiligen Layers
-  // *
-  // * Wird benoetigt, um mit der Maus einen Punkt zu treffen.
-  // *
-  // * @param point
-  // * Geo-Koordinate
-  // * @param dist
-  // * Distanz zum Punkt in Einheiten des Layers
-  // *
-  // * TODO SK Auf FilterFactory2 ändern... Beispiel von
-  // * http://docs.codehaus.org/display/GEOTDOC/Filter+Examples
-  // * funktioniert erst ab 2.5 ?? Vor dem Distcheck einen BBOX check
-  // * sollte die geschwindigkeit erhöhen.
-  // *
-  // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-  // * Kr&uuml;ger</a>
-  // */
-  // private static GeometryFilterImpl createNearPointFilter(
-  // final Point2D point, final Double dist) {
-  // // Filter fuer Envelope zusammenstellen
-  // final Geometry geometry = gf.createPoint(new Coordinate(point.getX(),
-  // point.getY()));
-  //
-  // final DWithinImpl dwithinFilter = (DWithinImpl) ff
-  // .createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
-  //
-  // dwithinFilter.setDistance(dist);
-  //
-  // dwithinFilter.setExpression2(ff.createLiteralExpression(geometry));
-  //
-  // return dwithinFilter;
-  // }
+		// Events ausloesen fuer jedes Layer
+		for (Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+			MapLayer layer = e.nextElement();
+			double[] values = result.get(layer);
+			fireMapPaneEvent(new GridCoverageValueSelectedEvent(this, layer,
+					point, values));
+		}
+		return !result.isEmpty();
+	}
 
-  /**
-   * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
-   * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-   * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
-   * Attribut mit dem Namen "GridCoverage" hat.
-   * 
-   * SK: Pyramidenlayer aka AbstractGridCoverage2DReader geben auch true zurück.
-   * 
-   * @param layer
-   *          zu ueberpruefendes Layer
-   */
-  public static boolean isGridCoverageLayer(MapLayer layer) {
-    final Object layerSourceObject = getLayerSourceObject(layer);
-    boolean b = (layerSourceObject instanceof GridCoverage2D)
-        || (layerSourceObject instanceof AbstractGridCoverage2DReader);
-    // if (!b && layerSourceObject instanceof DefaultFeatureResults){
-    // DefaultFeatureResults dfr = (DefaultFeatureResults)
-    // layerSourceObject;
-    // }
-    // LOGGER.debug(b+"= "+layerSourceObject.getClass().getSimpleName()+" "+
-    // layer.getTitle());
-    return b;
-    // try {
-    // FeatureCollection fc = layer.getFeatureSource().getFeatures();
-    // // Layer muss genau ein SimpleFeature beinhalten
-    // if ( fc == null || fc.size() != 1 )
-    // return false;
-    // // SimpleFeature muss genau 1 Attribut mit dem Namen "GridCoverage" haben
-    // SimpleFeatureType ftype = fc.getFeatureType();
-    // if ( ftype == null || ftype.getAttributeCount() != 1 ||
-    // !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(0).getName())
-    // )
-    // return false;
-    // } catch (Exception err) {
-    // }
-    // return true;
-  }
+	// /**
+	// * Bereitet einen BoundingBox-Filter vor. Das "linke" Attribut der
+	// * Expression (das SimpleFeature-Attribut, auf das der Filter angewendet
+	// wird),
+	// * wird dabei noch nicht belegt. Dies geschieht erst bei der Auswertung
+	// * entsprechend des jeweiligen Layers
+	// *
+	// * @param env
+	// * Bounding-Box
+	// */
+	// private static GeometryFilterImpl createBoundingBoxFilter(Envelope env) {
+	// // Filter fuer Envelope zusammenstellen
+	// Expression bbox = ff.createBBoxExpression(env);
+	// GeometryFilterImpl bboxFilter = (GeometryFilterImpl) ff
+	// .createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
+	// // GeometryFilterImpl bboxFilter =
+	// // (GeometryFilterImpl)ff.createGeometryFilter
+	// // (AbstractFilter.GEOMETRY_WITHIN);
+	// bboxFilter.setExpression2(bbox);
+	// return bboxFilter;
+	// }
+	//
+	// /**
+	// * Bereitet einen Punkt-Filter vor. Das "linke" Attribut der Expression
+	// (das
+	// * SimpleFeature-Attribut, auf das der Filter angewendet wird), wird dabei
+	// noch
+	// * nicht belegt. Dies geschieht erst bei der Auswertung entsprechend des
+	// * jeweiligen Layers
+	// *
+	// * @param point
+	// * Geo-Koordinate
+	// */
+	// private static GeometryFilterImpl createPointFilter(Point2D point) {
+	// // Filter fuer Envelope zusammenstellen
+	// Geometry geometry = gf.createPoint(new Coordinate(point.getX(), point
+	// .getY()));
+	// GeometryFilterImpl pointFilter = (GeometryFilterImpl) ff
+	// .createGeometryFilter(GeometryFilterImpl.GEOMETRY_CONTAINS);
+	// pointFilter.setExpression2(ff.createLiteralExpression(geometry));
+	// return pointFilter;
+	// }
+	//
+	// /**
+	// * Bereitet einen "InDerNaehe von" Distance-Filter vor. Das "linke"
+	// Attribut
+	// * der Expression (das SimpleFeature-Attribut, auf das der Filter
+	// angewendet
+	// * wird), wird dabei noch nicht belegt. Dies geschieht erst bei der
+	// * Auswertung entsprechend des jeweiligen Layers
+	// *
+	// * Wird benoetigt, um mit der Maus einen Punkt zu treffen.
+	// *
+	// * @param point
+	// * Geo-Koordinate
+	// * @param dist
+	// * Distanz zum Punkt in Einheiten des Layers
+	// *
+	// * TODO SK Auf FilterFactory2 ändern... Beispiel von
+	// * http://docs.codehaus.org/display/GEOTDOC/Filter+Examples
+	// * funktioniert erst ab 2.5 ?? Vor dem Distcheck einen BBOX check
+	// * sollte die geschwindigkeit erhöhen.
+	// *
+	// * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	// * Kr&uuml;ger</a>
+	// */
+	// private static GeometryFilterImpl createNearPointFilter(
+	// final Point2D point, final Double dist) {
+	// // Filter fuer Envelope zusammenstellen
+	// final Geometry geometry = gf.createPoint(new Coordinate(point.getX(),
+	// point.getY()));
+	//
+	// final DWithinImpl dwithinFilter = (DWithinImpl) ff
+	// .createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
+	//
+	// dwithinFilter.setDistance(dist);
+	//
+	// dwithinFilter.setExpression2(ff.createLiteralExpression(geometry));
+	//
+	// return dwithinFilter;
+	// }
 
-  /**
-   * Liefert das Objekt ({@link GridCoverage2D} oder {@link FeatureCollection}
-   * oder {@link AbstractGridCoverageReader} auf dem ein Layer basiert. Ein
-   * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-   * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
-   * Attribut mit Namen "GridCoverage" und Typ {@code GridCoverage2D} oder
-   * {@link AbstractGridCoverageReader} hat. Sind diese Bedingungen erfuellt,
-   * wird das 2. Attribut zurueckgegeben, ansonsten die
-   * {@link FeatureCollection}.
-   * 
-   * @param layer
-   *          ein Layer
-   * @return {@code null}, falls das Objekt nicht ermittelt werden kann (da ein
-   *         Fehler aufgetreten ist).
-   */
-  public static Object getLayerSourceObject(MapLayer layer) {
-    try {
-      final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
-          .getFeatureSource();
-      FeatureCollection<SimpleFeatureType, SimpleFeature> fc = featureSource
-          .getFeatures();
-      // RasterLayer muss genau ein SimpleFeature beinhalten
-      // Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
-      if (fc == null || fc.size() != 1) {
+	/**
+	 * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
+	 * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+	 * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
+	 * Attribut mit dem Namen "GridCoverage" hat.
+	 * 
+	 * SK: Pyramidenlayer aka AbstractGridCoverage2DReader geben auch true
+	 * zurück.
+	 * 
+	 * @param layer
+	 *            zu ueberpruefendes Layer
+	 */
+	public static boolean isGridCoverageLayer(MapLayer layer) {
+		final Object layerSourceObject = getLayerSourceObject(layer);
+		boolean b = (layerSourceObject instanceof GridCoverage2D)
+				|| (layerSourceObject instanceof AbstractGridCoverage2DReader);
+		// if (!b && layerSourceObject instanceof DefaultFeatureResults){
+		// DefaultFeatureResults dfr = (DefaultFeatureResults)
+		// layerSourceObject;
+		// }
+		// LOGGER.debug(b+"= "+layerSourceObject.getClass().getSimpleName()+" "+
+		// layer.getTitle());
+		return b;
+		// try {
+		// FeatureCollection fc = layer.getFeatureSource().getFeatures();
+		// // Layer muss genau ein SimpleFeature beinhalten
+		// if ( fc == null || fc.size() != 1 )
+		// return false;
+		// // SimpleFeature muss genau 1 Attribut mit dem Namen "GridCoverage"
+		// haben
+		// SimpleFeatureType ftype = fc.getFeatureType();
+		// if ( ftype == null || ftype.getAttributeCount() != 1 ||
+		// !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(0).getName())
+		// )
+		// return false;
+		// } catch (Exception err) {
+		// }
+		// return true;
+	}
 
-        return fc;
-      }
-      // SimpleFeatureType des RasterLayer muss genau 1 Attribut mit Namen
-      // "GridCoverage"
-      // Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
-      SimpleFeatureType ftype = fc.getSchema();
-      if (ftype == null
-          || ftype.getAttributeCount() != 1
-          || !"GridCoverage".equalsIgnoreCase(ftype.getAttributeDescriptors()
-              .get(0).getLocalName()))
-        return fc;
-      // (Einziges) SimpleFeature muss genau 2 Attribute besitzen, wobei das
-      // erste vom
-      // Typ Geometry ist und das zweite vom Typ GridCoverage2D
-      // sonst: FeatureCollextion zurueckgeben
+	/**
+	 * Liefert das Objekt ({@link GridCoverage2D} oder {@link FeatureCollection}
+	 * oder {@link AbstractGridCoverageReader} auf dem ein Layer basiert. Ein
+	 * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+	 * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
+	 * Attribut mit Namen "GridCoverage" und Typ {@code GridCoverage2D} oder
+	 * {@link AbstractGridCoverageReader} hat. Sind diese Bedingungen erfuellt,
+	 * wird das 2. Attribut zurueckgegeben, ansonsten die
+	 * {@link FeatureCollection}.
+	 * 
+	 * @param layer
+	 *            ein Layer
+	 * @return {@code null}, falls das Objekt nicht ermittelt werden kann (da
+	 *         ein Fehler aufgetreten ist).
+	 */
+	public static Object getLayerSourceObject(MapLayer layer) {
+		try {
+			final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+					.getFeatureSource();
+			FeatureCollection<SimpleFeatureType, SimpleFeature> fc = featureSource
+					.getFeatures();
 
-      /** CHANGE SK 9.8.08 BEGIN */
-      SimpleFeature f = fc.features().next();
-      if ((f.getFeatureType().getTypeName().equals("GridCoverage") && f
-          .getAttributeCount() >= 2)) {
-        // I am sure, that it is a raster some. We do not have to cast
-        // it to either cridcoverage or abstractReader, as the results
-        // are tested anyway...
-        return f.getAttribute(1);
-      }
-      /** CHANGE SK 9.8.08 END */
+			// RasterLayer muss genau ein SimpleFeature beinhalten
+			// Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
+			if (fc == null || fc.size() != 1) {
+				return fc;
+			}
 
-      if (f.getAttributeCount() != 2
-          || // Geaendert, da es bei AbstractGridCoverageReader 3 sind
-          // (SK, 19.08.07)
-          !(f.getAttribute(0) instanceof com.vividsolutions.jts.geom.Geometry)
-          || !(f.getAttribute(1) instanceof GridCoverage2D))
-        return fc;
+			// Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
+			SimpleFeatureType ftype = fc.getSchema(); 
 
-      // Objekt ist ein Raster!
-      return (GridCoverage2D) f.getAttribute(1);
-    } catch (Exception err) {
-      LOGGER.warn(err.getMessage(), err);
-      return null;
-    }
-  }
+			if (ftype == null || !GC_NAME.equals(ftype.getName()))
+				return fc;
 
-  /**
-   * Should be called when the {@link JMapPane} is not needed no more to help
-   * the GarbageCollector
-   * 
-   * Removes all {@link JMapPaneListener}s that are registered
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
+			FeatureIterator<SimpleFeature> fIt = fc.features();
 
-  public void dispose() {
-    if (isDisposed())
-      return;
+			try {
+				SimpleFeature onlyFeature = fIt.next();
+				GridCoverage2D grid = (GridCoverage2D) onlyFeature
+						.getAttribute(1);
 
-    if (dragWaitCursorListener != null)
-      this.removeMouseListener(dragWaitCursorListener);
-    if (mouseWheelZoomListener != null)
-      this.removeMouseWheelListener(mouseWheelZoomListener);
+				return grid;
 
-    // Alle mapPaneListener entfernen
-    mapPaneListeners.clear();
+			} finally {
+				fIt.close();
+			}
+			
+		} catch (Exception err) {
+			LOGGER.warn(err.getMessage(), err);
+			return null;
+		}
+	}
 
-    getContext().clearLayerList();
+	/**
+	 * Should be called when the {@link JMapPane} is not needed no more to help
+	 * the GarbageCollector
+	 * 
+	 * Removes all {@link JMapPaneListener}s that are registered
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
 
-    removeAll();
-    disposed = true;
-  }
+	public void dispose() {
+		if (isDisposed())
+			return;
 
-  /**
-   * A flag indicating if dispose() has already been called. If true, then
-   * further use of this {@link JMapPane} is undefined.
-   */
-  private boolean isDisposed() {
-    return disposed;
-  }
+		if (dragWaitCursorListener != null)
+			this.removeMouseListener(dragWaitCursorListener);
+		if (mouseWheelZoomListener != null)
+			this.removeMouseWheelListener(mouseWheelZoomListener);
 
-  //
-  // /**
-  // * Werden Rasterlayer waehrend einer PAN Aktion versteckt?
-  // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-  // Kr&uuml;ger</a>
-  // */
-  // public boolean isHideRasterLayersDuringPan() {
-  // return hideRasterLayersDuringPan;
-  // }
-  //
-  // /**
-  // * Bestimmt, ob Rasterlayer waehrend einer PAN Aktion versteckt werden
-  // soll. Default ist false.
-  // * @param hideRasterLayersDuringPan
-  // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-  // Kr&uuml;ger</a>
-  // */
-  // public void setHideRasterLayersDuringPan(boolean
-  // hideRasterLayersDuringPan) {
-  // this.hideRasterLayersDuringPan = hideRasterLayersDuringPan;
-  // }
+		// Alle mapPaneListener entfernen
+		mapPaneListeners.clear();
 
-  public boolean isSetWaitCursorDuringNextRepaint() {
-    return setWaitCursorDuringNextRepaint;
-  }
+		getContext().clearLayerList();
 
-  /**
-   * When setting this to true, the next repaint of this component will be
-   * accompanied by a WAIT Cursor
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void setWaitCursorDuringNextRepaint(boolean waitCursorDuringNextRepaint) {
-    this.setWaitCursorDuringNextRepaint = waitCursorDuringNextRepaint;
-  }
+		removeAll();
+		disposed = true;
+	}
 
-  /**
-   * Gibt den "normalen" Cursor zurueck. Dieser kann neben dem "pointer" auch
-   * ein Sanduhr-Wartecursor sein.
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public Cursor getNormalCursor() {
-    return normalCursor;
-  }
+	/**
+	 * A flag indicating if dispose() has already been called. If true, then
+	 * further use of this {@link JMapPane} is undefined.
+	 */
+	private boolean isDisposed() {
+		return disposed;
+	}
 
-  /**
-   * Setzt den "normalen" Cursor. Dieser kann neben dem default "pointer" z.B.
-   * auch ein Sanduhr-Wartecursor sein.
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  public void setNormalCursor(Cursor normalCursor) {
-    this.normalCursor = normalCursor;
-  }
+	//
+	// /**
+	// * Werden Rasterlayer waehrend einer PAN Aktion versteckt?
+	// * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	// Kr&uuml;ger</a>
+	// */
+	// public boolean isHideRasterLayersDuringPan() {
+	// return hideRasterLayersDuringPan;
+	// }
+	//
+	// /**
+	// * Bestimmt, ob Rasterlayer waehrend einer PAN Aktion versteckt werden
+	// soll. Default ist false.
+	// * @param hideRasterLayersDuringPan
+	// * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	// Kr&uuml;ger</a>
+	// */
+	// public void setHideRasterLayersDuringPan(boolean
+	// hideRasterLayersDuringPan) {
+	// this.hideRasterLayersDuringPan = hideRasterLayersDuringPan;
+	// }
 
-  // /**
-  // * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
-  // * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-  // * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
-  // Attribut
-  // * vom Type {@link org.geotools.feature.type.FeatureAttributeType} hat,
-  // welches
-  // * wiederum genau zwei Attribute hat:<br>
-  // * Eines vom Typ {@link
-  // org.opengis.spatialschema.geometry.geometry.Polygon}
-  // * und eines vom Typ {@link org.opengis.coverage.grid.GridCoverage}.
-  // * @param layer zu ueberpruefendes Layer
-  // */
-  // public static boolean isGridCoverageLayer(MapLayer layer) {
-  // try {
-  // FeatureCollection fc = layer.getFeatureSource().getFeatures();
-  // // Layer muss genau ein SimpleFeature beinhalten
-  // if ( fc == null || fc.size() != 1 )
-  // return false;
-  // // SimpleFeature muss genau 1 Attribut vom Typ FeatureAttributeType haben
-  // SimpleFeatureType ftype = fc.getFeatureType();
-  // if ( ftype == null || ftype.getAttributeCount() != 1 ||
-  // !(ftype.getAttributeType(0) instanceof
-  // org.geotools.feature.type.FeatureAttributeType) )
-  // return false;
-  // // FeatureAttribute muss genau 2 Atrribute haben
-  // org.geotools.feature.type.FeatureAttributeType atype =
-  // (org.geotools.feature
-  // .type.FeatureAttributeType)ftype.getAttributeType(0);
-  // if ( atype == null || atype.getAttributeCount() != 2 )
-  // return false;
-  // // Typ des ersten Attributs muss Polygon sein
-  // if ( !com.vividsolutions.jts.geom.Polygon.class.isAssignableFrom(
-  // atype.getAttributeType(0).getType() ) )
-  // return false;
-  // // Typ des zweiten Attributs muss GridCoverage sein
-  // if ( !org.opengis.coverage.grid.GridCoverage.class.isAssignableFrom(
-  // atype.getAttributeType(1).getType() ) )
-  // return false;
-  //
-  // } catch (Exception err) {
-  // }
-  // return true;
-  // }
+	public boolean isSetWaitCursorDuringNextRepaint() {
+		return setWaitCursorDuringNextRepaint;
+	}
 
-  /**
-   * Nuetzlich wenn die Componente gedruckt (z.B. wenn ein Screenshot gemacht
-   * wird) wird. Dann werden wird der Hintergrund auf WEISS gesetzt.
-   * 
-   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-   *         Kr&uuml;ger</a>
-   */
-  @Override
-  public void print(Graphics g) {
-    Color orig = getBackground();
-    setBackground(Color.WHITE);
+	/**
+	 * When setting this to true, the next repaint of this component will be
+	 * accompanied by a WAIT Cursor
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void setWaitCursorDuringNextRepaint(
+			boolean waitCursorDuringNextRepaint) {
+		this.setWaitCursorDuringNextRepaint = waitCursorDuringNextRepaint;
+	}
 
-    // wrap in try/finally so that we always restore the state
-    try {
-      super.print(g);
-    } finally {
-      setBackground(orig);
-    }
-  }
+	/**
+	 * Gibt den "normalen" Cursor zurueck. Dieser kann neben dem "pointer" auch
+	 * ein Sanduhr-Wartecursor sein.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public Cursor getNormalCursor() {
+		return normalCursor;
+	}
 
-  /**
-   * Sets the mapArea to smartly present the given features. Note: The method
-   * does not call {@link #repaint()} on the {@link JMapPane}.
-   */
-  public void zoomTo(SimpleFeature feature) {
-    final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
-        .getFeatureType());
-    mfc.add(feature);
-    zoomTo(mfc);
-  }
+	/**
+	 * Setzt den "normalen" Cursor. Dieser kann neben dem default "pointer" z.B.
+	 * auch ein Sanduhr-Wartecursor sein.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	public void setNormalCursor(Cursor normalCursor) {
+		this.normalCursor = normalCursor;
+	}
 
-  /**
-   * Sets the mapArea to best possibly present the given features. If only one
-   * single point is given, the window is moved over the point.
-   * 
-   * Note: The method does not call {@link #repaint()} on the {@link JMapPane} .
-   * 
-   * @param features
-   *          if <code>null</code> or size==0, the function doesn nothing.
-   */
-  public void zoomTo(FeatureCollection<SimpleFeatureType,SimpleFeature> features) {
+	// /**
+	// * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
+	// * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+	// * {@link FeatureCollection} nur ein SimpleFeature enthaelt, das genau ein
+	// Attribut
+	// * vom Type {@link org.geotools.feature.type.FeatureAttributeType} hat,
+	// welches
+	// * wiederum genau zwei Attribute hat:<br>
+	// * Eines vom Typ {@link
+	// org.opengis.spatialschema.geometry.geometry.Polygon}
+	// * und eines vom Typ {@link org.opengis.coverage.grid.GridCoverage}.
+	// * @param layer zu ueberpruefendes Layer
+	// */
+	// public static boolean isGridCoverageLayer(MapLayer layer) {
+	// try {
+	// FeatureCollection fc = layer.getFeatureSource().getFeatures();
+	// // Layer muss genau ein SimpleFeature beinhalten
+	// if ( fc == null || fc.size() != 1 )
+	// return false;
+	// // SimpleFeature muss genau 1 Attribut vom Typ FeatureAttributeType haben
+	// SimpleFeatureType ftype = fc.getFeatureType();
+	// if ( ftype == null || ftype.getAttributeCount() != 1 ||
+	// !(ftype.getAttributeType(0) instanceof
+	// org.geotools.feature.type.FeatureAttributeType) )
+	// return false;
+	// // FeatureAttribute muss genau 2 Atrribute haben
+	// org.geotools.feature.type.FeatureAttributeType atype =
+	// (org.geotools.feature
+	// .type.FeatureAttributeType)ftype.getAttributeType(0);
+	// if ( atype == null || atype.getAttributeCount() != 2 )
+	// return false;
+	// // Typ des ersten Attributs muss Polygon sein
+	// if ( !com.vividsolutions.jts.geom.Polygon.class.isAssignableFrom(
+	// atype.getAttributeType(0).getType() ) )
+	// return false;
+	// // Typ des zweiten Attributs muss GridCoverage sein
+	// if ( !org.opengis.coverage.grid.GridCoverage.class.isAssignableFrom(
+	// atype.getAttributeType(1).getType() ) )
+	// return false;
+	//
+	// } catch (Exception err) {
+	// }
+	// return true;
+	// }
 
-    CoordinateReferenceSystem mapCRS = getContext()
-        .getCoordinateReferenceSystem();
-    CoordinateReferenceSystem fCRS = features.getSchema()
-        .getGeometryDescriptor().getCoordinateReferenceSystem();
-    // if (! mapCRS.equals(fCRS)) {
-    // throw new
-    // RuntimeException(
-    // "Projecting the features to show to the map CRS is not yet implemented."
-    // );
-    // }
+	/**
+	 * Nuetzlich wenn die Componente gedruckt (z.B. wenn ein Screenshot gemacht
+	 * wird) wird. Dann werden wird der Hintergrund auf WEISS gesetzt.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+	 *         Kr&uuml;ger</a>
+	 */
+	@Override
+	public void print(Graphics g) {
+		Color orig = getBackground();
+		setBackground(Color.WHITE);
 
-    double width = mapArea.getWidth();
-    double height = mapArea.getHeight();
-    double ratio = height / width;
+		// wrap in try/finally so that we always restore the state
+		try {
+			super.print(g);
+		} finally {
+			setBackground(orig);
+		}
+	}
 
-    if (features == null || features.size() == 0) {
-      // feature count == 0 Zoom to the full extend
-      return;
-    } else if (features.size() == 1) {
+	/**
+	 * Sets the mapArea to smartly present the given features. Note: The method
+	 * does not call {@link #repaint()} on the {@link JMapPane}.
+	 */
+	public void zoomTo(SimpleFeature feature) {
+		final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
+				.getFeatureType());
+		mfc.add(feature);
+		zoomTo(mfc);
+	}
 
-      // feature count == 1 Just move the window to the point and zoom 'a
-      // bit'
-      SimpleFeature singleFeature = (SimpleFeature) features.iterator().next();
+	/**
+	 * Sets the mapArea to best possibly present the given features. If only one
+	 * single point is given, the window is moved over the point.
+	 * 
+	 * Note: The method does not call {@link #repaint()} on the {@link JMapPane}
+	 * .
+	 * 
+	 * @param features
+	 *            if <code>null</code> or size==0, the function doesn nothing.
+	 */
+	public void zoomTo(
+			FeatureCollection<SimpleFeatureType, SimpleFeature> features) {
 
-      if (((Geometry) singleFeature.getDefaultGeometry()).getCoordinates().length > 1) {
-        // System.out.println("Zoomed to only pne poylgon");
-        // Poly
-        // TODO max width vs. height
-        width = features.getBounds().getWidth() * 3;
-        height = ratio * width;
-      } else {
-        // System.out.println("Zoomed in a bit becasue only one point");
-        // width *= .9;
-        // height *= .9;
-      }
+		CoordinateReferenceSystem mapCRS = getContext()
+				.getCoordinateReferenceSystem();
+		CoordinateReferenceSystem fCRS = features.getSchema()
+				.getGeometryDescriptor().getCoordinateReferenceSystem();
+		// if (! mapCRS.equals(fCRS)) {
+		// throw new
+		// RuntimeException(
+		// "Projecting the features to show to the map CRS is not yet implemented."
+		// );
+		// }
 
-      Coordinate centre = features.getBounds().centre();
-      if (!mapCRS.equals(fCRS)) {
-        // only to calculations if the CRS differ
-        try {
-          MathTransform fToMap;
-          fToMap = CRS.findMathTransform(fCRS, mapCRS);
-          // centre is transformed to the mapCRS
-          centre = JTS.transform(centre, null, fToMap);
-        } catch (FactoryException e) {
-          LOGGER.error("Looking for a Math transform", e);
-        } catch (TransformException e) {
-          LOGGER.error("Looking for a Math transform", e);
-        }
-      }
+		double width = mapArea.getWidth();
+		double height = mapArea.getHeight();
+		double ratio = height / width;
 
-      Coordinate newLeftBottom = new Coordinate(centre.x - width / 2., centre.y
-          - height / 2.);
-      Coordinate newTopRight = new Coordinate(centre.x + width / 2., centre.y
-          + height / 2.);
+		if (features == null || features.size() == 0) {
+			// feature count == 0 Zoom to the full extend
+			return;
+		} else if (features.size() == 1) {
 
-      Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
+			// feature count == 1 Just move the window to the point and zoom 'a
+			// bit'
+			SimpleFeature singleFeature = (SimpleFeature) features.iterator()
+					.next();
 
-      setMapArea(newMapArea);
+			if (((Geometry) singleFeature.getDefaultGeometry())
+					.getCoordinates().length > 1) {
+				// System.out.println("Zoomed to only pne poylgon");
+				// Poly
+				// TODO max width vs. height
+				width = features.getBounds().getWidth() * 3;
+				height = ratio * width;
+			} else {
+				// System.out.println("Zoomed in a bit becasue only one point");
+				// width *= .9;
+				// height *= .9;
+			}
 
-    } else {
-      ReferencedEnvelope fBounds = features.getBounds();
+			Coordinate centre = features.getBounds().centre();
+			if (!mapCRS.equals(fCRS)) {
+				// only to calculations if the CRS differ
+				try {
+					MathTransform fToMap;
+					fToMap = CRS.findMathTransform(fCRS, mapCRS);
+					// centre is transformed to the mapCRS
+					centre = JTS.transform(centre, null, fToMap);
+				} catch (FactoryException e) {
+					LOGGER.error("Looking for a Math transform", e);
+				} catch (TransformException e) {
+					LOGGER.error("Looking for a Math transform", e);
+				}
+			}
 
-      Envelope bounds;
-      if (!mapCRS.equals(fCRS)) {
-        bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
-      } else {
-        bounds = fBounds;
-      }
-      // BB umrechnen von Layer-CRS in Map-CRS
+			Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
+					centre.y - height / 2.);
+			Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
+					centre.y + height / 2.);
 
-      // Expand a bit
-      bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
+			Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
 
-      setMapArea(bounds);
-    }
-  }
+			setMapArea(newMapArea);
 
-  /**
-   * 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>
-   */
-  private static 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>();
+		} else {
+			ReferencedEnvelope fBounds = features.getBounds();
 
-    /**
-     * 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;
-    }
+			Envelope bounds;
+			if (!mapCRS.equals(fCRS)) {
+				bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
+			} else {
+				bounds = fBounds;
+			}
+			// BB umrechnen von Layer-CRS in Map-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);
+			// Expand a bit
+			bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
 
-    /**
-     * 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 = ff.property(geomDescr
-          .getLocalName());
-      filter.setExpression1(geometry);
-      return filter;
-    }
+			setMapArea(bounds);
+		}
+	}
 
-  }
+	/**
+	 * 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>
+	 */
+	private static 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>();
 
-  /**
-   * {@link GeomFilterGenerator} for a bounding box constraint.
-   * 
-   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-   */
-  private 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 crs
+		 *            {@link CoordinateReferenceSystem} the base constraint
+		 *            ("right" filter argument is relative to)
+		 */
+		public GeomFilterGenerator(CoordinateReferenceSystem crs) {
+			this.baseCRS = crs;
+		}
 
-    /**
-     * Creates a new filter generator.
-     * 
-     * @param baseEnv
-     *          defines the bounding box
-     * @param crs
-     *          defines the CRS of the bounding box
-     */
-    public BoundingBoxFilterGenerator(Envelope baseEnv,
-        CoordinateReferenceSystem crs) {
-      super(crs);
-      this.baseEnv = baseEnv;
-    }
+		/**
+		 * 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);
 
-    /**
-     * 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 (!baseCRS.equals(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;
-    }
-  }
+		/**
+		 * 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 = ff.property(geomDescr.getLocalName());
+			filter.setExpression1(geometry);
+			return filter;
+		}
 
-  /**
-   * {@link GeomFilterGenerator} for a "near distance" constraint.
-   * 
-   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-   */
-  private 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
-     *          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(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);
-    }
+	/**
+	 * {@link GeomFilterGenerator} for a bounding box constraint.
+	 * 
+	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+	 */
+	private 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 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);
-    }
+		/**
+		 * Creates a new filter generator.
+		 * 
+		 * @param baseEnv
+		 *            defines the bounding box
+		 * @param crs
+		 *            defines the CRS of the bounding box
+		 */
+		public BoundingBoxFilterGenerator(Envelope baseEnv,
+				CoordinateReferenceSystem crs) {
+			super(crs);
+			this.baseEnv = baseEnv;
+		}
 
-    /**
-     * 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);
+		/**
+		 * 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 (!baseCRS.equals(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;
+		}
+	}
 
-        if (nearPoint == null || nearPoint2 == null)
-          throw new RuntimeException("Unable to transform CRS from " + baseCRS
-              + " to " + crs);
+	/**
+	 * {@link GeomFilterGenerator} for a "near distance" constraint.
+	 * 
+	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+	 */
+	private 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;
 
-        nearDist = Math.abs(nearPoint.x - nearPoint2.x);
-      }
-      // Filter fuer Point zusammenstellen
-      final Geometry geometry = FilterUtil.GEOMETRY_FAC.createPoint(nearPoint);
-      
-      final DWithinImpl dwithinFilter = (DWithinImpl) FilterUtil.FILTER_FAC
-          .createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
-      dwithinFilter.setDistance(nearDist);
-      dwithinFilter.setExpression2(FilterUtil.FILTER_FAC
-          .createLiteralExpression(geometry));
-      
+		/**
+		 * 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(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);
+		}
 
-      return dwithinFilter;
-    }
+		/**
+		 * 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);
 
-  /**
-   * Allows to optionally supply the {@link JMapPane} with meta information
-   * about layers. This is used (when supplied) for the algorithm that selects
-   * features with a mouse click.
-   * 
-   * @param layerID
-   * @param atm
-   */
-  public void setAttributeMetaDataFor(String layerID,
-      Map<Integer, AttributeMetaData> aMDMap) {
-    attributeMetaDataMapCache.put(layerID, aMDMap);
-  }
+				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 = (DWithinImpl) FilterUtil.FILTER_FAC
+					.createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
+			dwithinFilter.setDistance(nearDist);
+			dwithinFilter.setExpression2(FilterUtil.FILTER_FAC
+					.createLiteralExpression(geometry));
+
+			return dwithinFilter;
+		}
+
+	}
+
+	/**
+	 * Allows to optionally supply the {@link JMapPane} with meta information
+	 * about layers. This is used (when supplied) for the algorithm that selects
+	 * features with a mouse click.
+	 * 
+	 * @param layerID
+	 * @param atm
+	 */
+	public void setAttributeMetaDataFor(String layerID,
+			Map<Integer, AttributeMetaData> aMDMap) {
+		attributeMetaDataMapCache.put(layerID, aMDMap);
+	}
 }



More information about the Schmitzm-commits mailing list