[Schmitzm-commits] r151 - in trunk/src: schmitzm/geotools/gui skrueger/geotools skrueger/geotools/selection

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Jun 19 18:22:29 CEST 2009


Author: alfonx
Date: 2009-06-19 18:22:29 +0200 (Fri, 19 Jun 2009)
New Revision: 151

Modified:
   trunk/src/schmitzm/geotools/gui/JMapPane.java
   trunk/src/skrueger/geotools/MapPaneToolBar.java
   trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
   trunk/src/skrueger/geotools/selection/StyledLayerSelectionModelSynchronizer.java
Log:
* Selection stuff technically ready to use! :-) :-) Next translating tooltips etc... 

Modified: trunk/src/schmitzm/geotools/gui/JMapPane.java
===================================================================
--- trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-06-19 14:20:30 UTC (rev 150)
+++ trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-06-19 16:22:29 UTC (rev 151)
@@ -133,7 +133,7 @@
  * {@linkplain AffineTransform affine Transformation} mit der die aktuellen
  * Fenster-Koordinaten (z.B. eines <code>MouseEvent</code>) in
  * Karten-Koordinaten (Latitude/Longitude) umgerechnet werden koennen.
- *
+ * 
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  *         (University of Bonn/Germany)
  * @version 1.0
@@ -159,10 +159,12 @@
 		fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
 	}
 
-	private static final Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
+	private static final Cursor WAIT_CURSOR = Cursor
+			.getPredefinedCursor(Cursor.WAIT_CURSOR);
 
 	/** Logger for debug messages. */
-	protected static final Logger LOGGER = Logger.getLogger(JMapPane.class.getName());
+	protected static final Logger LOGGER = Logger.getLogger(JMapPane.class
+			.getName());
 
 	/** @deprecated ersetzt durch {@link #ZOOM_IN} */
 	public static final int ZoomIn = org.geotools.gui.swing.JMapPane.ZoomIn;
@@ -177,47 +179,47 @@
 
 	/**
 	 * 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 "Feature-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 "Feature-Auswahl auf allen (sichtbaren) Layern".
-	 *
+	 * 
 	 * @see #setWindowSelectionState(int)
 	 * @see #setState(int)
 	 */
@@ -225,7 +227,7 @@
 	/**
 	 * Flag fuer Modus
 	 * "Auswahl nur eines Features, das erste sichtbare von Oben".
-	 *
+	 * 
 	 * @see #setWindowSelectionState(int)
 	 * @see #setState(int)
 	 */
