[Schmitzm-commits] r136 - in trunk/src: schmitzm/jfree schmitzm/jfree/chart schmitzm/jfree/chart/renderer schmitzm/jfree/chart/selection schmitzm/jfree/feature skrueger/geotools/selection

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Jun 3 21:53:35 CEST 2009


Author: mojays
Date: 2009-06-03 21:53:33 +0200 (Wed, 03 Jun 2009)
New Revision: 136

Added:
   trunk/src/schmitzm/jfree/DatasetMetaDataGroup.java
   trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java
   trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java
   trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java
   trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java
Removed:
   trunk/src/schmitzm/jfree/feature/Feature2DatasetItemDatasetGroup.java
Modified:
   trunk/src/schmitzm/jfree/JFreeChartUtil.java
   trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java
   trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java
   trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java
   trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java
   trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java
Log:
chart selection reorganized

Added: trunk/src/schmitzm/jfree/DatasetMetaDataGroup.java
===================================================================
--- trunk/src/schmitzm/jfree/DatasetMetaDataGroup.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/DatasetMetaDataGroup.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,59 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jfree.data.general.Dataset;
+import org.jfree.data.general.DatasetGroup;
+
+/**
+ * This {@link DatasetGroup} is raped! It provides the possibility to add
+ * individual meta to a {@link Dataset}.
+ * Because a {@link DatasetGroup} can be set to <b>every</b> {@link Dataset}, the
+ * mata data can be accessed everywhere the {@link Dataset} can be accessed,
+ * independently of the concrete {@link Dataset}.<br>
+ * <b>Note:</b><br>
+ * If a "real" {@link DatasetGroup} is set for a {@link Dataset}, the meta data
+ * is lost!!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class DatasetMetaDataGroup extends DatasetGroup {
+  /** Holds meta data objects. */
+  protected Map<String,Object> metadata = new HashMap<String, Object>();
+
+  /**
+   * Creates a new meta data object.
+   */
+  public DatasetMetaDataGroup() {
+    super("METADATA");
+  }
+
+  /**
+   * Sets some meta data.
+   * @param metadataKey    a key for the meta data object
+   * @param metadataObject the meta data
+   */
+  public void setMetaData(String metadataKey, Object metadataObject) {
+    metadata.put(metadataKey, metadataObject);
+  }
+  
+  /**
+   * Returns some meta data.
+   * @param metadataKey  the key of the meta data
+   */
+  public Object getMetaData(String metadataKey) {
+    return metadata.get(metadataKey);
+  }
+
+}

Modified: trunk/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -42,6 +42,10 @@
 import schmitzm.jfree.chart.renderer.SelectionXYLineAndShapeRenderer;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
+import schmitzm.jfree.feature.Feature2SeriesDatasetMapping;
+import schmitzm.jfree.feature.FeatureDatasetMetaData;
+import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
+import schmitzm.jfree.feature.FeatureSeriesDatasetSelectionModel;
 import schmitzm.lang.LangUtil;
 import schmitzm.lang.ResourceProvider;
 
@@ -62,11 +66,11 @@
   /**
    * Creates a {@link XYDataset} for 2 attributes of a {@link FeatureCollection}.
    * @param fc    a {@link FeatureCollection}
-   * @param key   a (unique) key for the {@link XYSeries} in the dataset
+   * @param seriesKey   a (unique) key for the {@link XYSeries} in the dataset
    * @param xAttr feature attribute used for the X-value
    * @param yAttr feature attribute used for the Y-value
    */
