[Schmitzm-commits] r289 - in trunk/src: schmitzm/geotools/gui schmitzm/jfree schmitzm/jfree/chart schmitzm/jfree/chart/renderer schmitzm/jfree/chart/selection schmitzm/jfree/feature schmitzm/jfree/feature/style skrueger/geotools/selection skrueger/swing

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Aug 4 00:29:38 CEST 2009


Author: mojays
Date: 2009-08-04 00:29:36 +0200 (Tue, 04 Aug 2009)
New Revision: 289

Added:
   trunk/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java
   trunk/src/schmitzm/jfree/chart/selection/CategoryDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/feature/Feature2CategoryDatasetMapping.java
   trunk/src/schmitzm/jfree/feature/FeatureCategoryDatasetSelectionModel.java
Modified:
   trunk/src/schmitzm/geotools/gui/JMapPane.java
   trunk/src/schmitzm/jfree/JFreeChartUtil.java
   trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java
   trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java
   trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
   trunk/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java
   trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java
   trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModel.java
   trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java
   trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java
   trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java
   trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java
   trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java
   trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
   trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java
   trunk/src/skrueger/swing/TranslationEditJPanel.java
Log:
Chart-Selection highlighting for CategoryDatasets.
DatasetSelectionModel and Feature2DatasetMapping parameterized with 3 data types (Dataset, SeriesKey type, ItemKey type).
Imports organized.

Modified: trunk/src/schmitzm/geotools/gui/JMapPane.java
===================================================================
--- trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -60,6 +60,7 @@
 import org.geotools.coverage.grid.GridGeometry2D;
 import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
 import org.geotools.coverage.grid.io.AbstractGridFormat;
+import org.geotools.coverage.io.AbstractGridCoverageReader;
 import org.geotools.data.FeatureSource;
 import org.geotools.data.memory.MemoryFeatureCollection;
 import org.geotools.factory.GeoTools;

Modified: trunk/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -33,7 +33,6 @@
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Vector;
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
@@ -77,13 +76,11 @@
 import org.jfree.data.xy.XYSeriesCollection;
 
 import schmitzm.jfree.chart.renderer.SelectionRenderer;
-import schmitzm.jfree.chart.renderer.SelectionXYLineAndShapeRenderer;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.style.BasicChartStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
 import schmitzm.jfree.chart.style.ChartType;
-import schmitzm.jfree.feature.FeatureSeriesDatasetSelectionModel;
 import schmitzm.lang.LangUtil;
 import schmitzm.lang.ResourceProvider;
 
@@ -324,7 +321,7 @@
    * @return {@code null} if there is no {@link SelectionRenderer} defined
    *         for the dataset
    */