@@ -247,19 +249,20 @@
 	protected Vector<JMapPaneListener> mapPaneListeners = new Vector<JMapPaneListener>();
 
 	protected MouseSelectionTracker_Public selTracker = new MouseSelectionTracker_Public() {
-//MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit mehreren parallelen Mouse(Motion)Listenern        
-	    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;
-	      if ( getState() == ZOOM_IN || getState() == ZOOM_OUT )
-	        return;
-	      
-	      super.mouseDragged(event);
-	    }
-	    
-	    protected void selectionPerformed(int ox, int oy, int px, int py) {
+		// MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit
+		// mehreren parallelen Mouse(Motion)Listenern
+		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;
+			if (getState() == ZOOM_IN || getState() == ZOOM_OUT)
+				return;
+
+			super.mouseDragged(event);
+		}
+
+		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
@@ -316,160 +319,200 @@
 	/** 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);
-     }
+	/**
+	 * 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);
+	}
 
-      /**
-       * 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(LayoutManager layout, boolean isDoubleBuffered, GTRenderer renderer, MapContext context) {
-	     super(
-	         layout != null ? layout : new BorderLayout(),
-	         isDoubleBuffered,
-	         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(LayoutManager layout, boolean isDoubleBuffered,
+			GTRenderer renderer, MapContext context) {
+		super(layout != null ? layout : new BorderLayout(), isDoubleBuffered,
+				renderer != null ? renderer : new StreamingRenderer(),
+				context != null ? context : new DefaultMapContext(GTUtil.WGS84));
 
-	     // 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);
+		// 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);
 
-	     // 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 );
+		// 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 );
 
-	     setWindowSelectionState(ZOOM_IN);
-	     setState(ZOOM_IN);
+		setWindowSelectionState(ZOOM_IN);
+		setState(ZOOM_IN);
 
-//MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit mehreren parallelen Mouse(Motion)Listenern 	     
-//	     // Listener fuer Selektions-Rahmen
-//	     addMouseListener(selTracker);
-	     
-	     // Listener, der auf das Mausrad lauscht und mit Zoom reagiert
-	     mouseWheelZoomListener = new MouseWheelListener() {
-	       public void mouseWheelMoved(MouseWheelEvent e) {
-	         performMouseWheelEvent(e);
-	       }
-	     };
-	     this.addMouseWheelListener(mouseWheelZoomListener);
+		// MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit
+		// mehreren parallelen Mouse(Motion)Listenern
+		// // Listener fuer Selektions-Rahmen
+		// addMouseListener(selTracker);
 
-	     /**
-	      * 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);
+		// Listener, der auf das Mausrad lauscht und mit Zoom reagiert
+		mouseWheelZoomListener = new MouseWheelListener() {
+			public void mouseWheelMoved(MouseWheelEvent e) {
+				performMouseWheelEvent(e);
+			}
+		};
+		this.addMouseWheelListener(mouseWheelZoomListener);
 
-	     // 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
+		/**
+		 * 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);
 
-	     getContext().addMapLayerListListener(new schmitzm.geotools.map.event.MapLayerListAdapter() {
-	       private void resetHighlightLayer() {
-	         if (isHighlight())
-	           setHighlightLayer(getTopVisibleNonGridCoverageLayer());
-	       }
+		// 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().getDefaultGeometry().getCoordinateSystem();
-	             // 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);
-	           } catch (Exception err) {
-	             LOGGER.error("CRS could not be assigned to map context.");
-	           }
-	         }
-	       }
-	     });
-	    }
+					public void layerRemoved(
+							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().getDefaultGeometry()
+										.getCoordinateSystem();
+								// 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);
+							} catch (Exception err) {
+								LOGGER
+										.error("CRS could not be assigned to map context.");
+							}
+						}
+					}
+				});
+	}
+
 	/**
-	 * Get the BufferedImage to use as a flaoting icon in the lower right corner.
+	 * 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() {
@@ -478,7 +521,9 @@
 
 	/**
 	 * 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.
+	 * 
+	 * @param mapImageIcon
+	 *            <code>null</code> is allowed and deactivates this icon.
 	 */
 	public void setMapImage(BufferedImage mapImage) {
 		this.mapImage = mapImage;
@@ -487,10 +532,10 @@
 	/**
 	 * 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() {
@@ -501,28 +546,26 @@
 	 * 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;
+		this.mouseWaitCursorComponent = parentComponent;
 	}
 
-
-
 	/**
 	 * 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
@@ -543,12 +586,12 @@
 	 * 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);
+		// LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
 		RenderingHints java2DHints = getRenderer().getJava2DHints();
 		if (java2DHints == null)
 			java2DHints = GeoTools.getDefaultHints();
@@ -567,10 +610,10 @@
 	/**
 	 * 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
 	 */
@@ -601,14 +644,14 @@
 
 	/**
 	 * 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>
 	 */
@@ -620,16 +663,16 @@
 	 * 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>
 	 */
@@ -701,8 +744,8 @@
 
 	/**
 	 * 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
@@ -711,7 +754,7 @@
 	 * Layer</li>
 	 * <li>{@link #NONE} Nichts machen</li>
 	 * </ul>
-	 *
+	 * 
 	 * @param newSelState
 	 *            Modus fuer Window-Selektion
 	 */
@@ -722,9 +765,10 @@
 			throw new IllegalArgumentException(
 					"Unknown selection state for window selection!");
 
-//MS (2009-13-05): noch buggy -> wieder reingenommen (Probleme mit mehreren parallelen Mouse(Motion)Listenern        
-//MS (13.05.2009): Wird durch Ueberschreiben von mouseDragged(.) des
-//                 MouseSelectionTracker realisiert
+		// MS (2009-13-05): noch buggy -> wieder reingenommen (Probleme mit
+		// mehreren parallelen Mouse(Motion)Listenern
+		// MS (13.05.2009): Wird durch Ueberschreiben von mouseDragged(.) des
+		// MouseSelectionTracker realisiert
 		// Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
 		// Selektionsfenster beim Draggen nicht mehr gezeichnet wird
 		if ((newSelState == NONE) && (selState != NONE)) {
@@ -747,7 +791,7 @@
 	 * 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
 	 */
@@ -760,7 +804,7 @@
 	/**
 	 * 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.
 	 */
@@ -799,7 +843,7 @@
 
 	/**
 	 * Liefert den Modus fuer Window-Selektion.
-	 *
+	 * 
 	 * @see #setWindowSelectionState(int)
 	 */
 	public int getWindowSelectionState() {
@@ -808,7 +852,7 @@
 
 	/**
 	 * Fuegt der Map einen Listener hinzu.
-	 *
+	 * 
 	 * @param l
 	 *            neuer Listener
 	 */
@@ -818,7 +862,7 @@
 
 	/**
 	 * Entfernt einen Listener von der Map.
-	 *
+	 * 
 	 * @param l
 	 *            zu entfernender Listener
 	 */
@@ -828,7 +872,7 @@
 
 	/**
 	 * Propagiert ein Ereignis an alle angeschlossenen Listener.
-	 *
+	 * 
 	 * @param e
 	 *            Ereignis
 	 */
@@ -840,7 +884,7 @@
 	/**
 	 * Konvertiert die Maus-Koordinaten (relativ zum <code>JMapPane</code>) in
 	 * Karten-Koordinaten.
-	 *
+	 * 
 	 * @param e
 	 *            Maus-Ereignis
 	 */
@@ -869,7 +913,7 @@
 	 * Features oder Raster selektiert, werden zudem
 	 * {@link FeatureSelectedEvent FeatureSelectedEvents} (bzw.
 	 * GridCoverageSelectedEvents GridCoverageSelectedEvents) ausgeloest.
-	 *
+	 * 
 	 * @param ox
 	 *            X-Koordinate der VON-Position
 	 * @param oy
@@ -913,7 +957,7 @@
 
 	/**
 	 * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
-	 *
+	 * 
 	 * @param e
 	 *            Mausrad-Event
 	 */
@@ -955,7 +999,7 @@
 
 	/**
 	 * Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten.
-	 *
+	 * 
 	 * @param ox
 	 *            X-Koordinate der VON-Position
 	 * @param oy
@@ -974,7 +1018,7 @@
 
 	/**
 	 * Transformiert eine Fenster-Koordinate in eine Geo-Koordinate.
-	 *
+	 * 
 	 * @param x
 	 *            X-Koordinate
 	 * @param y
@@ -1015,7 +1059,7 @@
 	/**
 	 * 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
 	 */
@@ -1036,16 +1080,16 @@
 	 * 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
@@ -1053,12 +1097,12 @@
 	 */
 	@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);
 		}
@@ -1083,7 +1127,7 @@
 	 * 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
@@ -1264,11 +1308,11 @@
 	 * 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
@@ -1319,24 +1363,30 @@
 			}
 
 			/**
-			 * Paint an icon in the lower right corner.
-			 * FeatureRequest: [#717] MapIcon has long been disabled and should come back
+			 * 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
+				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
@@ -1363,7 +1413,7 @@
 	/**
 	 * Testet (anhand der Features), ob das Objekt eines Layers eine
 	 * Bounding-Box schneidet.
-	 *
+	 * 
 	 * @param layer
 	 *            ein Layer
 	 * @param env
@@ -1391,9 +1441,9 @@
 	 * 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 distancefilter
 	 *            Filter
 	 * @param mode
@@ -1441,7 +1491,7 @@
 
 			/**
 			 * 8.8.2008: SK Wenn für das Layer auch ein Filter aktiv ist, dann
-			 * soll dieser mit AND and den distanceFilter gebunden werden.
+			 * soll dieser mit AND an den distanceFilter gebunden werden.
 			 * "Filter filter" ist entweder der distanceFilter oder
 			 * (distanceFilter AND layerFilter)
 			 */