-  public static XYSeriesCollection createXYDataset(FeatureCollection fc, String key, String xAttr, String yAttr) {
+  public static XYSeriesCollection createXYDataset(FeatureCollection fc, String seriesKey, String xAttr, String yAttr) {
     // check data types of X- and Y-column
     AttributeType xType = fc.getSchema().getAttributeType(xAttr);
     if ( xType == null )
@@ -79,15 +83,21 @@
     if ( !Number.class.isAssignableFrom(yType.getBinding()) )
       throw new UnsupportedOperationException("Attribute must be numeric: "+yAttr);
     
-    XYSeriesCollection dataset   = new XYSeriesCollection();
-    FeatureIterator    fi        = fc.features();
-    XYSeries           xySeries  = new XYSeries(key,true,true);
+    
+    XYSeriesCollection           dataset   = new XYSeriesCollection();
+    Feature2SeriesDatasetMapping mapping   = new Feature2SeriesDatasetMapping(fc,dataset);
+    FeatureIterator              fi        = fc.features();
+    XYSeries                     xySeries  = new XYSeries(seriesKey,false,true);
     dataset.addSeries(xySeries);
-    for (;fi.hasNext();) {
+    dataset.setGroup( new FeatureDatasetMetaData(mapping) );
+    for (int i=0; fi.hasNext(); i++) {
       Feature f = fi.next();
       Number xValue = (Number)f.getAttribute(xAttr);
       Number yValue = (Number)f.getAttribute(yAttr);
       xySeries.add(xValue, yValue);
+      // Mapping between FID und data index in series
+      mapping.setMapping(f.getID(), seriesKey, i);
+      LOGGER.debug(f.getID() + " --> "+i);
     }
     return dataset;
   }
@@ -112,7 +122,12 @@
     XYPlot             plot             = new XYPlot(dataset, xAxis, yAxis, null);
     XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
     XYURLGenerator     urlGenerator     = new StandardXYURLGenerator();
-    XYItemRenderer     renderer         = new SelectionXYLineAndShapeRenderer(false, true);
+    XYItemRenderer     renderer         = new SelectionXYLineAndShapeRenderer(false, true) {
+      @Override
+      public FeatureSeriesDatasetSelectionModel createSelectionModel(XYDataset dataset) {
+        return new FeatureSeriesDatasetSelectionModel(dataset);
+      }
+    };
     
     renderer.setBaseToolTipGenerator(toolTipGenerator);
     renderer.setURLGenerator(urlGenerator);
@@ -177,8 +192,8 @@
   /**
    * @returns all {@link DatasetSelectionModel DatasetSelectionModels} that can be reached via the renderers of this chart. 
    */
-public static List<DatasetSelectionModel<?>> getDatasetSelectionModelFor(JFreeChart chart) {
-	ArrayList<DatasetSelectionModel<?>> renderers = new ArrayList<DatasetSelectionModel<?>>();
+public static List<FeatureDatasetSelectionModel<?>> getFeatureDatasetSelectionModelFor(JFreeChart chart) {
+	ArrayList<FeatureDatasetSelectionModel<?>> renderers = new ArrayList<FeatureDatasetSelectionModel<?>>();
 	
 	
 	Plot plot = chart.getPlot();
@@ -188,8 +203,9 @@
 
 		for (int i = 0; i < xyplot.getRendererCount(); i++) {
 			XYItemRenderer renderer = xyplot.getRenderer(i);
-			if (renderer instanceof DatasetSelectionModelProvider){
-				renderers.add( ((DatasetSelectionModelProvider)renderer).getSelectionModel());
+			if (renderer instanceof DatasetSelectionModelProvider &&
+			    ((DatasetSelectionModelProvider)renderer).getSelectionModel() instanceof FeatureDatasetSelectionModel){
+				renderers.add( (FeatureDatasetSelectionModel)((DatasetSelectionModelProvider)renderer).getSelectionModel());
 			}
 		}
 	}

Modified: trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -12,8 +12,10 @@
 
 import java.awt.event.MouseEvent;
 import java.awt.geom.Rectangle2D;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Vector;
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
@@ -104,6 +106,9 @@
       public void selectionPerformed(Rectangle2D selectedArea, Set<XYItemEntity> selectedEntities) {
         LOGGER.debug( selectedEntities.size() + " objects selected" );
         
+        // remember all changed selection models to reset "valueAdjusting"
+        // property at the end
+        Set<DatasetSelectionModel<?>> changedModels = new HashSet<DatasetSelectionModel<?>>();
         Plot plot = getChart().getPlot();
         for (Iterator<XYItemEntity> i = selectedEntities.iterator(); i.hasNext(); ) {
           XYItemEntity             e        = i.next();
@@ -114,11 +119,19 @@
            if ( renderer instanceof DatasetSelectionModelProvider )
              selModel = ((DatasetSelectionModelProvider<?>)renderer).getSelectionModel();
           }
-          
+
+          // set "valueAdjusting" property for selection model and remember the
+          // model to reset the property at the end
+          if ( selModel != null ) {
+            selModel.setValueIsAdjusting(true);
+            changedModels.add(selModel);
+          }
+          // perform the selection change
           if ( selModel instanceof SeriesDatasetSelectionModel ) {
-            int series = e.getSeriesIndex();
-            int item   = e.getItem();
-            ((SeriesDatasetSelectionModel)selModel).changeItemSelection(series, item);
+            int series           = e.getSeriesIndex();
+            Comparable seriesKey = e.getDataset().getSeriesKey(series);
+            int item             = e.getItem();
+            ((SeriesDatasetSelectionModel)selModel).changeItemSelection(seriesKey, item);
           } else {
             if ( selModel == null )
               LOGGER.warn("Selection not supported for dataset: "+LangUtil.getSimpleClassName(dataset));
@@ -126,8 +139,12 @@
               LOGGER.error("Selection not yet implemented for selection model: "+LangUtil.getSimpleClassName(selModel));
           }
         }
-        
+        // refresh the visualization
         refresh();
+        // reset the "valueAdjusting" property to inform listeners
+        // about the selection change
+        for (DatasetSelectionModel<?> selModel : changedModels)
+          selModel.setValueIsAdjusting(false);
       }
       
     };

Modified: trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -41,7 +41,7 @@
  * <b>Note:</b><br>
  * An adequate {@link SeriesDatasetSelectionModel} is automatically
  * created when a new {@link Plot} is set. Manually calling {@link #setSelectionModel(SeriesDatasetSelectionModel)}
- * is usually not necessary. Overwrite {@link #createSelectionModel()} to
+ * is usually not necessary. Overwrite {@link #createAndSetSelectionModel()} to
  * avoid this behavior.<br>
  * If no selection model is set, the behavior of this renderer is exactly
  * like the super class.
@@ -107,16 +107,26 @@
    * according to the {@link Dataset} of the current {@link Plot}. Automatically
    * called by {@link #setPlot(XYPlot)}.<br>
    * Sets the selection model to {@code null} if the renderer is not
-   * connected to a plot or the plot contains no dataset. 
+   * connected to a plot or the plot contains no dataset.
+   * @see #createSelectionModel(XYDataset) 
    */
-  public void createSelectionModel() {
+  public void createAndSetSelectionModel() {
     XYPlot    plot       = getPlot();
     XYDataset newDataset = (plot == null) ? null : plot.getDataset();
     if ( getSelectionModel() == null || getSelectionModel().getDataset() != newDataset )
-      setSelectionModel( newDataset != null ? new SeriesDatasetSelectionModel(newDataset) : null );
+      setSelectionModel( newDataset != null ? createSelectionModel(newDataset) : null );
   }
-  
+
   /**
+   * Creates an adequate {@link SeriesDatasetSelectionModel}
+   * according to the given {@link Dataset}. Subclasses can overwrite this
+   * method to create an alternative {@link SeriesDatasetSelectionModel}.
+   */
+  public SeriesDatasetSelectionModel createSelectionModel(XYDataset dataset) {
+    return new SeriesDatasetSelectionModel(dataset);
+  }
+
+  /**
    * Returns the color, the selected data <b>of the primary series</b>
    * is rendered with.
    * @return {@code null} if no selection color is defined
@@ -162,7 +172,7 @@
    */
   public void setPlot(XYPlot plot) {
     super.setPlot(plot);
-    createSelectionModel();
+    createAndSetSelectionModel();
   }
 
   /**
@@ -191,9 +201,17 @@
     // rendering process
     if ( getSelectionModel() != null ) {
       Paint selPaint  = getSelectionPaint(series);
-      if ( selPaint != null )
-        setSeriesPaint( series, selectionModel.isItemSelected(series, item) ? selPaint : origPaint, false );
-      else
+      if ( selPaint != null ) {
+        if ( item == 80 ) {
+          item ++;
+          item --;
+        }
+        Comparable seriesKey = dataset.getSeriesKey(series);
+        if ( selectionModel.isItemSelected(seriesKey, item) )
+          setSeriesPaint( series, selPaint, false );
+        else
+          setSeriesPaint( series, origPaint, false );
+      } else
         LOGGER.warn("No selection paint set for series "+series+". Series is rendererd normally.");
     } else
       LOGGER.debug("No selection model set for renderer. All series rendererd normally.");

Modified: trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -124,11 +124,13 @@
   }
   
   /**
-   * Informs all listeners about a general selection change.
+   * Informs all listeners about a general selection change. Does nothing
+   * if {@link #getValueIsAdjusting()} is {@code true}.
    */
   public void refreshSelection() {
-    for (DatasetSelectionListener l : listeners)
-      l.selectionChanged( createSelectionChangeEvent() );
+    if ( !getValueIsAdjusting() )
+      for (DatasetSelectionListener l : listeners)
+        l.selectionChanged( createSelectionChangeEvent() );
   }
   
   /**

Modified: trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -17,11 +17,20 @@
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
 public class DatasetSelectionChangeEvent extends ChangeEvent {
+  
   /**
    * Creates a new event.
    * @param source
+   * @param selModel the selection model
    */
-  public DatasetSelectionChangeEvent(Object source) {
+  public DatasetSelectionChangeEvent(DatasetSelectionModel<?> source) {
     super(source);
   }
+  
+  /**
+   * Returns the initiating {@link DatasetSelectionModel}.
+   */
+  public DatasetSelectionModel<?> getSource() {
+    return (DatasetSelectionModel<?>)super.getSource();
+  }
 }

Modified: trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -20,7 +20,7 @@
 import org.jfree.data.general.SeriesDataset;
 
 /**
- * This selection model maintains whether items of a {@link SeriesDataset} is selected
+ * This selection model maintains whether items of a {@link SeriesDataset} are selected
  * in a chart or not.
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
@@ -68,6 +68,9 @@
       selectedIdx.add(item);
     else
       selectedIdx.remove(item);
+    
+    // inform all listeners about the selection change
+    refreshSelection();
   }
   
   /**
@@ -91,6 +94,8 @@
       selectedIdx.clear();
     // clear the series map
     selectedSeriesIdx.clear();
+    // inform all listeners about the selection change
+    refreshSelection();
   }
   
   /**

Deleted: trunk/src/schmitzm/jfree/feature/Feature2DatasetItemDatasetGroup.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2DatasetItemDatasetGroup.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/Feature2DatasetItemDatasetGroup.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -1,120 +0,0 @@
-/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
-
-    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
-    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
-
-    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
-    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
-    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
- **/
-
-package schmitzm.jfree.feature;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.geotools.feature.Feature;
-import org.geotools.feature.FeatureCollection;
-import org.jfree.data.general.Dataset;
-import org.jfree.data.general.DatasetGroup;
-
-/**
- * This {@link DatasetGroup} is raped! It implements the mapping between
- * an dataset item (point in chart) and the corresponding {@link Feature}.
- * Because a {@link DatasetGroup} can be set to <b>every</b> {@link Dataset}, the
- * mapping can be accessed everywhere the {@link Dataset} can be accessed,
- * independently of the concrete {@link Dataset}. 
- * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
- */
-public class Feature2DatasetItemDatasetGroup<E extends Comparable> extends DatasetGroup {
-  /** Holds the {@link FeatureCollection} for the mapping */
-  protected FeatureCollection featureCollection = null;
-  /** Holds the data item (E) for each feature ID (String). */
-  protected Map<String,E> fid2did = new HashMap<String, E>();
-  /** Holds the feature ID (String) for each data item (E). */
-  protected Map<E,String> did2fid = new HashMap<E, String>();
-  
-  /**
-   * Creates a "mapping" dataset group with a default id. 
-   */
-  public Feature2DatasetItemDatasetGroup() {
-    this(null);
-  }
-
-  /**
-   * Creates a "mapping" dataset group with a default id. 
-   * @param fc a {@link FeatureCollection} (can be {@code null}) 
-   */
-  public Feature2DatasetItemDatasetGroup(FeatureCollection fc) {
-    super();
-    this.featureCollection = fc;
-  }
-
-  /**
-   * Creates a "mapping" dataset group.
-   * @param fc a {@link FeatureCollection}
-   * @param id id for the group (can be {@code null})
-   */
-  public Feature2DatasetItemDatasetGroup(FeatureCollection fc, String id) {
-    super(id);
-    this.featureCollection = fc;
-  }
-  
-  /**
-   * Returns the {@link FeatureCollection} the mapping is provided for.
-   */
-  public FeatureCollection getFeatureCollection() {
-    return featureCollection;
-  }
-  
-  /**
-   * Sets the mapping between a feature ID and a dataset item.
-   * @param fID    feature ID
-   * @param dataID dataset item
-   */
-  public void setMapping(String fID, E dataID) {
-    fid2did.put(fID, dataID);
-    did2fid.put(dataID,fID);
-  }
-  
-  /**
-   * Removes the mapping between a feature ID and a dataset item.
-   * @param fID    feature ID
-   */
-  public void removeMappingForFeatureID(String fID) {
-    E dataID = fid2did.remove(fID);
-    if ( dataID != null )
-      did2fid.remove(dataID);
-  }
-  
-  /**
-   * Removes the mapping between a feature ID and a dataset item.
-   * @param dateID data item
-   */
-  public void removeMappingForDataItem(E dataID) {
-    String fID = did2fid.remove(dataID);
-    if ( fID != null )
-      fid2did.remove(fID);
-  }
-
-  /**
-   * Returns the data item for a given feature ID.
-   * @param fID a feature ID
-   * @return {@code null} if no data item is registered for the feature ID
-   */
-  public E getDataID(String fID) {
-    return fid2did.get(fID);
-  }
-  
-  /**
-   * Returns feature ID for a given data item.
-   * @param dataID a date item
-   * @return {@code null} if feature ID is registered for the data item
-   */
-  public String getFeatureID(E itemID) {
-    return did2fid.get(itemID);
-  }
- 
-
-}

Added: trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,86 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree.feature;
+
+import org.geotools.feature.Feature;
+import org.geotools.feature.FeatureCollection;
+import org.jfree.data.general.Dataset;
+
+/**
+ * This class implements the mapping between {@link Dataset} items (points in chart)
+ * and the corresponding {@link Feature Features}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public abstract class Feature2DatasetMapping<E, F extends Dataset> {
+  /** Holds the {@link FeatureCollection} for the mapping */
+  protected FeatureCollection featureCollection = null;
+
+  /** Holds the {@link Dataset} for the mapping */
+  protected F dataset = null;
+
+  /**
+   * Creates a mapping. 
+   * @param fc a {@link FeatureCollection} (can be {@code null}) 
+   */
+  public Feature2DatasetMapping(FeatureCollection fc, F dataset) {
+    this.featureCollection = fc;
+    this.dataset           = dataset;
+  }
+
+  /**
+   * Returns the {@link FeatureCollection} the mapping is provided for.
+   */
+  public FeatureCollection getFeatureCollection() {
+    return featureCollection;
+  }
+
+  /**
+   * Returns the {@link Dataset} the mapping is provided for.
+   */
+  public F getDataset() {
+    return dataset;
+  }
+
+  /**
+   * Sets the mapping between a feature ID and a dataset item.
+   * @param featureID    feature ID
+   * @param itemID       defines the dataset item
+   */
+  public abstract void setMapping(String featureID, E itemID);
+  
+  /**
+   * Removes the mapping of a feature ID.
+   * @param fID feature ID
+   */
+  public abstract void removeMappingForFeatureID(String fID);
+  
+  /**
+   * Removes the mapping for a dataset item.
+   * @param itemID    dataset item
+   */
+  public abstract void removeMappingForDataItem(E itemID);
+
+  /**
+   * Returns the data items for a given feature ID.
+   * @param fID a feature ID
+   * @return {@code null} if no data item is registered for the feature ID
+   */
+  public abstract E getDataID(String fID);
+  
+  /**
+   * Returns the feature ID for a given data item.
+   * @param itemID a data item
+   * @return {@code null} if no feature ID is registered for the data item
+   */
+  public abstract String getFeatureID(E itemID);
+  
+}

Added: trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,198 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree.feature;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.geotools.feature.Feature;
+import org.geotools.feature.FeatureCollection;
+import org.jfree.data.general.SeriesDataset;
+
+/**
+ * This class implements the mapping between {@link SeriesDataset} items (points in chart)
+ * and the corresponding {@link Feature Features}.
+ * The structure of this mapping assumes that there can be multiple
+ * dataset items for one feature (e.g. in each series), but only one feature
+ * for each dataset item.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class Feature2SeriesDatasetMapping extends Feature2DatasetMapping<Integer,SeriesDataset> {
+  /** Holds the data items ({@code Map<SeriesKey,ItemIndex>})
+   *  for each feature ID (String). */
+  protected Map<String,Map<Comparable,Integer>> fid2did = new HashMap<String, Map<Comparable,Integer>>();
+  /** Holds for each series the feature ID (String) for each data item. */
+  protected Map<Comparable,Map<Integer,String>> did2fid = new HashMap<Comparable,Map<Integer,String>>();
+  
+  /**
+   * Creates a mapping. 
+   * @param fc a {@link FeatureCollection} (can be {@code null})
+   * @param dataset a {@link SeriesDataset} 
+   */
+  public Feature2SeriesDatasetMapping(FeatureCollection fc, SeriesDataset dataset) {
+    super(fc, dataset);
+  }
+
+  /**
+   * Returns the key of the primary series.
+   */
+  public Comparable getPrimarySeriesKey() {
+    return dataset.getSeriesKey(0);
+  }
+  
+  /**
+   * Sets the mapping between a feature ID and a dataset item IN THE
+   * PRIMARY SERIES.
+   * @param featureID    feature ID
+   * @param itemID       defines the dataset item
+   */
+  public void setMapping(String featureID, Integer itemID) {
+    setMapping(featureID, null, itemID);
+  }
+
+  /**
+   * Sets the mapping between a feature ID and a dataset item.
+   * @param featureID    feature ID
+   * @param seriesKey    defines the series of corresponding dataset item (if
+   *                     {@code null} the primary series is used)
+   * @param itemID       defines the dataset item
+   */
+  public void setMapping(String featureID, Comparable seriesKey, int itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    // Mapping FeatureID --> (Series/Index)
+    Map<Comparable,Integer> itemIDs = fid2did.get(featureID);
+    if ( itemIDs == null ) {
+      itemIDs = new HashMap<Comparable, Integer>();
+      fid2did.put(featureID, itemIDs);
+    }
+    itemIDs.put(seriesKey, itemID);
+    
+    // Mapping (Series/Index) --> FeatureID
+    Map<Integer,String> featureIDs = did2fid.get(seriesKey);
+    if ( featureIDs == null ) {
+      featureIDs = new HashMap<Integer, String>();
+      did2fid.put(seriesKey, featureIDs);
+    }
+    featureIDs.put(itemID, featureID);
+  }
+  
+  /**
+   * Removes the mapping of a feature ID.
+   * @param fID feature ID
+   */
+  public void removeMappingForFeatureID(String fID) {
+    // remove mapping FeatureID --> (Series/Index)
+    Map<Comparable, Integer> itemIDs = fid2did.remove(fID);
+
+    // remove mapping (Series/Index) --> FeatureID
+    // for all item IDs referencing to the feature ID
+    for (Comparable seriesKey : itemIDs.keySet()) {
+      Map<Integer, String> featureIDs = did2fid.get(seriesKey);
+      for (Integer itemID : itemIDs.values())
+        featureIDs.remove(itemID);
+    }
+  }
+  
+  /**
+   * Removes the mapping for a dataset item IN THE
+   * PRIMARY SERIES.
+   * @param itemID    dataset item
+   */
+  public void removeMappingForDataItem(Integer itemID) {
+    removeMappingForDataItem(null,itemID);
+  }
+
+  /**
+   * Removes the mapping for a dataset item.
+   * @param seriesKey defines the series of the dataset item (if
+   *                  {@code null} the primary series is used)
+   * @param itemID    dataset item
+   */
+  public void removeMappingForDataItem(Comparable seriesKey, Integer itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    // remove mapping (Series/Index) --> FeatureID 
+    Map<Integer, String> featureIDs = did2fid.get(seriesKey);
+    String fID = null;
+    if ( featureIDs != null )
+      fID = featureIDs.remove(itemID);
+    
+    // remove mapping FeatureID --> (Series/Index)
+    if ( fID != null ) {
+      Map<Comparable, Integer> itemIDs = fid2did.remove(fID);
+      itemIDs.remove(seriesKey);
+    }  
+  }
+
+  /**
+   * Returns the data items for a given feature IN THE
+   * PRIMARY SERIES.
+   * @param fID a feature ID
+   * @return {@code null} if no data item is registered for the feature ID
+   */
+  public Integer getDataID(String fID) {
+    return getDataID(null,fID);
+  }
+
+  /**
+   * Returns the data items for a given feature ID.
+   * @param fID a feature ID
+   * @param seriesKey defines the series of the dataset item (if
+   *                  {@code null} the primary series is used)
+   * @return {@code null} if no data item is registered for the feature ID
+   */
+  public Integer getDataID(Comparable seriesKey, String fID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    Map<Comparable,Integer> seriesIDs = getDataIDs(fID);
+    if ( seriesIDs != null )
+      return seriesIDs.get(seriesKey);
+    return null;
+  }
+
+
+  /**
+   * Returns the data items (of all series) for a given feature ID.
+   * @param fID a feature ID
+   * @return {@code null} if no data item is registered for the feature ID
+   */
+  public Map<Comparable,Integer> getDataIDs(String fID) {
+    return fid2did.get(fID);
+  }
+  
+  /**
+   * Returns the feature ID for a given data item IN THE
+   * PRIMARY SERIES.
+   * @param itemID a data item
+   * @return {@code null} if no feature ID is registered for the data item
+   */
+  public String getFeatureID(Integer itemID) {
+    return getFeatureID(null,itemID);
+  }
+
+  /**
+   * Returns the feature ID for a given data item.
+   * @param seriesKey defines the series of the dataset item  (if
+   *                  {@code null} the primary series is used)
+   * @param itemID a data item
+   * @return {@code null} if no feature ID is registered for the data item
+   */
+  public String getFeatureID(Comparable seriesKey, Integer itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    Map<Integer,String> featureIDs = did2fid.get(seriesKey);
+    if ( featureIDs != null )
+      return featureIDs.get(itemID); 
+    return null;
+  }
+}

Added: trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,41 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree.feature;
+
+import schmitzm.jfree.DatasetMetaDataGroup;
+
+/**
+ * Meta data for dataset whose data bases on features.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class FeatureDatasetMetaData extends DatasetMetaDataGroup {
+  /** Meta data ID for mapping between features and chart data. */
+  public static String KEY_MAPPING = "ID_MAPPING";
+  
+  /**
+   * Creates a new meta data object for features. 
+   * @param mapping mapping between features and chart data
+   */
+  public FeatureDatasetMetaData(Feature2DatasetMapping<?,?> mapping) {
+    super();
+    setMetaData(KEY_MAPPING, mapping);
+  }
+  
+  /**
+   * Returns the mapping between features and the corresponding
+   * dataset items.
+   */
+  public Feature2DatasetMapping<?,?> getMapping() {
+    return (Feature2DatasetMapping<?,?>)getMetaData(KEY_MAPPING);
+  }
+  
+}

Added: trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,49 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+package schmitzm.jfree.feature;
+
+import java.util.Set;
+
+import org.jfree.data.general.Dataset;
+
+import schmitzm.jfree.chart.selection.DatasetSelectionModel;
+
+/**
+ * This selection model maintains whether items of a {@link Dataset} corresponding
+ * to features are selected in a chart or not.
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ */
+public interface FeatureDatasetSelectionModel<E extends Dataset> extends DatasetSelectionModel<E> {
+  /**
+   * Checks if the data item of a feature is selected.
+   * @param fID  feature ID
+   */
+  public boolean isFeatureSelected(String fID);
+  
+  /**
+   * Sets whether the data item of a feature is selected or not.
+   * @param fID  feature ID
+   * @param selected  flag to (de)select the item
+   */
+  public void setItemSelected(String fID, boolean selected);
+  
+  /**
+   * Changes the selection of the data item of a feature.
+   * @param fID  feature ID
+   * @return {@code true} if the item changed to selected 
+   */
+  public boolean changeItemSelection(String fID);
+  
+  /**
+   * Returns the IDs of the selected features.
+   */
+  public Set<String> getSelectedFeatures();
+}

Added: trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -0,0 +1,135 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree.feature;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jfree.data.general.DatasetGroup;
+import org.jfree.data.general.SeriesDataset;
+
+import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
+import schmitzm.lang.LangUtil;
+
+/**
+ * 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class FeatureSeriesDatasetSelectionModel extends SeriesDatasetSelectionModel implements FeatureDatasetSelectionModel<SeriesDataset> {
+  /** Holds the mapping between features and the corresponding item indices
+   *  of each series. */
+  protected Feature2SeriesDatasetMapping mapping = null;
+  
+  /**
+   * Creates a new selection model.
+   * @param dataset a dataset providing a {@link FeatureSeriesDatasetSelectionModel FeatureSeriesDatasetSelectionModel<Map<Comparable,Integer>>}
+   *                as dataset group
+   */
+  public FeatureSeriesDatasetSelectionModel(SeriesDataset dataset) {
+    super(dataset);
+    // DatasetGroup must provide meta data (containing the Feature<->DataItem mapping)
+    DatasetGroup group = dataset.getGroup();
+    if ( group == null || !(group instanceof FeatureDatasetMetaData) )
+      throw new UnsupportedOperationException("Dataset must provide FeatureDatasetMetaData as DatasetGroup: "+LangUtil.getSimpleClassName(group));
+    FeatureDatasetMetaData metadata = (FeatureDatasetMetaData)group;
+    // Meta data must provide Feature2SeriesDatasetMapping
+    Feature2DatasetMapping<?,?> mapping = metadata.getMapping();
+    if ( mapping == null || !(mapping instanceof Feature2SeriesDatasetMapping) )
+      throw new UnsupportedOperationException("Mapping (provided by FeatureDatasetMetaData) must be a Feature2SeriesDatasetMapping: "+LangUtil.getSimpleClassName(mapping));
+    this.mapping = (Feature2SeriesDatasetMapping)mapping;
+  }
+
+  /**
+   * Checks if the data item of a feature is selected in any series.
+   * @param fID  feature ID
+   */
+  public boolean isFeatureSelected(String fID) {
+    for (int i=0; i<dataset.getSeriesCount(); i++)
+      if ( isFeatureSelected(fID,dataset.getSeriesKey(i)) )
+        return true;
+    return false;
+    
+  }
+  
+  /**
+   * Checks if the data item of a feature is selected.
+   * @param fID  feature ID
+   * @param seriesKey series to check for the feature ID
+   */
+  public boolean isFeatureSelected(String fID, Comparable seriesKey) {
+    Integer dataItem = mapping.getDataID(seriesKey,fID);
+    return dataItem != null && isItemSelected(seriesKey, dataItem);
+  }
+
+  /**
+   * Sets the selection state for a feature in all dataset series.
+   * @param fID  feature ID
+   * @param selected  flag to (de)select the item
+   */
+  public void setItemSelected(String fID, boolean selected) {
+    for (int i=0; i<dataset.getSeriesCount(); i++)
+      setItemSelected(fID, dataset.getSeriesKey(i), selected);
+  }
+  
+  /**
+   * Sets whether the data item of a feature is selected or not.
+   * @param fID  feature ID
+   * @param seriesKey series to set the selection in
+   * @param selected  flag to (de)select the item
+   */
+  public void setItemSelected(String fID, Comparable seriesKey, boolean selected) {
+    Integer dataItem = mapping.getDataID(seriesKey,fID);
+    if ( dataItem == null )
+      LOGGER.warn("Feature unknown in Feature2DatasetItemDatasetGroup: "+fID);
+    else
+      setItemSelected(seriesKey, dataItem, selected);
+  }
+
+  /**
+   * Changes the selection of the data item of a feature in all
+   * series.
+   * @param fID  feature ID
+   * @return {@code true} if at least one item changed to selected 
+   */
+  public boolean changeItemSelection(String fID) {
+    boolean anyChangedToTrue = false;
+    for (int i=0; i<dataset.getSeriesCount(); i++)
+      anyChangedToTrue |= changeItemSelection(fID, dataset.getSeriesKey(i));
+    return anyChangedToTrue;
+  }
+
+  /**
+   * Changes the selection of the data item of a feature.
+   * @param fID  feature ID
+   * @param seriesKey series to change the selection in
+   * @return {@code true} if the item changed to selected 
+   */
+  public boolean changeItemSelection(String fID, Comparable seriesKey) {
+    Integer dataItem = mapping.getDataID(seriesKey,fID);
+    return changeItemSelection(seriesKey, dataItem);
+  }
+
+  /**
+  * Returns the IDs of the selected features (in any series).
+  */
+  public Set<String> getSelectedFeatures() {
+    Set<String> selectedFIDs = new HashSet<String>();
+    for (Comparable seriesKey : selectedSeriesIdx.keySet()) 
+      for (Integer selIdx : selectedSeriesIdx.get(seriesKey)) {
+        String selFID = mapping.getFeatureID(seriesKey,selIdx);
+        selectedFIDs.add(selFID);
+      }
+    
+    return selectedFIDs;
+  }
+
+}

Modified: trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java
===================================================================
--- trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java	2009-05-30 20:26:57 UTC (rev 135)
+++ trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java	2009-06-03 19:53:33 UTC (rev 136)
@@ -15,23 +15,14 @@
 import java.beans.PropertyChangeListener;
 import java.util.Vector;
 
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.plaf.basic.BasicTreeUI.SelectionModelPropertyChangeHandler;
-
-import org.jfree.chart.JFreeChart;
 import org.jfree.data.general.Dataset;
-import org.jfree.data.general.SeriesDataset;
-import org.jfree.data.xy.XYSeriesCollection;
 
-import schmitzm.geotools.gui.FeatureCollectionTableModel;
 import schmitzm.jfree.chart.renderer.SelectionRenderer;
+import schmitzm.jfree.chart.selection.DatasetSelectionChangeEvent;
 import schmitzm.jfree.chart.selection.DatasetSelectionListener;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
-import schmitzm.jfree.chart.selection.DatasetSelectionChangeEvent;
-import schmitzm.jfree.feature.Feature2DatasetItemDatasetGroup;
+import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
 
 /**
  * This class keeps the selection of a {@link Dataset} (based on feature
@@ -54,10 +45,8 @@
                                         implements DatasetSelectionListener {
 
   /** Holds the chart datset to keep synchronized with the layer selection model. */
-  protected DatasetSelectionModel<?> datasetSelModel = null;
-  /** Hold the mapping between feature IDs and dataset items. */
-  protected Feature2DatasetItemDatasetGroup<?> mapping = null; 
-  
+  protected FeatureDatasetSelectionModel<?> datasetSelModel = null;
+
   /**
    * Creates a new synchronizer.
    * @param layerSelModel
@@ -67,19 +56,13 @@
    *            dataset selection model to keep synchronized with the layer
    *            selection model
    */
-  public ChartSelectionSynchronizer(StyledFeatureLayerSelectionModel layerSelModel, DatasetSelectionModel<?> datasetSelModel) {
+  public ChartSelectionSynchronizer(StyledFeatureLayerSelectionModel layerSelModel, FeatureDatasetSelectionModel<?> datasetSelModel) {
     super(layerSelModel);
-    // the dataset selection model must provide a mapping
-    // to the feature IDs
-    if ( datasetSelModel.getDataset() == null ||
-         !(datasetSelModel.getDataset().getGroup() instanceof Feature2DatasetItemDatasetGroup) )
-      throw new UnsupportedOperationException("Dataset must provide a Feature2DatasetItemDatasetGroup as DatasetGroup.");
     this.datasetSelModel = datasetSelModel;
-    this.mapping         = (Feature2DatasetItemDatasetGroup<?>)datasetSelModel.getDataset().getGroup();
   }
 
   /**
-   * Called by {@link StyledLayerSelectionModel} when a the selection on other
+   * Called by {@link StyledLayerSelectionModel} when the selection on other
    * selection components (map, table, ...) has changed. When calling this
    * method changes the dataset selection according to the
    * {@link StyledLayerSelectionModel} selection.
@@ -105,25 +88,40 @@
 
     datasetSelModel.setValueIsAdjusting(true);
     datasetSelModel.clearSelection();
-    
-    for (String fID : newSelection) {
-      Comparable dataID = mapping.getDataID(fID);
-      if (dataID != null ) {
-//TODO: Fallunterscheidung zwischen den unterschiedlichen DatasetSelectionModel-Typen!!
-      } else {
-          LOGGER.warn("Something that is not visible in the chart should be selected");
-      }
-    }
+    for (String fID : newSelection)
+      datasetSelModel.setItemSelected(fID, true);
     datasetSelModel.setValueIsAdjusting(false); // event is fired autmatically!
 
     // Danger of event circles in valueChanged(..) banned
     selectionChangeCausedByMe = false;
   }
 
+  /**
+   * Called when the chart selection is changed by the user. When calling this
+   * method changes the selection of the {@link StyledLayerSelectionModel}.
+   * @param evt an event
+   */
   @Override
-  public void selectionChanged(DatasetSelectionChangeEvent e) {
-    // TODO Auto-generated method stub
-    
+  public void selectionChanged(DatasetSelectionChangeEvent evt) {
+    // ignore event if it is part of multiple events
+    if (evt != null && evt.getSource().getValueIsAdjusting())
+        return;
+    // ignore event if it is caused by the ChartSelectionSynchronizer
+    if (selectionChangeCausedByMe)
+        return;
+
+    // Avoid event circles in propertyChange(..)
+    selectionChangeCausedByMe = true;
+
+    // reset the selection of the DpLayerSelectionModel
+    layerSelModel.setValueIsAdjusting(true);
+    layerSelModel.clearSelection();
+    for (String featureID : datasetSelModel.getSelectedFeatures())
+      layerSelModel.addSelection(featureID);
+    layerSelModel.setValueIsAdjusting(false);
+
+    // Danger of event circles in propertyChange(..) banned
+    selectionChangeCausedByMe = false;
   }
   
 



More information about the Schmitzm-commits mailing list