-  public static DatasetSelectionModel<?> getSelectionModelForDataset(Plot plot, Dataset dataset) {
+  public static DatasetSelectionModel<?,?,?> getSelectionModelForDataset(Plot plot, Dataset dataset) {
     SelectionRenderer<?> selRenderer = getSelectionRendererForDataset(plot, dataset);
     if ( selRenderer != null )
       return selRenderer.getSelectionModel();
@@ -366,9 +363,9 @@
    * @param plot    the plot to check for renderer  
    * @return never {@code null}
    */
-  public static Map<Integer,DatasetSelectionModel<?>> getSelectionModels(Plot plot) {
-    Map<Integer,SelectionRenderer<?>>     selRenderer = getSelectionRenderer(plot);
-    Map<Integer,DatasetSelectionModel<?>> selModels   = new HashMap<Integer, DatasetSelectionModel<?>>();
+  public static Map<Integer,DatasetSelectionModel<?,?,?>> getSelectionModels(Plot plot) {
+    Map<Integer,SelectionRenderer<?>>         selRenderer = getSelectionRenderer(plot);
+    Map<Integer,DatasetSelectionModel<?,?,?>> selModels   = new HashMap<Integer, DatasetSelectionModel<?,?,?>>();
     for (int dataset : selRenderer.keySet())
       selModels.put(dataset, selRenderer.get(dataset).getSelectionModel());
     return selModels;

Modified: trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -35,6 +35,7 @@
 import java.util.Set;
 
 import org.jfree.chart.ChartPanel;
+import org.jfree.chart.entity.CategoryItemEntity;
 import org.jfree.chart.entity.ChartEntity;
 import org.jfree.chart.entity.EntityCollection;
 import org.jfree.chart.entity.XYItemEntity;
@@ -44,7 +45,8 @@
 /**
  * This tracker listens to mouse window selections and single mouse
  * clicks on a {@link ChartPanel}. It determines all selected 
- * {@link XYItemEntity XYItemEntities}.<b>
+ * {@link XYItemEntity XYItemEntities} and
+ * {@link CategoryItemEntity CategoryItemEntities}.
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  */
 public abstract class ChartMouseSelectionTracker extends MouseSelectionTracker {
@@ -97,18 +99,19 @@
 
     // Check every chart data points if the selection area
     // contains it (or it contains the selected point)
-    HashSet<XYItemEntity> selectedEntities = new HashSet<XYItemEntity>();
+    HashSet<ChartEntity> selectedEntities = new HashSet<ChartEntity>();
     for( Object entityObj : chartPanel.getChartRenderingInfo().getEntityCollection().getEntities() ) {
       ChartEntity entity = (ChartEntity)entityObj;
       // ignore all non-data entities
-      if ( !(entity instanceof XYItemEntity) )
+      if ( !(entity instanceof XYItemEntity) &&
+           !(entity instanceof CategoryItemEntity) )
         continue;
       
       // on point click, check whether point is inside the
       // entity area, otherwise check intersection
       if ( selectedPoint != null && entity.getArea().contains(selectedPoint) || 
            selectedPoint == null && entity.getArea().intersects(selectedArea) )
-        selectedEntities.add( (XYItemEntity)entity );
+        selectedEntities.add( entity );
     }
     selectionPerformed(selectedArea, selectedEntities);
   }
@@ -119,5 +122,5 @@
    * @param rect             the selection range
    * @param selectedEntities the selected {@link XYItemEntity XYItemEntities}
    */
-  protected abstract void selectionPerformed(Rectangle2D rect, Set<XYItemEntity> selectedEntities);
+  protected abstract void selectionPerformed(Rectangle2D rect, Set<ChartEntity> selectedEntities);
 }

Modified: trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -37,6 +37,8 @@
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
+import org.jfree.chart.entity.CategoryItemEntity;
+import org.jfree.chart.entity.ChartEntity;
 import org.jfree.chart.entity.XYItemEntity;
 import org.jfree.chart.event.ChartChangeEvent;
 import org.jfree.chart.event.ChartChangeEventType;
@@ -45,7 +47,6 @@
 import org.jfree.chart.plot.Plot;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.renderer.AbstractRenderer;
-import org.jfree.chart.renderer.category.AbstractCategoryItemRenderer;
 import org.jfree.chart.renderer.category.CategoryItemRenderer;
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.data.category.CategoryDataset;
@@ -53,8 +54,10 @@
 import org.jfree.data.xy.XYDataset;
 
 import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.chart.renderer.PointSelectionCategoryRenderer;
 import schmitzm.jfree.chart.renderer.PointSelectionXYRenderer;
 import schmitzm.jfree.chart.renderer.SelectionRenderer;
+import schmitzm.jfree.chart.selection.CategoryDatasetSelectionModel;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
 import schmitzm.jfree.feature.FeatureSeriesDatasetSelectionModel;
@@ -154,105 +157,97 @@
 
 		selectionTracker = new ChartMouseSelectionTracker(this) {
 
+		    private <E,F> void performSelection(DatasetSelectionModel<?,E,F> selModel, E seriesKey, F item) {
+              switch (windowSelectionMode) {
+                case SELECT_SET: // Is cleared once earlier
+                case SELECT_ADD:
+                  if (!selModel.isItemSelected(seriesKey, item))
+                      selModel.setItemSelected(seriesKey, item, true);
+                  break;
+                case SELECT_SWAP:
+                  selModel.changeItemSelection(seriesKey, item);
+                  break;
+              case SELECT_REMOVE:
+                  if (selModel.isItemSelected(seriesKey, item))
+                    selModel.setItemSelected(seriesKey, item, false);
+                  break;
+              }
+
+		      
+		    }
 			/**
 			 * This method is only called, if the #WindowSelectionMode is not in
 			 * Zoom-Mode. Otherwise this listener is disabled.
 			 */
 			@SuppressWarnings("fallthrough")
 			public void selectionPerformed(Rectangle2D selectedArea,
-					Set<XYItemEntity> selectedEntities) {
+					Set<ChartEntity> selectedEntities) {
 				LOGGER.debug(selectedEntities.size() + " objects selected");
 
                 Plot plot = getChart().getPlot();
 
 				// remember all changed selection models to reset
 				// "valueAdjusting" property at the end
-				Set<DatasetSelectionModel<?>> changedModels = new HashSet<DatasetSelectionModel<?>>();
+				Set<DatasetSelectionModel<?,?,?>> changedModels = new HashSet<DatasetSelectionModel<?,?,?>>();
 				// if selection mode is SELECT_SET all models change
 				// (also these which are not in the selectedEntities
 				// anymore!), because they must be cleared 
 				if ( windowSelectionMode == WindowSelectionMode.SELECT_SET ) {
-				  for ( DatasetSelectionModel<?> selModel : JFreeChartUtil.getSelectionModels(plot).values() ) {
+				  for ( DatasetSelectionModel<?,?,?> selModel : JFreeChartUtil.getSelectionModels(plot).values() ) {
 				    changedModels.add(selModel);
                     selModel.setValueIsAdjusting(true);
                     selModel.clearSelection();
 				  }
 				}
 				
-				for (Iterator<XYItemEntity> i = selectedEntities.iterator(); i
-						.hasNext();) {
-					XYItemEntity e = i.next();
-					Dataset dataset = e.getDataset();
-					DatasetSelectionModel<?> selModel = JFreeChartUtil.getSelectionModelForDataset(
+				for (Iterator<ChartEntity> i = selectedEntities.iterator(); i.hasNext();) {
+					ChartEntity e = i.next();
+					Dataset dataset = null;
+                    if ( e instanceof CategoryItemEntity )
+                      dataset = ((CategoryItemEntity)e).getDataset();
+                    if ( e instanceof XYItemEntity )
+                      dataset = ((XYItemEntity)e).getDataset();
+					DatasetSelectionModel<?,?,?> selModel = JFreeChartUtil.getSelectionModelForDataset(
 					                                          plot, dataset);
 					// set "valueAdjusting" property for selection model and
 					// remember the
 					// model to reset the property at the end
 					if (selModel != null) {
 						selModel.setValueIsAdjusting(true);
-
-//MS: now done above!
-//						/*
-//						 * If we do a SELCTION_SET and this is the first time we
-//						 * change this selection model, let's clear it before
-//						 * adding all the selected object.
-//						 */
-//						if (!changedModels.contains(selModel)
-//								&& windowSelectionMode == WindowSelectionMode.SELECT_SET){
-//							selModel.clearSelection();
-//						}
-
 						changedModels.add(selModel);
 					}
 					// perform the selection change
 					if (selModel instanceof SeriesDatasetSelectionModel) {
-						int series = e.getSeriesIndex();
-						Comparable<?> seriesKey = e.getDataset().getSeriesKey(series);
-						int item = e.getItem();
-						final SeriesDatasetSelectionModel seriesDatasetSelectionModel = (SeriesDatasetSelectionModel) selModel;
-
-						/*
-						 * We have the SelectionModel, a SeriesKey and it's
-						 * Item-ID. Now we deal with it depending on the
-						 * WindowSelectionMode
-						 */
-						switch (windowSelectionMode) {
-						case SELECT_SET:
-							// Is cleared once earlier
-						case SELECT_ADD:
-							if (!seriesDatasetSelectionModel.isItemSelected(
-									seriesKey, item))
-								seriesDatasetSelectionModel.setItemSelected(
-										seriesKey, item, true);
-							break;
-						case SELECT_SWAP:
-							seriesDatasetSelectionModel.changeItemSelection(
-									seriesKey, item);
-							break;
-						case SELECT_REMOVE:
-							if (seriesDatasetSelectionModel.isItemSelected(
-									seriesKey, item))
-								seriesDatasetSelectionModel.setItemSelected(
-										seriesKey, item, false);
-							break;
-						}
-
+					    XYItemEntity  xyEntity  = (XYItemEntity)e;
+						int           series    = xyEntity.getSeriesIndex();
+						Comparable<?> seriesKey = xyEntity.getDataset().getSeriesKey(series);
+						int           item      = xyEntity.getItem();
+						performSelection(
+						    (SeriesDatasetSelectionModel)selModel,
+						    seriesKey,
+						    item
+						);
+					} else if ( selModel instanceof CategoryDatasetSelectionModel ) {
+                        CategoryItemEntity  catEntity = (CategoryItemEntity)e;
+                        Comparable<?>       seriesKey = catEntity.getRowKey();
+                        Comparable<?>       itemKey   = catEntity.getColumnKey();
+                        performSelection(
+                            (CategoryDatasetSelectionModel)selModel,
+                            seriesKey,
+                            itemKey
+                        );
 					} else {
 						if (selModel == null)
-							LOGGER.warn("Selection not supported for dataset: "
-									+ LangUtil.getSimpleClassName(dataset));
+							LOGGER.warn("Selection not supported for dataset: " + LangUtil.getSimpleClassName(dataset));
 						else
-							LOGGER
-									.error("Selection not yet implemented for selection model: "
-											+ LangUtil
-													.getSimpleClassName(selModel));
+							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)
+				for (DatasetSelectionModel<?,?,?> selModel : changedModels)
 					selModel.setValueIsAdjusting(false);
 			}
 
@@ -396,6 +391,8 @@
     protected SelectionRenderer<?> createSelectionRenderer(Dataset dataset) {
       if ( dataset instanceof XYDataset )
         return new PointSelectionXYRenderer();
+      if ( dataset instanceof CategoryDataset )
+        return new PointSelectionCategoryRenderer();
 
       LOGGER.warn("No selection renderer provided for dataset: "+LangUtil.getSimpleClassName(dataset));
       return null;
@@ -419,12 +416,14 @@
       selRenderer.setBaseStroke( originRenderer.lookupSeriesStroke(0) );
       
       if ( dataset instanceof XYDataset ) {
+        ((XYItemRenderer)selRenderer).setBaseToolTipGenerator( ((XYItemRenderer)originRenderer).getBaseToolTipGenerator() );
         for (int i=0; i<((XYDataset)dataset).getSeriesCount(); i++) {
           selRenderer.setSeriesShape(i, originRenderer.lookupSeriesShape(i));
           selRenderer.setSeriesStroke(i, originRenderer.lookupSeriesStroke(i));
         }
       }
       if ( dataset instanceof CategoryDataset ) {
+        ((CategoryItemRenderer)selRenderer).setBaseToolTipGenerator( ((CategoryItemRenderer)originRenderer).getBaseToolTipGenerator() );
 //        for (int i=0; i<((CategoryDataset)dataset).getSeriesCount(); i++)
 //          if ( ((CategoryItemRenderer)originRenderer).getSeriesShape(i) != null )
 //            ((CategoryItemRenderer)selRenderer).setSeriesShape(i, ((CategoryItemRenderer)originRenderer).getSeriesShape(i));

Added: trunk/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.chart.renderer;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.log4j.Logger;
+import org.jfree.chart.axis.CategoryAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.Plot;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.category.CategoryItemRendererState;
+import org.jfree.chart.renderer.category.LineAndShapeRenderer;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.chart.selection.CategoryDatasetSelectionModel;
+import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
+import schmitzm.lang.LangUtil;
+
+/**
+ * Extends the {@link LineAndShapeRenderer} with the
+ * {@link SelectionRenderer} functionality. Additionally redefines
+ * the {@link #drawItem(Graphics2D, CategoryItemRendererState, Rectangle2D, CategoryPlot, CategoryAxis, ValueAxis, CategoryDataset, int, int, int)}
+ * method to realize the highlight rendering of the selected
+ * items. <b>Only the selected data points are rendered. No lines
+ * ore areas!</b><br>
+ * <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 #createAndSetSelectionModel()} to
+ * avoid this behavior.<br>
+ * If no selection model is set, the behavior of this renderer is exactly
+ * like the super class.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class PointSelectionCategoryRenderer extends LineAndShapeRenderer implements SelectionRenderer<CategoryDatasetSelectionModel> {
+  /** Used for log and debug messages. */
+  protected Logger LOGGER = LangUtil.createLogger(this);
+
+  /** Holds the selection model, the renderer uses to determine whether a
+   *  data item is selected or not. */
+  protected CategoryDatasetSelectionModel selectionModel = null;
+
+  /** Holds the selection color for each series. */
+  protected Paint selectionPaint = null;
+  
+  /**
+   * Creates a new renderer.
+   */
+  public PointSelectionCategoryRenderer() {
+    super(false,true);
+    init();
+  }
+
+  /**
+   * Called by every constructor to initialize the extensions 
+   * of this renderer.
+   */
+  protected void init() {
+    // set a default highlight color for the primary series
+    setSelectionPaint(Color.YELLOW);
+  }
+  
+  /**
+   * Returns always {@code false}, so that no series of the selection
+   * renderer is visible in the legend.
+   */
+  @Override
+  public boolean isSeriesVisibleInLegend(int series) {
+    return false;
+  }
+ 
+  /**
+   * Sets the selection model the renderer uses to determine whether
+   * a data item is selected or not.
+   * @param model the selection model
+   */
+  @Override
+  public void setSelectionModel(CategoryDatasetSelectionModel model) {
+    this.selectionModel = model;
+  }
+  
+  /**
+   * Returns the selection model the renderer uses to determine whether
+   * a data item is selected or not.
+   */
+  @Override
+  public CategoryDatasetSelectionModel getSelectionModel() {
+    return selectionModel;
+  }
+  
+  /**
+   * Creates and sets an adequate {@link SeriesDatasetSelectionModel}
+   * 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.
+   * @see #createSelectionModel(XYDataset) 
+   */
+  public void createAndSetSelectionModel() {
+    Dataset newDataset = JFreeChartUtil.getDatasetForRenderer(getPlot(),this);
+    if ( getSelectionModel() == null || getSelectionModel().getDataset() != newDataset )
+      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}.
+   * @param dataset must be a {@link XYDataset}
+   * @throws IllegalArgumentException if {@code dataset} is no {@link XYDataset}
+   */
+  @Override
+  public CategoryDatasetSelectionModel createSelectionModel(Dataset dataset) {
+    if ( !(dataset instanceof CategoryDataset) )
+      throw new IllegalArgumentException(LangUtil.getSimpleClassName(this)+".createSelectionModel(.) can only be applied for CategoryDataset: "+LangUtil.getSimpleClassName(dataset));
+    return new CategoryDatasetSelectionModel((CategoryDataset)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
+   *         for the series
+   */
+  public Paint getSelectionPaint() {
+    return selectionPaint;
+  }
+
+  /**
+   * Sets the color, the selected data is rendered with.
+   * @param paint color for the selected data
+   */
+  public void setSelectionPaint(Paint paint) {
+    selectionPaint = paint;
+  }
+  
+  /**
+   * Creates and sets a new {@link SeriesDatasetSelectionModel}, if no selection model
+   * is set yet, or the selection model's dataset differs from the dataset of the
+   * new plot.
+   * @param plot the plot rendered by this renderer
+   */
+  @Override
+  public void setPlot(CategoryPlot plot) {
+    super.setPlot(plot);
+    createAndSetSelectionModel();
+  }
+  
+  /**
+   * Sets the rendering color (temporary for the rendering process) to the
+   * {@linkplain #getSelectionPaint(int) highlight color}, if the item is
+   * defined as selected (by the {@linkplain #getSelectionModel() selection model}).
+   */
+  @Override
+  public void drawItem(Graphics2D g,
+      CategoryItemRendererState state,
+      Rectangle2D dataArea,
+      CategoryPlot plot,
+      CategoryAxis domainAxis,
+      ValueAxis rangeAxis,
+      CategoryDataset dataset,
+      int row, // this is the series
+      int column, // this is the item index in the series
+      int pass) {
+
+    // if selection model and color is set and the item is selected
+    // the highlighting selection color is set for the rendering
+    // process; otherwise the item is ignored for rendering!!
+    if ( getSelectionModel() != null ) {
+      Paint selPaint  = getSelectionPaint();
+      if ( selPaint != null ) {
+        Comparable<?> seriesKey = dataset.getRowKey(row);
+        Comparable<?> itemKey   = dataset.getColumnKey(column);
+        if ( selectionModel.isItemSelected(seriesKey, itemKey) ) {
+          setSeriesPaint( row, selPaint, false );
+          super.drawItem(g, state, dataArea, plot, domainAxis, rangeAxis, dataset, row, column, pass);
+        }
+      } else
+        LOGGER.warn("No selection paint set. Series is not rendererd highlighted.");
+    } else
+      LOGGER.debug("No selection model set for renderer. All series rendererd normally.");
+  }
+}

Modified: trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -33,8 +33,6 @@
 import java.awt.Graphics2D;
 import java.awt.Paint;
 import java.awt.geom.Rectangle2D;
-import java.util.HashMap;
-import java.util.Map;
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.axis.ValueAxis;
@@ -76,7 +74,8 @@
   protected SeriesDatasetSelectionModel selectionModel = null;
 
   /** Holds the selection color for each series. */
-  protected Map<Integer,Paint> selectionPaint = new HashMap<Integer, Paint>();
+  protected Paint selectionPaint = null;
+//  protected Map<Integer,Paint> selectionPaint = new HashMap<Integer, Paint>();
   
   /**
    * Creates a new renderer.
@@ -109,6 +108,7 @@
    * a data item is selected or not.
    * @param model the selection model
    */
+  @Override
   public void setSelectionModel(SeriesDatasetSelectionModel model) {
     this.selectionModel = model;
   }
@@ -117,6 +117,7 @@
    * Returns the selection model the renderer uses to determine whether
    * a data item is selected or not.
    */
+  @Override
   public SeriesDatasetSelectionModel getSelectionModel() {
     return selectionModel;
   }
@@ -130,8 +131,7 @@
    * @see #createSelectionModel(XYDataset) 
    */
   public void createAndSetSelectionModel() {
-    XYPlot  plot       = getPlot();
-    Dataset newDataset = JFreeChartUtil.getDatasetForRenderer(plot,this);
+    Dataset newDataset = JFreeChartUtil.getDatasetForRenderer(getPlot(),this);
     if ( getSelectionModel() == null || getSelectionModel().getDataset() != newDataset )
       setSelectionModel( newDataset != null ? createSelectionModel(newDataset) : null );
   }
@@ -143,6 +143,7 @@
    * @param dataset must be a {@link XYDataset}
    * @throws IllegalArgumentException if {@code dataset} is no {@link XYDataset}
    */
+  @Override
   public SeriesDatasetSelectionModel createSelectionModel(Dataset dataset) {
     if ( !(dataset instanceof XYDataset) )
       throw new IllegalArgumentException(LangUtil.getSimpleClassName(this)+".createSelectionModel(.) can only be applied for XYDataset: "+LangUtil.getSimpleClassName(dataset));
@@ -155,8 +156,10 @@
    * @return {@code null} if no selection color is defined
    *         for the series
    */
+  @Override
   public Paint getSelectionPaint() {
-    return getSelectionPaint(0);
+//    return getSelectionPaint(0);
+    return selectionPaint;
   }
 
   /**
@@ -164,28 +167,30 @@
    * is rendered with.
    * @param paint color for the selected data
    */
+  @Override
   public void setSelectionPaint(Paint paint) {
-    setSelectionPaint(0, paint);
+//    setSelectionPaint(0, paint);
+    selectionPaint = paint;
   }
 
-  /**
-   * Returns the color, the selected data is rendered with.
-   * @param series the data series
-   * @return {@code null} if no selection color is defined
-   *         for the series
-   */
-  public Paint getSelectionPaint(int series) {
-    return selectionPaint.get(series);
-  }
-
-  /**
-   * Sets the color, the selected data is rendered with.
-   * @param series the data series
-   * @param paint color for the selected data
-   */
-  public void setSelectionPaint(int series, Paint paint) {
-    selectionPaint.put(series, paint);
-  }
+//  /**
+//   * Returns the color, the selected data is rendered with.
+//   * @param series the data series
+//   * @return {@code null} if no selection color is defined
+//   *         for the series
+//   */
+//  public Paint getSelectionPaint(int series) {
+//    return selectionPaint.get(series);
+//  }
+//
+//  /**
+//   * Sets the color, the selected data is rendered with.
+//   * @param series the data series
+//   * @param paint color for the selected data
+//   */
+//  public void setSelectionPaint(int series, Paint paint) {
+//    selectionPaint.put(series, paint);
+//  }
   
   /**
    * Creates and sets a new {@link SeriesDatasetSelectionModel}, if no selection model
@@ -193,6 +198,7 @@
    * new plot.
    * @param plot the plot rendered by this renderer
    */
+  @Override
   public void setPlot(XYPlot plot) {
     super.setPlot(plot);
     createAndSetSelectionModel();
@@ -203,6 +209,7 @@
    * {@linkplain #getSelectionPaint(int) highlight color}, if the item is
    * defined as selected (by the {@linkplain #getSelectionModel() selection model}).
    */
+  @Override
   public void drawItem(Graphics2D g,
       XYItemRendererState state,
       Rectangle2D dataArea,
@@ -220,7 +227,7 @@
     // the highlighting selection color is set for the rendering
     // process; otherwise the item is ignored for rendering!!
     if ( getSelectionModel() != null ) {
-      Paint selPaint  = getSelectionPaint(series);
+      Paint selPaint  = getSelectionPaint();//(series);
       if ( selPaint != null ) {
         Comparable<?> seriesKey = dataset.getSeriesKey(series);
         if ( selectionModel.isItemSelected(seriesKey, item) ) {
@@ -228,7 +235,7 @@
           super.drawItem(g, state, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState, pass);
         }
       } else
-        LOGGER.warn("No selection paint set for series "+series+". Series is rendererd normally.");
+        LOGGER.warn("No selection paint set. Series is not rendererd highlighted.");
     } else
       LOGGER.debug("No selection model set for renderer. All series rendererd normally.");
   }

Modified: trunk/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -40,7 +40,7 @@
  * a highlighted way. 
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
-public interface SelectionRenderer<E extends DatasetSelectionModel<?>> extends DatasetSelectionModelProvider<E>{
+public interface SelectionRenderer<E extends DatasetSelectionModel<?,?,?>> extends DatasetSelectionModelProvider<E>{
   /**
    * Returns the color, the selected data is rendered with.
    */

Modified: trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/AbstractDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -29,6 +29,10 @@
  ******************************************************************************/
 package schmitzm.jfree.chart.selection;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 import java.util.Vector;
 
 import org.apache.log4j.Logger;
@@ -44,15 +48,23 @@
  * the {@link Dataset} as {@link DatasetChangeListener} to recognize the moment a
  * series is removed. Subclasses must implement
  * {@link #datasetChanged(org.jfree.data.general.DatasetChangeEvent)} to react with an
- * automatic unselect.
+ * automatic unselect.<br>
+ * <br>
+ * {@code D} = the dataset type the model handles<br>
+ * {@code E} = the data type the series are identified with in the dataset<br>
+ * {@code F} = the data type the data items are identified with in each series
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
-public abstract class AbstractDatasetSelectionModel<E extends Dataset> implements DatasetSelectionModel<E> {
+public abstract class AbstractDatasetSelectionModel<D extends Dataset, E, F> implements DatasetSelectionModel<D, E, F> {
   /** {@link Logger} to log waring, debug or error messages. */
   protected Logger LOGGER = LangUtil.createLogger(this);
 
   /** Holds the {@link Dataset} whose data can be selected. */
-  protected E dataset = null;
+  protected D dataset = null;
+
+  /** Contains a {@link Set} for each series. In each of these sets the
+   *  selected items are stored. */
+  protected Map<E,Set<F>> selectedSeriesIdx = new HashMap<E,Set<F>>();
   
   /** Holds the listeners to the {@link DatasetSelectionModel}. */
   protected Vector<DatasetSelectionListener> listeners = new Vector<DatasetSelectionListener>();
@@ -67,7 +79,7 @@
    * Creates a new selection model.
    * @param dataset {@link Dataset} whose data can be selected
    */
-  public AbstractDatasetSelectionModel(E dataset) {
+  public AbstractDatasetSelectionModel(D dataset) {
     this.dataset = dataset;
     dataset.addChangeListener(this);
   }
@@ -77,7 +89,7 @@
    * @param dataset a dataset
    * @return {@code null} if selection is not supported for dataset
    */
-  public static AbstractDatasetSelectionModel<?> createInstanceFor(Dataset dataset) {
+  public static AbstractDatasetSelectionModel<?,?,?> createInstanceFor(Dataset dataset) {
     if ( dataset instanceof SeriesDataset )
       return new SeriesDatasetSelectionModel((SeriesDataset)dataset);
     return null;
@@ -86,20 +98,82 @@
   /**
    * Returns the {@link Dataset} whose data can be selected. 
    */
-  public E getDataset() {
+  @Override
+  public D getDataset() {
     return dataset;
   }
   
   /**
+   * Checks if an series item is selected.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   */
+  @Override
+  public boolean isItemSelected(E seriesKey, F item) {
+    // determine the set for the series
+    Set<F> selectedIdx = selectedSeriesIdx.get(seriesKey);
+    // check whether item is selected
+    return selectedIdx != null && selectedIdx.contains(item);  
+  }
+
+  /**
+   * Sets whether a series item is selected or not.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   * @param selected  flag to (de)select the item
+   */
+  @Override
+  public void setItemSelected(E seriesKey, F item, boolean selected) {
+    // determine the set for the series
+    Set<F> selectedIdx = selectedSeriesIdx.get(seriesKey);
+    // create a set for the series if not yet existing
+    if ( selectedIdx == null ) {
+      selectedIdx = new HashSet<F>();
+      selectedSeriesIdx.put(seriesKey, selectedIdx);
+    }
+    // add/remove item index
+    if ( selected )
+      selectedIdx.add(item);
+    else
+      selectedIdx.remove(item);
+    
+    // inform all listeners about the selection change
+    refreshSelection();
+  }
+
+  /**
+   * Changes the selection of a series item.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   * @return {@code true} if the item changed to selected 
+   */
+  @Override
+  public boolean changeItemSelection(E seriesKey, F item) {
+    boolean nowSelected = !isItemSelected(seriesKey, item);
+    setItemSelected(seriesKey, item, nowSelected);
+    return nowSelected;
+  }
+
+  /**
    * Clears the selection.
    */
-  public abstract void clearSelection();
+  @Override
+  public void clearSelection() {
+    // clear all series sets
+    for (Set<F> selectedIdx: selectedSeriesIdx.values())
+      selectedIdx.clear();
+    // clear the series map
+    selectedSeriesIdx.clear();
+    // inform all listeners about the selection change
+    refreshSelection();
+  }
   
   /**
    * Adds a listener which will be informed about changed on the
    * selection model.
    * @param listener the listener to be added
    */
+  @Override
   public void addSelectionListener(DatasetSelectionListener listener) {
     listeners.add(listener);
   }
@@ -108,6 +182,7 @@
    * Removes a listener from the selection model.
    * @param listener the listener to be remove
    */
+  @Override
   public void removeSelectionListener(DatasetSelectionListener listener) {
     listeners.remove(listener);
   }
@@ -119,6 +194,7 @@
    * {@link #setValueIsAdjusting(boolean) setValueIsAdjusting(false)}
    * is called.
    */
+  @Override
   public boolean getValueIsAdjusting() {
     return this.valueIsAdjusting;
   }
@@ -131,6 +207,7 @@
    * refresh is initiated.
    * @see #refreshSelection()
    */
+  @Override
   public void setValueIsAdjusting(boolean valueIsAdjusting) {
     if ( valueIsAdjusting != this.valueIsAdjusting ) {
       this.valueIsAdjusting = valueIsAdjusting;
@@ -143,6 +220,7 @@
    * Informs all listeners about a general selection change. Does nothing
    * if {@link #getValueIsAdjusting()} is {@code true}.
    */
+  @Override
   public void refreshSelection() {
     if ( !getValueIsAdjusting() )
       for (DatasetSelectionListener l : listeners)

Added: trunk/src/schmitzm/jfree/chart/selection/CategoryDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/CategoryDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/CategoryDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.chart.selection;
+
+import java.util.Set;
+
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.general.DatasetChangeEvent;
+import org.jfree.data.general.SeriesDataset;
+
+/**
+ * This selection model maintains whether items of a {@link SeriesDataset} are selected
+ * in a chart or not.
+ * Any item in this model is identified by its row key (= dataset series: {@link Comparable}) and
+ * its column key (= category: {@link Comparable}). 
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ */
+public class CategoryDatasetSelectionModel extends AbstractDatasetSelectionModel<CategoryDataset, Comparable<?>, Comparable<?>> {
+  /**
+   * Creates a new selection model.
+   * @param dataset {@link Dataset} whose data can be selected
+   */
+  public CategoryDatasetSelectionModel(CategoryDataset dataset) {
+    super(dataset);
+  }
+
+  /**
+   * Listens for dataset changes. If a series is no longer present
+   * in the dataset, the respective items are removed from selection
+   * list.
+   */
+  @Override
+  public void datasetChanged(DatasetChangeEvent event) {
+    if ( event.getDataset() != this.dataset ||
+         !(event.getDataset() instanceof CategoryDataset) )
+      return;
+    CategoryDataset changedDataset = (CategoryDataset)event.getDataset();
+      
+    // check whether all series are still present
+    for (Comparable<?> seriesKey : selectedSeriesIdx.keySet())
+      // if series is no longer present, also remove series
+      // from selection model
+      if ( changedDataset.getRowIndex(seriesKey) < 0 ) {
+        // clear series set and remove series set
+        Set<Comparable<?>> selectedIdx = selectedSeriesIdx.get(seriesKey);
+        if ( selectedIdx != null )
+          selectedIdx.clear();
+        selectedSeriesIdx.remove(seriesKey);
+      }
+  }
+
+}

Modified: trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionChangeEvent.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -42,14 +42,14 @@
    * @param source
    * @param selModel the selection model
    */
-  public DatasetSelectionChangeEvent(DatasetSelectionModel<?> source) {
+  public DatasetSelectionChangeEvent(DatasetSelectionModel<?,?,?> source) {
     super(source);
   }
   
   /**
    * Returns the initiating {@link DatasetSelectionModel}.
    */
-  public DatasetSelectionModel<?> getSource() {
-    return (DatasetSelectionModel<?>)super.getSource();
+  public DatasetSelectionModel<?,?,?> getSource() {
+    return (DatasetSelectionModel<?,?,?>)super.getSource();
   }
 }

Modified: trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -30,6 +30,7 @@
 package schmitzm.jfree.chart.selection;
 
 import org.jfree.data.general.Dataset;
+import org.jfree.data.general.DatasetChangeEvent;
 import org.jfree.data.general.DatasetChangeListener;
 
 /**
@@ -37,16 +38,43 @@
  * in a chart or not. The model connects to the {@link Dataset} as {@link DatasetChangeListener}
  * to recognize the moment a series is removed. Subclasses must implement
  * {@link #datasetChanged(org.jfree.data.general.DatasetChangeEvent)} to react with an
- * automatic unselect.
+ * automatic unselect.<br>
+ * <br>
+ * {@code D} = the dataset type the model handles<br>
+ * {@code E} = the data type the series are identified with in the dataset<br>
+ * {@code F} = the data type the data items are identified with in each series
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
-public interface DatasetSelectionModel<E extends Dataset> extends DatasetChangeListener {
+public interface DatasetSelectionModel<D extends Dataset, E, F> extends DatasetChangeListener {
   /**
    * Returns the {@link Dataset} whose data can be selected. 
    */
-  public E getDataset();
+  public D getDataset();
   
   /**
+   * Checks if an series item is selected.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   */
+  public boolean isItemSelected(E seriesKey, F item);
+
+  /**
+   * Sets whether a series item is selected or not.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   * @param selected  flag to (de)select the item
+   */
+  public void setItemSelected(E seriesKey, F item, boolean selected);
+  
+  /**
+   * Changes the selection of a series item.
+   * @param seriesKey key of the series
+   * @param item      the item in the series
+   * @return {@code true} if the item changed to selected 
+   */
+  public boolean changeItemSelection(E seriesKey, F item);
+
+  /**
    * Clears the selection.
    */
   public void clearSelection();
@@ -87,4 +115,13 @@
    * Informs all listeners about a general selection change.
    */
   public void refreshSelection();
+  
+  
+  /**
+   * Listens for dataset changes. If a some data items are no longer present
+   * in the dataset, the respective items are removed from selection list.
+   */
+  @Override
+  public void datasetChanged(DatasetChangeEvent event);
+
 }

Modified: trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -37,7 +37,7 @@
  * a {@link AbstractDatasetSelectionModel}.
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
-public interface DatasetSelectionModelProvider<E extends DatasetSelectionModel<?>> {
+public interface DatasetSelectionModelProvider<E extends DatasetSelectionModel<?,?,?>> {
   /**
    * Returns the selection model for the (primary) {@link Dataset}. 
    */

Modified: trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/chart/selection/SeriesDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -29,9 +29,6 @@
  ******************************************************************************/
 package schmitzm.jfree.chart.selection;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 
 import org.jfree.data.general.Dataset;
@@ -41,13 +38,11 @@
 /**
  * This selection model maintains whether items of a {@link SeriesDataset} are selected
  * in a chart or not.
+ * Any item in this model is identified by its dataset series ({@link Comparable}) and
+ * its <b>index</b> in the series ({@link Integer}). 
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
  */
-public class SeriesDatasetSelectionModel extends AbstractDatasetSelectionModel<SeriesDataset> {
-  /** Contains a {@link Set} for each series. In each of these sets the
-   *  indices of the selected items are stored. */
-  protected Map<Comparable,Set<Integer>> selectedSeriesIdx = new HashMap<Comparable,Set<Integer>>();
-
+public class SeriesDatasetSelectionModel extends AbstractDatasetSelectionModel<SeriesDataset, Comparable<?>, Integer> {
   /**
    * Creates a new selection model.
    * @param dataset {@link Dataset} whose data can be selected
@@ -55,71 +50,12 @@
   public SeriesDatasetSelectionModel(SeriesDataset dataset) {
     super(dataset);
   }
-  
+
   /**
-   * Checks if an series item is selected.
-   * @param seriesKey key of the series
-   * @param item      index of the item in the series
+   * Listens for dataset changes. If a series is no longer present
+   * in the dataset, the respective items are removed from selection
+   * list.
    */
-  public boolean isItemSelected(Comparable seriesKey, int item) {
-    // determine the set for the series
-    Set<Integer> selectedIdx = selectedSeriesIdx.get(seriesKey);
-    // check whether item is selected
-    return selectedIdx != null && selectedIdx.contains(item);  
-  }
-  
-  /**
-   * Sets whether a series item is selected or not.
-   * @param seriesKey key of the series
-   * @param item      index of the item in the series
-   * @param selected  flag to (de)select the item
-   */
-  public void setItemSelected(Comparable seriesKey, int item, boolean selected) {
-    // determine the set for the series
-    Set<Integer> selectedIdx = selectedSeriesIdx.get(seriesKey);
-    // create a set for the series if not yet existing
-    if ( selectedIdx == null ) {
-      selectedIdx = new HashSet<Integer>();
-      selectedSeriesIdx.put(seriesKey, selectedIdx);
-    }
-    // add/remove item index
-    if ( selected )
-      selectedIdx.add(item);
-    else
-      selectedIdx.remove(item);
-    
-    // inform all listeners about the selection change
-    refreshSelection();
-  }
-  
-  /**
-   * Changes the selection of a series item.
-   * @param seriesKey key of the series
-   * @param item      index of the item in the series
-   * @return {@code true} if the item changed to selected 
-   */
-  public boolean changeItemSelection(Comparable seriesKey, int item) {
-    boolean nowSelected = !isItemSelected(seriesKey, item);
-    setItemSelected(seriesKey, item, nowSelected);
-    return nowSelected;
-  }
-  
-  /**
-   * Clears the selection for all series.
-   */
-  public void clearSelection() {
-    // clear all series sets
-    for (Set<Integer> selectedIdx: selectedSeriesIdx.values())
-      selectedIdx.clear();
-    // clear the series map
-    selectedSeriesIdx.clear();
-    // inform all listeners about the selection change
-    refreshSelection();
-  }
-  
-  /**
-   * 
-   */
   @Override
   public void datasetChanged(DatasetChangeEvent event) {
     if ( event.getDataset() != this.dataset ||
@@ -128,7 +64,7 @@
     SeriesDataset changedDataset = (SeriesDataset)event.getDataset();
       
     // check whether all series are still present
-    for (Comparable seriesKey : selectedSeriesIdx.keySet())
+    for (Comparable<?> seriesKey : selectedSeriesIdx.keySet())
       // if series is no longer present, also remove series
       // from selection model
       if ( changedDataset.indexOf(seriesKey) < 0 ) {

Added: trunk/src/schmitzm/jfree/feature/Feature2CategoryDatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2CategoryDatasetMapping.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/Feature2CategoryDatasetMapping.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.feature;
+
+import org.geotools.feature.Feature;
+import org.geotools.feature.FeatureCollection;
+import org.jfree.data.category.CategoryDataset;
+
+/**
+ * This class implements the mapping between {@link CategoryDataset} 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 Feature2CategoryDatasetMapping extends Feature2DatasetMapping<CategoryDataset,Comparable<?>,Comparable<?>> {
+  /**
+   * Creates a mapping. 
+   * @param fc a {@link FeatureCollection} (can be {@code null})
+   * @param dataset a {@link CategoryDataset} 
+   */
+  public Feature2CategoryDatasetMapping(FeatureCollection fc, CategoryDataset dataset) {
+    super(fc, dataset);
+  }
+
+  /**
+   * Returns the key of the primary series.
+   */
+  public Comparable<?> getPrimarySeriesKey() {
+    return (Comparable<?>)dataset.getRowKeys().get(0);
+  }
+  
+}

Modified: trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/Feature2DatasetMapping.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -29,27 +29,41 @@
  ******************************************************************************/
 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;
 
 /**
  * This class implements the mapping between {@link Dataset} items (points in chart)
- * and the corresponding {@link Feature Features}.
+ * and the corresponding {@link Feature Features}.<br>
+ * <br>
+ * {@code D} = the dataset type the model handles<br>
+ * {@code E} = the data type the series are identified with in the dataset<br>
+ * {@code F} = the data type the data items are identified with in each series
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
-public abstract class Feature2DatasetMapping<E, F extends Dataset> {
+public abstract class Feature2DatasetMapping<D extends Dataset, E, F> {
   /** Holds the {@link FeatureCollection} for the mapping */
   protected FeatureCollection featureCollection = null;
 
   /** Holds the {@link Dataset} for the mapping */
-  protected F dataset = null;
+  protected D dataset = null;
 
+  /** Holds the data items ({@code Map<SeriesKey,ItemID>})
+   *  for each feature ID (String). */
+  protected Map<String,Map<E,F>> fid2did = new HashMap<String, Map<E,F>>();
+  /** Holds for each series the feature ID (String) for each data item. */
+  protected Map<E,Map<F,String>> did2fid = new HashMap<E,Map<F,String>>();
+
+  
   /**
    * Creates a mapping. 
    * @param fc a {@link FeatureCollection} (can be {@code null}) 
    */
-  public Feature2DatasetMapping(FeatureCollection fc, F dataset) {
+  public Feature2DatasetMapping(FeatureCollection fc, D dataset) {
     this.featureCollection = fc;
     this.dataset           = dataset;
   }
@@ -64,41 +78,160 @@
   /**
    * Returns the {@link Dataset} the mapping is provided for.
    */
-  public F getDataset() {
+  public D getDataset() {
     return dataset;
   }
 
   /**
-   * Sets the mapping between a feature ID and a dataset item.
+   * Returns the key of the primary series.
+   */
+  public abstract E getPrimarySeriesKey();
+
+  /**
+   * 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 abstract void setMapping(String featureID, E itemID);
+  public void setMapping(String featureID, F 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 in the dataset (if
+   *                     {@code null} the primary series is used)
+   * @param itemID       defines the dataset item in the series
+   */
+  public void setMapping(String featureID, E seriesKey, F itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    // Mapping FeatureID --> (Series/Index)
+    Map<E, F> itemIDs = fid2did.get(featureID);
+    if ( itemIDs == null ) {
+      itemIDs = new HashMap<E, F>();
+      fid2did.put(featureID, itemIDs);
+    }
+    itemIDs.put(seriesKey, itemID);
+    
+    // Mapping (Series/Index) --> FeatureID
+    Map<F,String> featureIDs = did2fid.get(seriesKey);
+    if ( featureIDs == null ) {
+      featureIDs = new HashMap<F, String>();
+      did2fid.put(seriesKey, featureIDs);
+    }
+    featureIDs.put(itemID, featureID);
+  }
   
   /**
    * Removes the mapping of a feature ID.
    * @param fID feature ID
    */
-  public abstract void removeMappingForFeatureID(String fID);
+  public void removeMappingForFeatureID(String fID) {
+    // remove mapping FeatureID --> (Series/Index)
+    Map<E, F> itemIDs = fid2did.remove(fID);
+
+    // remove mapping (Series/Index) --> FeatureID
+    // for all item IDs referencing to the feature ID
+    for (E seriesKey : itemIDs.keySet()) {
+      Map<F, String> featureIDs = did2fid.get(seriesKey);
+      for (F itemID : itemIDs.values())
+        featureIDs.remove(itemID);
+    }
+  }
   
   /**
-   * Removes the mapping for a dataset item.
+   * Removes the mapping for a dataset item IN THE
+   * PRIMARY SERIES.
    * @param itemID    dataset item
    */
-  public abstract void removeMappingForDataItem(E itemID);
+  public void removeMappingForDataItem(F itemID) {
+    removeMappingForDataItem(null,itemID);
+  }
+  
+  /**
+   * Removes the mapping for a dataset item.
+   * @param seriesKey defines the series in the dataset (if
+   *                  {@code null} the primary series is used)
+   * @param itemID    defines the dataset item in the series
+   */
+  public void removeMappingForDataItem(E seriesKey, F itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    // remove mapping (Series/Index) --> FeatureID 
+    Map<F, String> featureIDs = did2fid.get(seriesKey);
+    String fID = null;
+    if ( featureIDs != null )
+      fID = featureIDs.remove(itemID);
+    
+    // remove mapping FeatureID --> (Series/Index)
+    if ( fID != null ) {
+      Map<E, F> 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 F getDataID(String fID) {
+    return getDataID(null,fID);
+  }
+
+  /**
    * Returns the data items for a given feature ID.
+   * @param seriesKey  defines the series in the dataset
    * @param fID a feature ID
    * @return {@code null} if no data item is registered for the feature ID
    */
-  public abstract E getDataID(String fID);
+  public F getDataID(E seriesKey, String fID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    Map<E, F> seriesIDs = getDataIDs(fID);
+    if ( seriesIDs != null )
+      return seriesIDs.get(seriesKey);
+    return null;
+    
+  }
+
+  /**
+   * 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(F itemID) {
+    return getFeatureID(null,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 Map<E,F> getDataIDs(String fID) {
+    return fid2did.get(fID);
+  }
   
   /**
    * Returns the feature ID for a given data item.
-   * @param itemID a data item
+   * @param seriesKey defines the series in the dataset
+   * @param itemID    defines the dataset item in the series (if
+   *                  {@code null} the primary series is used)
    * @return {@code null} if no feature ID is registered for the data item
    */
-  public abstract String getFeatureID(E itemID);
+  public String getFeatureID(E seriesKey, F itemID) {
+    if ( seriesKey == null )
+      seriesKey = getPrimarySeriesKey();
+    Map<F,String> featureIDs = did2fid.get(seriesKey);
+    if ( featureIDs != null )
+      return featureIDs.get(itemID); 
+    return null;
+  }
   
 }

Modified: trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/Feature2SeriesDatasetMapping.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -29,9 +29,6 @@
  ******************************************************************************/
 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;
@@ -44,12 +41,12 @@
  * 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>>();
+public class Feature2SeriesDatasetMapping extends Feature2DatasetMapping<SeriesDataset,Comparable<?>,Integer> {
+//  /** 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. 
@@ -63,154 +60,161 @@
   /**
    * Returns the key of the primary series.
    */
-  public Comparable getPrimarySeriesKey() {
+  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 IN THE
+//   * PRIMARY SERIES.
+//   * @param featureID    feature ID
+//   * @param itemID       defines the dataset item
+//   */
+//  @Override
+//  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);
-  }
+//  /**
+//   * 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
+//   */
+//  @Override
+//  public void setMapping(String featureID, Comparable<?> seriesKey, Integer 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 of a feature ID.
+//   * @param fID feature ID
+//   */
+//  @Override
+//  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 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);
-    }  
-  }
+//  /**
+//   * 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
+//   */
+//  @Override
+//  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 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 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
+//   */
+//  @Override
+//  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 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
+//   */
+//  @Override
+//  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 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;
-  }
+//  /**
+//   * 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
+//   */
+//  @Override
+//  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/FeatureCategoryDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureCategoryDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/FeatureCategoryDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.feature;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.DatasetGroup;
+
+import schmitzm.jfree.chart.selection.CategoryDatasetSelectionModel;
+import schmitzm.lang.LangUtil;
+
+/**
+ * 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class FeatureCategoryDatasetSelectionModel extends CategoryDatasetSelectionModel implements FeatureDatasetSelectionModel<CategoryDataset,Comparable<?>,Comparable<?>> {
+  /** Holds the mapping between features and the corresponding
+   *  column/row keys. */
+  protected Feature2CategoryDatasetMapping mapping = null;
+  
+  /**
+   * Creates a new selection model.
+   * @param dataset a dataset providing {@link FeatureDatasetMetaData}
+   *                as dataset group containing a {@link Feature2CategoryDatasetMapping}
+   */
+  public FeatureCategoryDatasetSelectionModel(CategoryDataset 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 Feature2CategoryDatasetMapping) )
+      throw new UnsupportedOperationException("Mapping (provided by FeatureDatasetMetaData) must be a Feature2CategoryDatasetMapping: "+LangUtil.getSimpleClassName(mapping));
+    this.mapping = (Feature2CategoryDatasetMapping)mapping;
+  }
+
+  /**
+   * Checks if the data item of a feature is selected in any series.
+   * @param fID  feature ID
+   */
+  @Override
+  public boolean isFeatureSelected(String fID) {
+    for (Object seriesKey : dataset.getRowKeys() )
+      if ( isFeatureSelected(fID,(Comparable<?>)seriesKey) )
+        return true;
+    return false;
+    
+  }
+  
+  /**
+   * Checks if the data item of a feature is selected.
+   * @param fID  feature ID
+   * @param seriesKey series (row) to check for the feature ID
+   */
+  public boolean isFeatureSelected(String fID, Comparable<?> seriesKey) {
+    Comparable<?> 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
+   */
+  @Override
+  public void setItemSelected(String fID, boolean selected) {
+    for (Object seriesKey : dataset.getRowKeys())
+      setItemSelected(fID, (Comparable<?>)seriesKey, selected);
+  }
+  
+  /**
+   * Sets whether the data item of a feature is selected or not.
+   * @param fID  feature ID
+   * @param seriesKey series (row) to set the selection in
+   * @param selected  flag to (de)select the item
+   */
+  public void setItemSelected(String fID, Comparable<?> seriesKey, boolean selected) {
+    Comparable<?> 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 
+   */
+  @Override
+  public boolean changeItemSelection(String fID) {
+    boolean anyChangedToTrue = false;
+    for (Object seriesKey : dataset.getRowKeys())
+      anyChangedToTrue |= changeItemSelection(fID, (Comparable<?>)seriesKey);
+    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) {
+    Comparable<?> dataItem = mapping.getDataID(seriesKey,fID);
+    return changeItemSelection(seriesKey, dataItem);
+  }
+
+  /**
+   * Returns the IDs of the selected features (in any series/row).
+   */
+  public Set<String> getSelectedFeatures() {
+    Set<String> selectedFIDs = new HashSet<String>();
+    for (Comparable<?> seriesKey : selectedSeriesIdx.keySet()) 
+      for (Comparable<?> selIdx : selectedSeriesIdx.get(seriesKey)) {
+        String selFID = mapping.getFeatureID(seriesKey,selIdx);
+        selectedFIDs.add(selFID);
+      }
+    
+    return selectedFIDs;
+  }
+
+}

Modified: trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -32,10 +32,12 @@
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
+import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.XYDataset;
 
 import schmitzm.jfree.chart.SelectableChartPanel;
+import schmitzm.jfree.chart.renderer.PointSelectionCategoryRenderer;
 import schmitzm.jfree.chart.renderer.PointSelectionXYRenderer;
 import schmitzm.jfree.chart.renderer.SelectionRenderer;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
@@ -109,6 +111,15 @@
           }
         };
 
+        if ( dataset instanceof CategoryDataset )
+          return new PointSelectionCategoryRenderer() {
+            @Override
+            public FeatureCategoryDatasetSelectionModel createSelectionModel(Dataset dataset) {
+              if ( !(dataset instanceof CategoryDataset) )
+                throw new IllegalArgumentException(LangUtil.getSimpleClassName(this)+".createSelectionModel(.) can only be applied for CategoryDataset: "+LangUtil.getSimpleClassName(dataset));
+              return new FeatureCategoryDatasetSelectionModel((CategoryDataset)dataset);
+            }
+          };
     }
     LOGGER.warn("No Feature2DatasetMapping provided for dataset: "+LangUtil.getSimpleClassName(dataset));
 

Modified: trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/FeatureDatasetMetaData.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -43,7 +43,7 @@
    * Creates a new meta data object for features. 
    * @param mapping mapping between features and chart data
    */
-  public FeatureDatasetMetaData(Feature2DatasetMapping<?,?> mapping) {
+  public FeatureDatasetMetaData(Feature2DatasetMapping<?,?,?> mapping) {
     super();
     setMetaData(KEY_MAPPING, mapping);
   }
@@ -52,8 +52,8 @@
    * Returns the mapping between features and the corresponding
    * dataset items.
    */
-  public Feature2DatasetMapping<?,?> getMapping() {
-    return (Feature2DatasetMapping<?,?>)getMetaData(KEY_MAPPING);
+  public Feature2DatasetMapping<?,?,?> getMapping() {
+    return (Feature2DatasetMapping<?,?,?>)getMetaData(KEY_MAPPING);
   }
   
 }

Modified: trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/FeatureDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -40,7 +40,7 @@
  * 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> {
+public interface FeatureDatasetSelectionModel<D extends Dataset, E, F> extends DatasetSelectionModel<D, E, F> {
   /**
    * Checks if the data item of a feature is selected.
    * @param fID  feature ID
@@ -65,4 +65,5 @@
    * Returns the IDs of the selected features.
    */
   public Set<String> getSelectedFeatures();
+
 }

Modified: trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/FeatureSeriesDatasetSelectionModel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -42,15 +42,15 @@
  * 
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
-public class FeatureSeriesDatasetSelectionModel extends SeriesDatasetSelectionModel implements FeatureDatasetSelectionModel<SeriesDataset> {
+public class FeatureSeriesDatasetSelectionModel extends SeriesDatasetSelectionModel implements FeatureDatasetSelectionModel<SeriesDataset,Comparable<?>,Integer> {
   /** 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
+   * @param dataset a dataset providing {@link FeatureDatasetMetaData}
+   *                as dataset group containing a {@link Feature2SeriesDatasetMapping}
    */
   public FeatureSeriesDatasetSelectionModel(SeriesDataset dataset) {
     super(dataset);
@@ -60,7 +60,7 @@
       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();
+    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;
@@ -70,6 +70,7 @@
    * Checks if the data item of a feature is selected in any series.
    * @param fID  feature ID
    */
+  @Override
   public boolean isFeatureSelected(String fID) {
     for (int i=0; i<dataset.getSeriesCount(); i++)
       if ( isFeatureSelected(fID,dataset.getSeriesKey(i)) )
@@ -83,7 +84,7 @@
    * @param fID  feature ID
    * @param seriesKey series to check for the feature ID
    */
-  public boolean isFeatureSelected(String fID, Comparable seriesKey) {
+  public boolean isFeatureSelected(String fID, Comparable<?> seriesKey) {
     Integer dataItem = mapping.getDataID(seriesKey,fID);
     return dataItem != null && isItemSelected(seriesKey, dataItem);
   }
@@ -93,6 +94,7 @@
    * @param fID  feature ID
    * @param selected  flag to (de)select the item
    */
+  @Override
   public void setItemSelected(String fID, boolean selected) {
     for (int i=0; i<dataset.getSeriesCount(); i++)
       setItemSelected(fID, dataset.getSeriesKey(i), selected);
@@ -104,7 +106,7 @@
    * @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) {
+  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);
@@ -118,6 +120,7 @@
    * @param fID  feature ID
    * @return {@code true} if at least one item changed to selected 
    */
+  @Override
   public boolean changeItemSelection(String fID) {
     boolean anyChangedToTrue = false;
     for (int i=0; i<dataset.getSeriesCount(); i++)
@@ -131,7 +134,7 @@
    * @param seriesKey series to change the selection in
    * @return {@code true} if the item changed to selected 
    */
-  public boolean changeItemSelection(String fID, Comparable seriesKey) {
+  public boolean changeItemSelection(String fID, Comparable<?> seriesKey) {
     Integer dataItem = mapping.getDataID(seriesKey,fID);
     return changeItemSelection(seriesKey, dataItem);
   }
@@ -139,9 +142,10 @@
   /**
   * Returns the IDs of the selected features (in any series).
   */
+  @Override
   public Set<String> getSelectedFeatures() {
     Set<String> selectedFIDs = new HashSet<String>();
-    for (Comparable seriesKey : selectedSeriesIdx.keySet()) 
+    for (Comparable<?> seriesKey : selectedSeriesIdx.keySet()) 
       for (Integer selIdx : selectedSeriesIdx.get(seriesKey)) {
         String selFID = mapping.getFeatureID(seriesKey,selIdx);
         selectedFIDs.add(selFID);

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -34,7 +34,6 @@
 import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.XYDataset;
-import org.jfree.data.xy.XYSeriesCollection;
 
 import schmitzm.jfree.chart.style.BasicChartStyle;
 import schmitzm.jfree.chart.style.ChartType;

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -63,6 +63,7 @@
 import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
+import schmitzm.jfree.feature.Feature2CategoryDatasetMapping;
 import schmitzm.jfree.feature.Feature2SeriesDatasetMapping;
 import schmitzm.jfree.feature.FeatureDatasetMetaData;
 import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
@@ -87,9 +88,9 @@
 	 * @param chart
 	 *            a chart
 	 */
-	public static List<FeatureDatasetSelectionModel<?>> getFeatureDatasetSelectionModelFor(
+	public static List<FeatureDatasetSelectionModel<?,?,?>> getFeatureDatasetSelectionModelFor(
 			JFreeChart chart) {
-		ArrayList<FeatureDatasetSelectionModel<?>> renderers = new ArrayList<FeatureDatasetSelectionModel<?>>();
+		ArrayList<FeatureDatasetSelectionModel<?,?,?>> renderers = new ArrayList<FeatureDatasetSelectionModel<?,?,?>>();
 
 		Plot plot = chart.getPlot();
 
@@ -406,34 +407,25 @@
 	 * @throws UnsupportedOperationException
 	 *             if attributes are not numeric
 	 */
-	public static DefaultCategoryDataset createCategoryDataset(
-			FeatureCollection fc, FeatureChartStyle chartStyle) {
+	public static DefaultCategoryDataset createCategoryDataset(FeatureCollection fc, FeatureChartStyle chartStyle) {
 		int attrCount = chartStyle.getAttributeCount();
 		if (attrCount < 2)
-			throw new IllegalArgumentException(
-					"FeatureChartStyle must define at least 2 attributes to create CategoryDataset: "
-							+ attrCount);
+		  throw new IllegalArgumentException("FeatureChartStyle must define at least 2 attributes to create CategoryDataset: "+ attrCount);
 		String xAttrName = chartStyle.getAttributeName(0);
 		// only check whether X attribute exists (numeric and not-numeric
 		// allowed)
-		checkAttributeType(fc.getSchema(), xAttrName, Comparable.class,
-				"Domain attribute", "CategoryDataset");
+		checkAttributeType(fc.getSchema(), xAttrName, Comparable.class,"Domain attribute", "CategoryDataset");
 		// check data types of Y attribute (only numeric allowed)
 		for (int i = 1; i < attrCount; i++)
-			checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i),
-					Number.class, "Range attribute", "CategoryDataset");
+		  checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i), Number.class, "Range attribute", "CategoryDataset");
 		
-		
 		// Calculate any statistics needed for normalization. 
 		HashMap<String,StaticBin1D> statisticsForNormalization = calcStatisticsForNormalization(fc, chartStyle);
 
 		// Create a new dataset and insert the series
-		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
-		// TODO: Mapping for CategoryDataset!! (CategoryDataset is no
-		// SeriesDataset!)
-		// Feature2SeriesDatasetMapping mapping = new
-		// Feature2SeriesDatasetMapping(fc,dataset);
-		// dataset.setGroup( new FeatureDatasetMetaData(mapping) );
+		DefaultCategoryDataset         dataset = new DefaultCategoryDataset();
+		Feature2CategoryDatasetMapping mapping = new Feature2CategoryDatasetMapping(fc,dataset);
+		dataset.setGroup( new FeatureDatasetMetaData(mapping) );
 
 		// If dataset should be sorted, the features must be sorted first
 		// according to the domain attribute. CategoryDataset has no
@@ -441,45 +433,41 @@
 		// createXYDataset(..))
 		Iterator<Feature> fi = null;
 		if (chartStyle.isSortDomainAxis()) {
-			Vector<Feature> sortedFeatures = FeatureUtil.sortFeatures(fc
-					.features(), xAttrName);
-			// Create an Iterator for the sorted Features
-			fi = sortedFeatures.iterator();
+		  Vector<Feature> sortedFeatures = FeatureUtil.sortFeatures(fc.features(), xAttrName);
+		  // Create an Iterator for the sorted Features
+		  fi = sortedFeatures.iterator();
 		} else
-			fi = new PipedFeatureIterator(fc.features());
+		  fi = new PipedFeatureIterator(fc.features());
 
 		// Iterate the FeatureCollection and fill the series
 		for (int fIdx = 0; fi.hasNext(); fIdx++) {
 			Feature f = fi.next();
 			// Determine the category (NULL not permitted!)
-			Comparable catValue = (Comparable) f.getAttribute(xAttrName);
+			Comparable<?> catValue = (Comparable<?>)f.getAttribute(xAttrName);
 			if (catValue == null)
 				continue;
 			// Determine the Y values and fill the dataset
 			for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
 				String yAttrName = chartStyle.getAttributeName(attrIdx);
-				Number yValue = (Number) f.getAttribute(yAttrName);
-				
-				/* Normalization of a range axis value */
-				if (chartStyle.isAttributeNormalized(attrIdx))
-					yValue = normalize(yValue, yAttrName, statisticsForNormalization);
+				Number yValue    = (Number) f.getAttribute(yAttrName);
 	
-				// // TODO: here maybe filtering the several NULL aliases
+				// TODO: here maybe filtering the several NULL aliases
 				// if ( yValue is a NULL alias )
 				// yValue = null;
 
-				// // TODO: here maybe ignore NULL values completely.
+				// TODO: here maybe ignore NULL values completely.
 				// if ( yValue == null )
 				// continue;
 
-				/* Note: Normalization does not make sense for a DOMAIN axis in a category dataset! */
+                /* Normalization of a range axis value */
+                if (chartStyle.isAttributeNormalized(attrIdx))
+                  yValue = normalize(yValue, yAttrName, statisticsForNormalization);
 
-				// Add data to dataset
+                // Add data to dataset
 				dataset.addValue(yValue, yAttrName, catValue);
 
-				// TODO: Implement the Mapping for CategoryDataset
-				// // Mapping between FID and data index in series
-				// mapping.setMapping(f.getID(), yAttrName, fIdx);
+				// Mapping between FID and data index in series
+				mapping.setMapping(f.getID(), yAttrName, catValue);
 			}
 
 		}

Modified: trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java
===================================================================
--- trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/skrueger/geotools/selection/ChartSelectionSynchronizer.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -63,7 +63,7 @@
                                         implements DatasetSelectionListener {
 
   /** Holds the chart datset to keep synchronized with the layer selection model. */
-  protected FeatureDatasetSelectionModel<?> datasetSelModel = null;
+  protected FeatureDatasetSelectionModel<?,?,?> datasetSelModel = null;
 
   /**
    * Creates a new synchronizer.
@@ -74,7 +74,7 @@
    *            dataset selection model to keep synchronized with the layer
    *            selection model
    */
-  public ChartSelectionSynchronizer(StyledFeatureLayerSelectionModel layerSelModel, FeatureDatasetSelectionModel<?> datasetSelModel) {
+  public ChartSelectionSynchronizer(StyledFeatureLayerSelectionModel layerSelModel, FeatureDatasetSelectionModel<?,?,?> datasetSelModel) {
     super(layerSelModel);
     this.datasetSelModel = datasetSelModel;
   }

Modified: trunk/src/skrueger/swing/TranslationEditJPanel.java
===================================================================
--- trunk/src/skrueger/swing/TranslationEditJPanel.java	2009-08-03 14:03:52 UTC (rev 288)
+++ trunk/src/skrueger/swing/TranslationEditJPanel.java	2009-08-03 22:29:36 UTC (rev 289)
@@ -41,13 +41,13 @@
 
 import javax.swing.BorderFactory;
 import javax.swing.JLabel;
-import schmitzm.swing.JPanel;
 import javax.swing.JTextField;
 import javax.swing.SpringLayout;
 import javax.swing.SwingConstants;
 
 import org.apache.log4j.Logger;
 
+import schmitzm.swing.JPanel;
 import schmitzm.swing.SpringUtilities;
 import skrueger.i8n.Translation;
 



More information about the Schmitzm-commits mailing list