@@ -1464,9 +1514,17 @@
 				// Liefert eine FeatureCollection zurück, in welcher nur
 				// Features enthalten sind, welche bei der aktuellen
 				// Anzeigeskala aufgrund des Styles gerendert werden.
-				
-				LOGGER.debug("Atlas sometimes hangs here... layertitle = "+layer.getTitle());
-				LOGGER.debug("Atlas sometimes hangs here... fc.size = "+fc.size());
+
+				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;
+				}
+
+				// @Martin Using size() produces the same problem
 				if (!fc.isEmpty()) {
 
 					fc = filterSLDVisibleOnly(fc, layer.getStyle());
@@ -1494,9 +1552,9 @@
 	 * 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
@@ -1578,18 +1636,18 @@
 	 * 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>
 	 */
@@ -1611,7 +1669,7 @@
 	 * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
 	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
 	 * durchsucht.
-	 *
+	 * 
 	 * @param filter
 	 *            Filter
 	 * @param mode
@@ -1640,7 +1698,7 @@
 	 * 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
@@ -1704,7 +1762,7 @@
 	 * 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
@@ -1736,14 +1794,14 @@
 	 * 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
@@ -1798,7 +1856,7 @@
 			GridCoverage2D sourceGrid;
 
 			if (layerObj instanceof AbstractGridCoverage2DReader) {
-				//LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
+				// LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
 				// );
 				AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
 				Parameter readGG = new Parameter(
@@ -1862,13 +1920,13 @@
 	 * 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
@@ -1894,7 +1952,7 @@
 	 * Expression (das Feature-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
 	 */
@@ -1915,7 +1973,7 @@
 	 * Feature-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
 	 */
@@ -1934,19 +1992,19 @@
 	 * der Expression (das Feature-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>
 	 */
@@ -1971,10 +2029,10 @@
 	 * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
 	 * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
 	 * Attribut mit dem Namen "GridCoverage" hat.
-	 *
+	 * 
 	 * SK: Pyramidenlayer aka AbstractGridCoverage2DReader geben auch true
 	 * zurück.
-	 *
+	 * 
 	 * @param layer
 	 *            zu ueberpruefendes Layer
 	 */
@@ -2014,7 +2072,7 @@
 	 * {@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
@@ -2073,9 +2131,9 @@
 	/**
 	 * 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>
 	 */
@@ -2135,7 +2193,7 @@
 	/**
 	 * 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>
 	 */
@@ -2147,7 +2205,7 @@
 	/**
 	 * 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>
 	 */
@@ -2158,7 +2216,7 @@
 	/**
 	 * 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>
 	 */
@@ -2214,7 +2272,7 @@
 	/**
 	 * Nuetzlich wenn die Componente gedruckt wird. Dann werden wird der
 	 * Hintergrund auf WEISS gesetzt.
-	 *
+	 * 
 	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
 	 *         Kr&uuml;ger</a>
 	 */
@@ -2230,101 +2288,105 @@
 			setBackground(orig);
 		}
 	}
-	
-	
-	  /**
-	   * Sets the mapArea to smartly present the given features. Note: The method does not call {@link #repaint()} on the {@link JMapPane}.
-	   */
-	  public void zoomTo(org.geotools.feature.Feature feature){
-			final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature.getFeatureType());
-			mfc.add(feature);
-			zoomTo(mfc);
-	  }
 
-	  /**
-		 * 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 features) {
-			
-			CoordinateReferenceSystem mapCRS = getContext().getCoordinateReferenceSystem();
-			CoordinateReferenceSystem fCRS = features.getSchema().getDefaultGeometry().getCoordinateSystem();
-//			if (! mapCRS.equals(fCRS)) {
-//				throw new RuntimeException("Projecting the features to show to the map CRS is not yet implemented.");
-//			}
+	/**
+	 * Sets the mapArea to smartly present the given features. Note: The method
+	 * does not call {@link #repaint()} on the {@link JMapPane}.
+	 */
+	public void zoomTo(org.geotools.feature.Feature feature) {
+		final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
+				.getFeatureType());
+		mfc.add(feature);
+		zoomTo(mfc);
+	}
 
-			double width = mapArea.getWidth();
-			double height = mapArea.getHeight();
-			double ratio = height / width;
+	/**
+	 * 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 features) {
 
-			if (features == null || features.size() == 0) {
-				// feature count == 0 Zoom to the full extend
-				return;
-			} else if (features.size() == 1) {
-				
-				// feature count == 1 Just move the window to the point and zoom 'a
-				// bit'
-				Feature singleFeature = (Feature) features.iterator().next();
+		CoordinateReferenceSystem mapCRS = getContext()
+				.getCoordinateReferenceSystem();
+		CoordinateReferenceSystem fCRS = features.getSchema()
+				.getDefaultGeometry().getCoordinateSystem();
+		// if (! mapCRS.equals(fCRS)) {
+		// throw new
+		// RuntimeException("Projecting the features to show to the map CRS is not yet implemented.");
+		// }
 
-				if (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;
-				}
+		double width = mapArea.getWidth();
+		double height = mapArea.getHeight();
+		double ratio = height / width;
 
-				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(e);
-					} catch (TransformException e) {
-						LOGGER.error(e);
-					}
+		if (features == null || features.size() == 0) {
+			// feature count == 0 Zoom to the full extend
+			return;
+		} else if (features.size() == 1) {
+
+			// feature count == 1 Just move the window to the point and zoom 'a
+			// bit'
+			Feature singleFeature = (Feature) features.iterator().next();
+
+			if (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;
+			}
+
+			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(e);
+				} catch (TransformException e) {
+					LOGGER.error(e);
 				}
+			}
 
-				Coordinate newLeftBottom = new Coordinate(
-						centre.x - width / 2., centre.y - height / 2.);
-				Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
-						centre.y + height / 2.);
+			Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
+					centre.y - height / 2.);
+			Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
+					centre.y + height / 2.);
 
-				Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
+			Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
 
-				setMapArea(newMapArea);
+			setMapArea(newMapArea);
 
+		} else {
+			ReferencedEnvelope fBounds = features.getBounds();
+
+			Envelope bounds;
+			if (!mapCRS.equals(fCRS)) {
+				bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
 			} else {
-				ReferencedEnvelope fBounds = features.getBounds();
-				
-				Envelope bounds;
-				if (! mapCRS.equals(fCRS)) {
-					bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
-				} else {
-					bounds = fBounds;
-				}
-				// BB umrechnen von Layer-CRS in Map-CRS
+				bounds = fBounds;
+			}
+			// BB umrechnen von Layer-CRS in Map-CRS
 
-				// Expand a bit
-				bounds.expandBy(bounds.getWidth() / 6., bounds
-						.getHeight() / 6.);
-				
-				setMapArea(bounds);
-			}
+			// Expand a bit
+			bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
+
+			setMapArea(bounds);
 		}
+	}
 
-
 }

Modified: trunk/src/skrueger/geotools/MapPaneToolBar.java
===================================================================
--- trunk/src/skrueger/geotools/MapPaneToolBar.java	2009-06-19 14:20:30 UTC (rev 150)
+++ trunk/src/skrueger/geotools/MapPaneToolBar.java	2009-06-19 16:22:29 UTC (rev 151)
@@ -8,6 +8,7 @@
 
 import javax.swing.AbstractAction;
 import javax.swing.AbstractButton;
+import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
@@ -724,7 +725,31 @@
 		 */
 		public MapPaneToolBarAction(int id, MapPaneToolBar toolBar,
 				String name, Icon icon) {
+			this (id, toolBar, name, icon, null);
+		}
+		
+		/**
+		 * Creates a new action.
+		 * 
+		 * @param id
+		 *            unique ID for the action
+		 * @param toolBar
+		 *            The {@link MapPaneToolBar} this action is made for
+		 * @param name
+		 *            description used for buttons or menus
+		 * @param icon
+		 *            icon used for buttons or menus
+		 * @param toolTip
+		 *            Tooltip to use for the button or menu
+		 */
+		public MapPaneToolBarAction(int id, MapPaneToolBar toolBar,
+				String name, Icon icon, String toolTip) {
 			super(name, icon);
+			
+			if (toolTip != null && !toolTip.trim().isEmpty()){
+				putValue(Action.SHORT_DESCRIPTION, toolTip);
+			}
+			
 			this.id = id;
 			this.toolBar = toolBar;
 		}

Modified: trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
===================================================================
--- trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java	2009-06-19 14:20:30 UTC (rev 150)
+++ trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java	2009-06-19 16:22:29 UTC (rev 151)
@@ -105,6 +105,10 @@
 	 */
 	@Override
 	public void propertyChange(PropertyChangeEvent evt) {
+
+		if (!isEnabled())
+			return;
+
 		if (!(evt instanceof StyledLayerSelectionEvent))
 			return;
 		StyledLayerSelectionEvent selEvt = (StyledLayerSelectionEvent) evt;
@@ -127,13 +131,20 @@
 		selectionChangeCausedByMe = false;
 	}
 
+	/**
+	 * Changes the Style of the {@link MapLayer} to reflect changes of the
+	 * selection.
+	 * 
+	 * @param newSelection
+	 *            A {@link Vector} of Feature-IDs that are selected.
+	 */
 	private void changeLayerStyle(final Vector<String> newSelection) {
 		Style selectionMapStyle = null;
 		try {
 			if (newSelection.isEmpty()) {
 
 				selectionMapStyle = styledMapLayer.getStyle();
-//				LOGGER.debug("NO SELECTION .. set to original style directly");
+				// LOGGER.debug("NO SELECTION .. set to original style directly");
 
 			} else {
 				LOGGER.debug("SELECTION .. change style");
@@ -150,8 +161,8 @@
 				// .createSelectionStyle(normalStyle, geoObj);
 				selectionMapStyle = StylingUtil
 						.createSelectionStyle(styledMapLayer.getGeoObject());
-//				selectionMapStyle = StylingUtil
-//				.createDefaultStyle(styledMapLayer.getGeoObject());
+				// selectionMapStyle = StylingUtil
+				// .createDefaultStyle(styledMapLayer.getGeoObject());
 
 				selectionMapStyle.getFeatureTypeStyles()[0]
 						.setName(SELECTION_STYLING);
@@ -196,7 +207,7 @@
 				} else {
 					newFeatureTypes = originalFeatureTypeStyles;
 				}
-				
+
 				// The last FTS is the selection FTS
 				newFeatureTypes = LangUtil.extendArray(newFeatureTypes,
 						selectionMapStyle.getFeatureTypeStyles());
@@ -212,25 +223,33 @@
 		}
 	}
 
+	/**
+	 * Used to synchronize {@link FeatureSelectedEvent}s with the
+	 * {@link StyledFeatureLayerSelectionModel}
+	 */
 	@Override
 	public void performMapPaneEvent(JMapPaneEvent e) {
 
+		// Ignore event if it is caused by us or the synchronizer is disabled.
+		if (!isEnabled() || selectionChangeCausedByMe)
+			return;
+
+		if (!(e instanceof FeatureSelectedEvent)) {
+			// LOGGER.debug("Ignoring event " + e);
+			return;
+		}
+
 		/**
-		 * Only listen to FeatureSelectionEvents if the appropriate tool is
+		 * Only listen to FeatureSelectedEvents if an appropriate tool is
 		 * selected.
 		 */
 		final int selectedTool = toolBar.getSelectedTool();
 		if (selectedTool != MapPaneToolBar.TOOL_SELECTION_ADD
 				&& selectedTool != MapPaneToolBar.TOOL_SELECTION_REMOVE
-				&& selectedTool != MapPaneToolBar.TOOL_SELECTION_CLEAR
 				&& selectedTool != MapPaneToolBar.TOOL_SELECTION_SET) {
 			return;
 		}
 
-		if (!(e instanceof FeatureSelectedEvent)) {
-			// LOGGER.debug("Ignoring event " + e);
-			return;
-		}
 		// only listen to events directly coming from JMapPane
 		// selection (ignore selections from FilterDialog)
 		if (e.getSourceObject() != this.mapPane)
@@ -238,48 +257,52 @@
 
 		FeatureSelectedEvent fse = (FeatureSelectedEvent) e;
 
-		// ignore event if it is caused by the DpLayerVectorSelectionModel
-		if (selectionChangeCausedByMe)
+		/**
+		 * Checking, that the FeatureSelectedEvent actually contains features from this layer 
+		 */
+		final String sourceID = fse.getSourceLayer().getTitle();
+		final String syncForID = mapLayer.getTitle();
+		if (sourceID != null && syncForID != null
+				&& !sourceID.equals(syncForID)){
+			LOGGER.debug("Ignoring a FeatureSelectedEvent from "+sourceID);
 			return;
+		}
+		
 
-		LOGGER.debug("Do event " + fse);
+		LOGGER.debug("do event " + fse);
 
 		// Avoid event circles in propertyChange(..)
 		selectionChangeCausedByMe = true;
 
-		if (selectedTool == MapPaneToolBar.TOOL_SELECTION_CLEAR) {
-			layerSelModel.clearSelection();
-		} else {
-			Collection<Feature> selectionResult = (Collection<Feature>) fse
-					.getSelectionResult();
+		Collection<Feature> selectionResult = (Collection<Feature>) fse
+				.getSelectionResult();
 
-			// reset the selection of the DpLayerSelectionModel
-			// layerSelModel.setValueIsAdjusting(true);
+		// reset the selection of the DpLayerSelectionModel
+		// layerSelModel.setValueIsAdjusting(true);
 
-			if (selectedTool == MapPaneToolBar.TOOL_SELECTION_ADD) {
-				layerSelModel.setValueIsAdjusting(true);
-				for (Feature f : selectionResult) {
-					layerSelModel.addSelection(f.getID());
-				}
-				layerSelModel.setValueIsAdjusting(false);
-			} else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_SET) {
-				layerSelModel.setValueIsAdjusting(true);
-				layerSelModel.clearSelection();
+		if (selectedTool == MapPaneToolBar.TOOL_SELECTION_ADD) {
+			layerSelModel.setValueIsAdjusting(true);
+			for (Feature f : selectionResult) {
+				layerSelModel.addSelection(f.getID());
+			}
+			layerSelModel.setValueIsAdjusting(false);
+		} else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_SET) {
+			layerSelModel.setValueIsAdjusting(true);
+			layerSelModel.clearSelection();
 
-				for (Feature f : selectionResult) {
-					layerSelModel.addSelection(f.getID());
-				}
+			for (Feature f : selectionResult) {
+				layerSelModel.addSelection(f.getID());
+			}
 
-				LOGGER.debug("Setting selection to " + selectionResult.size());
-				layerSelModel.setValueIsAdjusting(false);
-			} else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_REMOVE) {
-				layerSelModel.setValueIsAdjusting(true);
-				for (Feature f : selectionResult) {
-					layerSelModel.removeSelection(f.getID());
-				}
-				layerSelModel.setValueIsAdjusting(false);
+			LOGGER.debug("Setting selection to " + selectionResult.size());
+			layerSelModel.setValueIsAdjusting(false);
+		} else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_REMOVE) {
+			layerSelModel.setValueIsAdjusting(true);
+			for (Feature f : selectionResult) {
+				layerSelModel.removeSelection(f.getID());
 			}
-		} // els it's not a Clear Selection command
+			layerSelModel.setValueIsAdjusting(false);
+		}
 
 		// Show selected features in the map, which is not automatically done by
 		// the origin: FeatureSelectedEvent
@@ -288,4 +311,5 @@
 		// Danger of event circles in propertyChange(..) banned
 		selectionChangeCausedByMe = false;
 	}
+
 }

Modified: trunk/src/skrueger/geotools/selection/StyledLayerSelectionModelSynchronizer.java
===================================================================
--- trunk/src/skrueger/geotools/selection/StyledLayerSelectionModelSynchronizer.java	2009-06-19 14:20:30 UTC (rev 150)
+++ trunk/src/skrueger/geotools/selection/StyledLayerSelectionModelSynchronizer.java	2009-06-19 16:22:29 UTC (rev 151)
@@ -10,28 +10,55 @@
  * The {@link StyledLayerSelectionModelSynchronizer} is the super class for all
  * 
  * @author mojays
- *
+ * 
  * @param <E>
+ *            The concrete implementation of {@link StyledLayerSelectionModel}
+ *            that this Synchronizer works on.
  */
-public abstract class StyledLayerSelectionModelSynchronizer<E extends StyledLayerSelectionModel<?>> implements PropertyChangeListener{
+public abstract class StyledLayerSelectionModelSynchronizer<E extends StyledLayerSelectionModel<?>>
+		implements PropertyChangeListener {
 	protected final Logger LOGGER = Logger.getLogger(this.getClass());
-	
-	  /** Flag to avoid event circles between {@link DpLayerVectorSelectionModel}
-	   *  and {@link ListSelectionModel} of the feature table. */
-	  protected boolean selectionChangeCausedByMe = false;
-	  /** Holds the selection model of the layer to keep synchronized
-	   *  with the feature table. */
-	  protected final E layerSelModel;
 
-	  /**
-		 * Creates a new synchronizer
-		 * 
-		 * @param layerSelModel
-		 *            layer selection model to keep synchronized with 
-		 */
-		protected StyledLayerSelectionModelSynchronizer(E layerSelModel) {
+	/**
+	 * Flag to avoid event circles between {@link DpLayerVectorSelectionModel}
+	 * and {@link ListSelectionModel} of the feature table.
+	 */
+	protected boolean selectionChangeCausedByMe = false;
+	/**
+	 * Holds the selection model of the layer to keep synchronized with the
+	 * feature table.
+	 */
+	protected final E layerSelModel;
 
-			this.layerSelModel = layerSelModel;
-		}
-	  
+	/**
+	 * Allows to enable/disable the Synchronizer's functionality it.
+	 */
+	private boolean enabled = true;
+
+	/**
+	 * Creates a new synchronizer
+	 * 
+	 * @param layerSelModel
+	 *            layer selection model to keep synchronized with
+	 */
+	protected StyledLayerSelectionModelSynchronizer(E layerSelModel) {
+
+		this.layerSelModel = layerSelModel;
+	}
+
+	/**
+	 * Allows to disable this Synchronizer. Used to disable the selection
+	 * functionality if no corresponding dialog is open.
+	 * 
+	 * @param enabled
+	 *            <code>true</code> or <code>false</code>
+	 */
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+	}
+
+	public boolean isEnabled() {
+		return enabled;
+	}
+
 }



More information about the Schmitzm-commits mailing list