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

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Aug 3 01:16:15 CEST 2009


Author: mojays
Date: 2009-08-03 01:16:13 +0200 (Mon, 03 Aug 2009)
New Revision: 283

Added:
   trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
   trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java
Modified:
   trunk/src/schmitzm/geotools/feature/FeatureUtil.java
   trunk/src/schmitzm/geotools/gui/MouseSelectionTracker.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/SelectionXYLineAndShapeRenderer.java
   trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java
   trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
   trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java
Log:
Chart selection via single click.
Subtitle applied from ChartStyle.
Highlight rendering of selected chart data re-structured (special highlight datasets in plot).

Modified: trunk/src/schmitzm/geotools/feature/FeatureUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/feature/FeatureUtil.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/geotools/feature/FeatureUtil.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -538,7 +538,7 @@
    */
   public static Vector<Feature> sortFeatures(FeatureIterator fi, String attrName) {
     // First create a SortedMap with CollisionList
-    SortedMap<Comparable, Vector<Feature>> sortedFeatureLists = new TreeMap<Comparable, Vector<Feature>>();
+    SortedMap<Comparable<?>, Vector<Feature>> sortedFeatureLists = new TreeMap<Comparable<?>, Vector<Feature>>();
     for (;fi.hasNext();) {
       Feature f = fi.next();
       // Check whether attribute value is Comparable
@@ -546,7 +546,7 @@
       if ( attrValue != null && !(attrValue instanceof Comparable) )
         throw new UnsupportedOperationException("Feature sort only supported for Comparable attributes: "+LangUtil.getSimpleClassName(attrValue));
       // Determine X value as sort attribute (NULL not permitted for XYDateset!)
-      Comparable xValue = (Comparable)attrValue;
+      Comparable<?> xValue = (Comparable<?>)attrValue;
       if ( xValue == null )
         continue;
       
@@ -590,7 +590,7 @@
     FeatureIterator   fi       = fc.features();
     // Array fuer die Attribut-Werte eines Features
     Object[]          fValues  = new Object[resultType.getAttributeCount()];
-    for ( Feature f = null; fi.hasNext(); ) {
+    for ( ; fi.hasNext(); ) {
       // Werte der alten Attribute in Array schreiben
       fi.next().getAttributes(fValues);
       // Default-Werte der neuen Attribute in Array schreiben

Modified: trunk/src/schmitzm/geotools/gui/MouseSelectionTracker.java
===================================================================
--- trunk/src/schmitzm/geotools/gui/MouseSelectionTracker.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/geotools/gui/MouseSelectionTracker.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -35,14 +35,49 @@
 
 /**
  * Extends the geotools {@link org.geotools.gui.swing.MouseSelectionTracker} with an
- * enable/disable functionality. 
+ * enable/disable functionality. Furthermore the tracker (optionally)
+ * also reacts on single clicks.
+ * @see #setSelectionMode(SelectionMode)
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  */
 public abstract class MouseSelectionTracker extends MouseSelectionTracker_Public {
+  /** Selection events the tracker reacts on. */
+  public enum SelectionMode {
+    /** Tracker reacts on single clicks as well as on
+     *  window selections. */
+    ALL,
+    /** Tracker reacts only on single clicks. Window selections
+     *  are ignored. */
+    ONLY_SINGLE_CLICK,
+    /** Tracker reacts only on window selection. Single clicks
+     *  are ignored. */
+    ONLY_WINDOW_SELECTION
+  }
+
   /** Indicates whether the tracker reacts on mouse events. */
   protected boolean enabled = true;
+  /** Specifies the selection events the tracker reacts on. */
+  protected SelectionMode selectionMode = null;
 
   /**
+   * Creates a new tracker, which reacts only on window
+   * selection events (default geotools behavior for
+   * {@link org.geotools.gui.swing.MouseSelectionTracker}).
+   */
+  public MouseSelectionTracker() {
+    this(SelectionMode.ONLY_WINDOW_SELECTION);
+  }
+
+  /**
+   * Creates a new tracker.
+   * @param mode  specifies the selection events the tracker reacts on
+   */ 
+  public MouseSelectionTracker(SelectionMode mode) {
+    super();
+    setSelectionMode(mode);
+  }
+  
+  /**
    * Returns whether the tracker reacts on mouse events or not.
    */
   public boolean isEnabled() {
@@ -57,15 +92,36 @@
   }
 
   /**
-   * Ignores the event if tracker is disabled. Otherwise the
-   * super method is called.
+   * Sets the selection events the tracker reacts on.
+   * @param mode the mode to set
    */
+  public void setSelectionMode(SelectionMode mode) {
+    this.selectionMode = mode;
+  }
+
+  /**
+   * Returns the selection events the tracker reacts on.
+   */
+  public SelectionMode getSelectionMode() {
+    return selectionMode;
+  }
+
+  /**
+   * Ignores the event if tracker is disabled or selection mode
+   * is {@link SelectionMode#ONLY_WINDOW_SELECTION}. Otherwise
+   * {@link #selectionPerformed(int, int, int, int)} is called for
+   * the selected point.
+   */
   @Override
   public void mouseClicked(MouseEvent e) {
-    if ( !isEnabled() )
+    if ( SelectionMode.ONLY_WINDOW_SELECTION.equals(getSelectionMode()) ||
+        !isEnabled() || e.getButton() != MouseEvent.BUTTON1 )
       return;
     super.mouseClicked(e);
-  }
+  
+    int clickX = e.getX();
+    int clickY = e.getY();
+    selectionPerformed(clickX, clickY, clickX, clickY);}
 
   /**
    * Ignores the event if tracker is disabled. Otherwise the
@@ -112,12 +168,14 @@
   }
 
   /**
-   * Ignores the event if tracker is disabled. Otherwise the
-   * super method is called.
+   * Ignores the event if tracker is disabled or selection mode
+   * is {@link SelectionMode#ONLY_SINGLE_CLICK}, so that the
+   * dragging rectangle is not drawn.
    */
   @Override
   public void mouseDragged(MouseEvent e) {
-    if ( !isEnabled() )
+    if ( SelectionMode.ONLY_SINGLE_CLICK.equals( getSelectionMode() ) ||
+        !isEnabled() )
       return;
     super.mouseDragged(e);
   }

Modified: trunk/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -30,7 +30,10 @@
 package schmitzm.jfree;
 
 import java.awt.Color;
+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;
@@ -41,6 +44,7 @@
 import org.jfree.chart.event.RendererChangeListener;
 import org.jfree.chart.labels.StandardXYToolTipGenerator;
 import org.jfree.chart.labels.XYToolTipGenerator;
+import org.jfree.chart.plot.CategoryPlot;
 import org.jfree.chart.plot.Plot;
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
@@ -66,12 +70,15 @@
 import org.jfree.chart.urls.XYURLGenerator;
 import org.jfree.data.function.Function2D;
 import org.jfree.data.function.LineFunction2D;
+import org.jfree.data.general.Dataset;
 import org.jfree.data.general.DatasetUtilities;
 import org.jfree.data.statistics.Regression;
 import org.jfree.data.xy.XYDataset;
 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;
@@ -164,7 +171,7 @@
                  if ( stepped )
                    return new XYStepRenderer();
                  // normal line renderer
-                 return new SelectionXYLineAndShapeRenderer(true, false);
+                 return new XYLineAndShapeRenderer(true, false);
       case AREA: // Apply stacked
                  if ( stacked ) {
                    // "stacked" and "stepped" can not be applied the same time
@@ -237,8 +244,172 @@
     throw new UnsupportedOperationException("CategoryItemRenderer could not be created for chart type: "+type); 
   }
 
+  /**
+   * Returns the renderer for the {@code i}-th dataset of a plot.
+   * @param plot  a plot
+   * @param index the dataset index
+   * @return the primary renderer if no specific renderer is
+   *         set for dataset {@code i}
+   */
+  public static Object getRendererForDataset(Plot plot, int i) {
+    Object renderer = null;
+    if ( plot instanceof XYPlot ) {
+      renderer = ((XYPlot)plot).getRenderer(i);
+      if ( renderer == null )
+        renderer = ((XYPlot)plot).getRenderer();
+    }
+
+    if ( plot instanceof CategoryPlot ) {
+      renderer = ((CategoryPlot)plot).getRenderer(i);
+      if ( renderer == null )
+        renderer = ((CategoryPlot)plot).getRenderer();
+    }
+    
+    return renderer;
+  }
+  
+  /**
+   * Searchs the renderers of a plot for {@link SelectionRenderer} for
+   * a {@link Dataset}.
+   * @param plot    the plot to check for renderer  
+   * @param dataset the dataset a {@link SelectionRenderer} is
+   *                searched for
+   * @return {@code null} if there is no {@link SelectionRenderer} defined
+   *         for the dataset
+   */
+  public static SelectionRenderer<?> getSelectionRendererForDataset(Plot plot, Dataset dataset) {
+    if ( plot instanceof XYPlot ) {
+      XYPlot xyPlot = (XYPlot)plot;
+      for (int i=0; i<xyPlot.getDatasetCount(); i++) {
+        Dataset d = xyPlot.getDataset(i);
+        if ( d != dataset )
+          continue;
+        // determine renderer for dataset (if no renderer is set,
+        // take the primary renderer)
+        XYItemRenderer r = xyPlot.getRenderer(i);
+        if ( r == null )
+          r = xyPlot.getRenderer();
+        // stop search, if renderer is a SelectionRenderer
+        if ( r instanceof SelectionRenderer<?> )
+          return (SelectionRenderer<?>)r;
+      }
+    }
+
+    if ( plot instanceof CategoryPlot ) {
+      CategoryPlot catPlot = (CategoryPlot)plot;
+      for (int i=0; i<catPlot.getDatasetCount(); i++) {
+        Dataset d = catPlot.getDataset(i);
+        if ( d != dataset )
+          continue;
+        // determine renderer for dataset (if no renderer is set,
+        // take the primary renderer)
+        CategoryItemRenderer r = catPlot.getRenderer(i);
+        if ( r == null )
+          r = catPlot.getRenderer();
+        // stop search, if renderer is a SelectionRenderer
+        if ( r instanceof SelectionRenderer<?> )
+          return (SelectionRenderer<?>)r;
+      }
+    }
+    
+    return null;
+  }
  
   /**
+   * Searchs the renderers of a plot for {@link SelectionRenderer} for
+   * a {@link Dataset} and returns its {@link DatasetSelectionModel}.
+   * @param plot    the plot to check for renderer  
+   * @param dataset the dataset a {@link SelectionRenderer} is
+   *                searched for
+   * @return {@code null} if there is no {@link SelectionRenderer} defined
+   *         for the dataset
+   */
+  public static DatasetSelectionModel<?> getSelectionModelForDataset(Plot plot, Dataset dataset) {
+    SelectionRenderer<?> selRenderer = getSelectionRendererForDataset(plot, dataset);
+    if ( selRenderer != null )
+      return selRenderer.getSelectionModel();
+    return null;
+  }
+
+  /**
+   * Returns all {@link SelectionRenderer} for a {@link Plot}.
+   * @param plot    the plot to check for renderer  
+   * @return never {@code null}
+   */
+  public static Map<Integer,SelectionRenderer<?>> getSelectionRenderer(Plot plot) {
+    Map<Integer,SelectionRenderer<?>> selRenderer = new HashMap<Integer,SelectionRenderer<?>>();
+    
+    if ( plot instanceof XYPlot ) {
+      XYPlot xyPlot = (XYPlot)plot;
+      for (int i=0; i<xyPlot.getRendererCount(); i++) {
+        XYItemRenderer r = xyPlot.getRenderer(i);
+        if ( r instanceof SelectionRenderer<?> )
+          selRenderer.put(i, (SelectionRenderer<?>)r);
+      }
+    }
+
+    if ( plot instanceof CategoryPlot ) {
+      CategoryPlot catPlot = (CategoryPlot)plot;
+      for (int i=0; i<catPlot.getRendererCount(); i++) {
+        CategoryItemRenderer r = catPlot.getRenderer(i);
+        if ( r instanceof SelectionRenderer<?> )
+          selRenderer.put(i, (SelectionRenderer<?>)r);
+      }
+    }
+    
+    return selRenderer;
+  }
+  
+  /**
+   * Searchs the renderers of a plot for all {@link SelectionRenderer}
+   * and returns their {@link DatasetSelectionModel DatasetSelectionModels}.
+   * @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<?>>();
+    for (int dataset : selRenderer.keySet())
+      selModels.put(dataset, selRenderer.get(dataset).getSelectionModel());
+    return selModels;
+  }
+  
+  /**
+   * Returns the (first) dataset of a {@link Plot} which is rendererd
+   * by a renderer.
+   * @param plot     the plot which holds the datasets and renderer
+   * @param renderer the renderer a dataset is seached for
+   * @return {@code null} if there is no dataset which is rendered
+   *         by the given renderer 
+   */
+  public static Dataset getDatasetForRenderer(Plot plot, Object renderer) {
+    if ( plot instanceof XYPlot ) {
+      XYPlot xyPlot = (XYPlot)plot;
+      for (int i=0; i<xyPlot.getRendererCount(); i++)
+        if ( xyPlot.getRenderer(i) == renderer )
+          return xyPlot.getDataset(i);
+    }
+
+    if ( plot instanceof CategoryPlot ) {
+      CategoryPlot catPlot = (CategoryPlot)plot;
+      for (int i=0; i<catPlot.getRendererCount(); i++)
+        if ( catPlot.getRenderer(i) == renderer )
+          return catPlot.getDataset(i);
+    }
+    
+    return null;
+  }
+
+  /**
+   * Applies general dataset properties to a {@link Dataset}.
+   * @param dataset dataset the properties are applied to
+   * @param sample  dataset the properties are taken from
+   */
+  public static void applyDatasetProperties(Dataset dataset, Dataset sample) {
+    dataset.setGroup( sample.getGroup() );
+  }
+  
+  /**
    * Creates a {@link JFreeChart} which shows a point for each data iten and
    * a the appropriate regression line.
    * @param dataset        the data
@@ -259,12 +430,7 @@
     XYPlot             plot             = new XYPlot(dataset, xAxis, yAxis, null);
     XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
     XYURLGenerator     urlGenerator     = new StandardXYURLGenerator();
-    XYItemRenderer     renderer         = new SelectionXYLineAndShapeRenderer(false, true) {
-      @Override
-      public FeatureSeriesDatasetSelectionModel createSelectionModel(XYDataset dataset) {
-        return new FeatureSeriesDatasetSelectionModel(dataset);
-      }
-    };
+    XYItemRenderer     renderer         = new XYLineAndShapeRenderer(false, true);
     
     renderer.setBaseToolTipGenerator(toolTipGenerator);
     renderer.setURLGenerator(urlGenerator);
@@ -289,7 +455,7 @@
    * @param seriesKey  the key for the created dataset
    * @param sampleCnt  count of created samples
    */
-  public static XYDataset createRegressionLineDataset(XYSeriesCollection dataset, int series, Comparable seriesKey, int sampleCount) {
+  public static XYDataset createRegressionLineDataset(XYSeriesCollection dataset, int series, Comparable<?> seriesKey, int sampleCount) {
     double minX = dataset.getSeries(0).getMinX();
     double maxX = dataset.getSeries(0).getMaxX();
     return createRegressionLineDataset(dataset,series,seriesKey,minX,maxX,sampleCount);
@@ -304,7 +470,7 @@
    * @param endX       the last value the sample data is created for
    * @param sampleCnt  count of created samples
    */
-  public static XYDataset createRegressionLineDataset(XYDataset dataset, int series, Comparable seriesKey, double startX, double endX, int sampleCount) {
+  public static XYDataset createRegressionLineDataset(XYDataset dataset, int series, Comparable<?> seriesKey, double startX, double endX, int sampleCount) {
     double[]   coefficients = Regression.getOLSRegression(dataset, series);
     Function2D curve        = new LineFunction2D(coefficients[0], coefficients[1]);
     return DatasetUtilities.sampleFunction2D(curve, startX, endX, 2, seriesKey);
@@ -327,6 +493,7 @@
   }
 
 
+
 //###################
 //  BISHER NUR WILDE TESTS
 //###################

Modified: trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/ChartMouseSelectionTracker.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -29,6 +29,7 @@
  ******************************************************************************/
 package schmitzm.jfree.chart;
 
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.util.HashSet;
 import java.util.Set;
@@ -41,7 +42,9 @@
 import schmitzm.geotools.gui.MouseSelectionTracker;
 
 /**
- * This tracker listens to mouse window selections on a {@link ChartPanel}.
+ * This tracker listens to mouse window selections and single mouse
+ * clicks on a {@link ChartPanel}. It determines all selected 
+ * {@link XYItemEntity XYItemEntities}.<b>
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  */
 public abstract class ChartMouseSelectionTracker extends MouseSelectionTracker {
@@ -52,10 +55,21 @@
    * Creates a new listener.
    * @param panel the chart panel connected to the listener (used to
    *              determine the {@link EntityCollection})
+   * @param mode  specifies the selection events the tracker reacts on
    */
+  public ChartMouseSelectionTracker(ChartPanel panel, SelectionMode mode) {
+    super(mode);
+    this.chartPanel    = panel;
+  }
+
+  /**
+   * Creates a new listener which reacts on single clicks as well
+   * as on window selection events.
+   * @param panel the chart panel connected to the listener (used to
+   *              determine the {@link EntityCollection})
+   */
   public ChartMouseSelectionTracker(ChartPanel panel) {
-    super();
-    this.chartPanel = panel;
+    this(panel, SelectionMode.ALL);
   }
   
   /**
@@ -66,20 +80,34 @@
   protected void selectionPerformed(int ox, int oy, int px, int py) {
     // Create rectangle for selection window
     Rectangle2D selectedArea = new Rectangle2D.Double(
-                                     Math.min(ox,px),
-                                     Math.min(oy,py),
-                                     Math.abs(ox-px),
-                                     Math.abs(oy-py) );
+        Math.min(ox,px),
+        Math.min(oy,py),
+        Math.abs(ox-px),
+        Math.abs(oy-py) );
+    // If not a window is selected, but a point, create also
+    // an point object for the click location  
+    Point2D selectedPoint = null;
+    if ( ox == px && oy == py )
+      selectedPoint = new Point2D.Double(ox,oy);
+    
+    // ignore window selection if ONLY_SINGLE_CLICK is set
+    if ( selectedPoint == null &&
+         SelectionMode.ONLY_SINGLE_CLICK.equals(getSelectionMode()) )
+       return;
 
     // Check every chart data points if the selection area
-    // contains it   
+    // contains it (or it contains the selected point)
     HashSet<XYItemEntity> selectedEntities = new HashSet<XYItemEntity>();
     for( Object entityObj : chartPanel.getChartRenderingInfo().getEntityCollection().getEntities() ) {
       ChartEntity entity = (ChartEntity)entityObj;
       // ignore all non-data entities
       if ( !(entity instanceof XYItemEntity) )
         continue;
-      if ( entity.getArea().intersects(selectedArea) )
+      
+      // 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 );
     }
     selectionPerformed(selectedArea, selectedEntities);

Modified: trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/SelectableChartPanel.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -38,15 +38,26 @@
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.entity.XYItemEntity;
+import org.jfree.chart.event.ChartChangeEvent;
+import org.jfree.chart.event.ChartChangeEventType;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.DatasetRenderingOrder;
 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;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.XYDataset;
 
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.chart.renderer.PointSelectionXYRenderer;
+import schmitzm.jfree.chart.renderer.SelectionRenderer;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
-import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
 import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
+import schmitzm.jfree.feature.FeatureSeriesDatasetSelectionModel;
 import schmitzm.lang.LangUtil;
 
 /**
@@ -62,7 +73,7 @@
  */
 public class SelectableChartPanel extends org.jfree.chart.ChartPanel {
 	/** Used for log and debug messages. */
-	protected Logger LOGGER = LangUtil.createLogger(this);
+	private static Logger LOGGER = LangUtil.createLogger(SelectableChartPanel.class);
 
 	/**
 	 * Types of window selection on chart panel.
@@ -152,47 +163,51 @@
 					Set<XYItemEntity> selectedEntities) {
 				LOGGER.debug(selectedEntities.size() + " objects selected");
 
+                Plot plot = getChart().getPlot();
+
 				// remember all changed selection models to reset
-				// "valueAdjusting"
-				// property at the end
+				// "valueAdjusting" property at the end
 				Set<DatasetSelectionModel<?>> changedModels = new HashSet<DatasetSelectionModel<?>>();
-				Plot plot = getChart().getPlot();
+				// 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() ) {
+				    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 = null;
-					if (plot instanceof XYPlot) {
-						XYItemRenderer renderer = ((XYPlot) plot)
-								.getRendererForDataset((XYDataset) dataset);
-						if (renderer instanceof DatasetSelectionModelProvider)
-							selModel = ((DatasetSelectionModelProvider<?>) renderer)
-									.getSelectionModel();
-					}
-
+					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);
 
-						/*
-						 * 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();
-						}
+//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);
+						Comparable<?> seriesKey = e.getDataset().getSeriesKey(series);
 						int item = e.getItem();
 						final SeriesDatasetSelectionModel seriesDatasetSelectionModel = (SeriesDatasetSelectionModel) selModel;
 
@@ -244,50 +259,6 @@
 		};
 		addMouseListener(selectionTracker);
 		setWindowSelectionMode(WindowSelectionMode.ZOOM_IN_CHART);
-
-		// XYPlot p = (XYPlot)getChart().getPlot();
-		// XYLineAndShapeRenderer r = (XYLineAndShapeRenderer)p.getRenderer();
-
-		//    
-		// XYItemRenderer r2 = new
-		// XYLineAndShapeRenderer(r.getBaseLinesVisible(),
-		// r.getBaseShapesVisible()) {
-		// public void drawItem(Graphics2D g, XYItemRendererState state,
-		// Rectangle2D dataArea,
-		// PlotRenderingInfo info,
-		// XYPlot plot,
-		// ValueAxis domainAxis,
-		// ValueAxis rangeAxis,
-		// XYDataset dataset,
-		// int series,
-		// int item,
-		// CrosshairState crosshairState,
-		// int pass) {
-		// if ( !selectedIdx.contains(item) )
-		// return;
-		//        
-		// super.drawItem(g, state, dataArea, info, plot, domainAxis, rangeAxis,
-		// dataset, series, item, crosshairState, pass);
-		// }
-		// };
-		// r.setBasePaint(Color.gray);
-		// r2.setBasePaint(Color.YELLOW);
-		// int datasetCount = p.getDatasetCount();
-		// p.setDataset(datasetCount, p.getDataset());
-		// p.setRenderer(datasetCount, r2);
-		// p.setSeriesRenderingOrder(SeriesRenderingOrder.REVERSE);
-
-		// addChartMouseListener( new ChartMouseListener() {
-		// @Override
-		// public void chartMouseClicked(ChartMouseEvent e) {
-		// System.err.println("MouseClicked: "+e.getEntity());
-		// }
-		// @Override
-		// public void chartMouseMoved(ChartMouseEvent e) {
-		// System.err.println("MouseMoved: "+e.getEntity());
-		// }
-		// });
-
 	}
 
 	/**
@@ -298,7 +269,24 @@
 		repaint();
 	}
 
-	/**
+    /**
+     * Sets the behavior of the chart panel on window selections via mouse.
+     * @param mode new selection mode
+     */
+    public void setWindowSelectionMode(WindowSelectionMode mode) {
+        this.windowSelectionMode = mode;
+        updateStatesForWindowSelectionMode();
+    }
+
+    /**
+     * Returns the behavior of the chart panel on window selections via mouse.
+     * @param selectionMode new selection mode
+     */
+    public WindowSelectionMode getWindowSelectionMode() {
+        return this.windowSelectionMode;
+    }
+
+    /**
 	 * After setting a new chart the zoom relevant properties are reset
 	 * according to the new chart. After calling the super-method, this methods
 	 * resets the properties according to the current
@@ -312,6 +300,9 @@
 		// chart properties!
 		// But we do not want them changed, so reset the states.
 		updateStatesForWindowSelectionMode();
+
+		// create renderers to highlight the selected items
+		updateSelectionRenderers();
 	}
 
 	/**
@@ -324,32 +315,132 @@
 				getFillZoomRectangle());
 		// enable/disable the selection functionality
 		if (selectionTracker != null)
-			selectionTracker
-					.setEnabled(windowSelectionMode != WindowSelectionMode.ZOOM_IN_CHART);
+		  selectionTracker.setEnabled(windowSelectionMode != WindowSelectionMode.ZOOM_IN_CHART);
 	}
-
+	
 	/**
-	 * Sets the behavior of the chart panel on window selections via mouse.
-	 * 
-	 * @param mode
-	 *            new selection mode
+	 * This methods creates a {@link SelectionRenderer} for each {@link Dataset}
+	 * in the plot to realize the highlight of the selected items.
 	 */
-	public void setWindowSelectionMode(WindowSelectionMode mode) {
-		this.windowSelectionMode = mode;
-		updateStatesForWindowSelectionMode();
-
+	protected void updateSelectionRenderers() {
+	  if ( getChart() == null || getChart().getPlot() == null )
+	    return;
+	  Plot plot = getChart().getPlot();
+	  
+	  if ( plot instanceof XYPlot ) {
+        XYPlot xyPlot = (XYPlot)plot;
+        // remove all existing SelectionRenderer
+        for (int i=0; i<xyPlot.getRendererCount(); i++)
+          if ( xyPlot.getRenderer(i) instanceof SelectionRenderer ) {
+            xyPlot.setDataset(i, null);
+            xyPlot.setRenderer(i, null, false);
+          }
+        // add an SelectionRenderer for every "normal" renderer
+        int baseDatasetCount  = xyPlot.getDatasetCount();
+        for (int i=0; i<baseDatasetCount; i++) {
+          XYDataset      dataset         = xyPlot.getDataset(i);
+          XYItemRenderer datasetRenderer = (XYItemRenderer)JFreeChartUtil.getRendererForDataset(xyPlot, i);
+          // Create SelectionRenderer
+          XYItemRenderer selRenderer     = (XYItemRenderer)createSelectionRenderer(dataset);
+          int            selRendererIdx  = baseDatasetCount+i;
+          // Add the new SelectionRenderer with the original dataset
+          xyPlot.setDataset(selRendererIdx, dataset);
+          xyPlot.setRenderer(selRendererIdx, selRenderer, false);
+          applyRendererPropertiesToSelectionRenderer(dataset,(AbstractRenderer)datasetRenderer,(AbstractRenderer)selRenderer);
+        }
+        // revert the rendering order (0 to X) so that the SelectionRenderers
+        // are rendered last and the selected items are shown in foreground
+        xyPlot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
+	  }
+	  
+      if ( plot instanceof CategoryPlot ) {
+        CategoryPlot catPlot = (CategoryPlot)plot;
+        // remove all existing SelectionRenderer
+        for (int i=0; i<catPlot.getRendererCount(); i++)
+          if ( catPlot.getRenderer(i) instanceof SelectionRenderer ) {
+            catPlot.setDataset(i, null);
+            catPlot.setRenderer(i, null, false);
+          }
+        // add an SelectionRenderer for every "normal" renderer
+        int baseDatasetCount  = catPlot.getDatasetCount();
+        for (int i=0; i<baseDatasetCount; i++) {
+          CategoryDataset      dataset         = catPlot.getDataset(i);
+          CategoryItemRenderer datasetRenderer = (CategoryItemRenderer)JFreeChartUtil.getRendererForDataset(catPlot, i);
+          // Create SelectionRenderer
+          CategoryItemRenderer selRenderer     = (CategoryItemRenderer)createSelectionRenderer(dataset);
+          int                  selRendererIdx  = baseDatasetCount+i;
+          // Add the new SelectionRenderer with the original dataset
+          catPlot.setDataset(selRendererIdx, dataset);
+          catPlot.setRenderer(selRendererIdx, selRenderer, false);
+          applyRendererPropertiesToSelectionRenderer(dataset,(AbstractRenderer)datasetRenderer,(AbstractRenderer)selRenderer);
+        }
+        // revert the rendering order (0 to X) so that the SelectionRenderers
+        // are rendered last and the selected items are shown in foreground
+        catPlot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
+      }
+      
+      // fire event about the renderer changes
+      JFreeChartUtil.fireChangeEvent(plot);
 	}
 
-	/**
-	 * Returns the behavior of the chart panel on window selections via mouse.
-	 * 
-	 * @param mode
-	 *            new selection mode
-	 */
-	public WindowSelectionMode getWindowSelectionMode() {
-		return this.windowSelectionMode;
-	}
+    /**
+     * Creates an adequate selection renderer for a dataset. This implementation
+     * returns a renderer which draws only the data points. Sub-classes can
+     * override this method to create different renderers or renderers with
+     * different selection models (e.g. {@link FeatureSeriesDatasetSelectionModel})
+     * for special purposes.
+     * @param dataset a dataset
+     * @return besides {@link SelectionRenderer} the returned object must be
+     *         an {@link AbstractRenderer}  
+     */
+    protected SelectionRenderer<?> createSelectionRenderer(Dataset dataset) {
+      if ( dataset instanceof XYDataset )
+        return new PointSelectionXYRenderer();
 
+      LOGGER.warn("No selection renderer provided for dataset: "+LangUtil.getSimpleClassName(dataset));
+      return null;
+    }
+    
+    /**
+     * Applies some rendering properties to the (new) selection renderer.
+     * This methods simply sets the series shape of the selection renderer
+     * to the shape of the origin renderer, so that the highlighted data
+     * items are drawn the same way as the origin data items.
+     * @param dataset        the dataset for the selection renderer
+     * @param originRenderer the origin renderer for the dataset (should not
+     *                       be changed!)
+     * @param selRenderer    the selection renderer to apply the properties to
+     */
+    protected <E> void  applyRendererPropertiesToSelectionRenderer(Dataset dataset, AbstractRenderer originRenderer, AbstractRenderer selRenderer) {
+      if ( selRenderer == null || originRenderer == null )
+        return;
+      
+      selRenderer.setBaseShape( originRenderer.lookupSeriesShape(0) );
+      selRenderer.setBaseStroke( originRenderer.lookupSeriesStroke(0) );
+      
+      if ( dataset instanceof XYDataset ) {
+        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 ) {
+//        for (int i=0; i<((CategoryDataset)dataset).getSeriesCount(); i++)
+//          if ( ((CategoryItemRenderer)originRenderer).getSeriesShape(i) != null )
+//            ((CategoryItemRenderer)selRenderer).setSeriesShape(i, ((CategoryItemRenderer)originRenderer).getSeriesShape(i));
+      }
+    }
+    /**
+     * If a new dataset is added this method updates the selection
+     * renderers.
+     */
+    @Override
+    public void chartChanged(ChartChangeEvent e) {
+      super.chartChanged(e);
+      if ( ChartChangeEventType.NEW_DATASET.equals( e.getType() ) )
+        updateSelectionRenderers();
+    }
+
 	/**
 	 * Ignores the event if the window selection mode is not
 	 * {@link WindowSelectionMode#ZOOM_IN_CHART}, to avoid conflicts between the two
@@ -373,5 +464,5 @@
 			return;
 		super.mouseMoved(e);
 	}
-
+	
 }

Added: trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.CrosshairState;
+import org.jfree.chart.plot.Plot;
+import org.jfree.chart.plot.PlotRenderingInfo;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYItemRendererState;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
+import schmitzm.lang.LangUtil;
+
+/**
+ * Extends the {@link XYLineAndShapeRenderer} with the
+ * {@link SelectionRenderer} functionality. Additionally redefines
+ * the {@link #drawItem(Graphics2D, XYItemRendererState, Rectangle2D, PlotRenderingInfo, XYPlot, ValueAxis, ValueAxis, XYDataset, int, int, CrosshairState, 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 PointSelectionXYRenderer extends XYLineAndShapeRenderer implements SelectionRenderer<SeriesDatasetSelectionModel> {
+  /** 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 SeriesDatasetSelectionModel selectionModel = null;
+
+  /** Holds the selection color for each series. */
+  protected Map<Integer,Paint> selectionPaint = new HashMap<Integer, Paint>();
+  
+  /**
+   * Creates a new renderer.
+   */
+  public PointSelectionXYRenderer() {
+    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
+   */
+  public void setSelectionModel(SeriesDatasetSelectionModel model) {
+    this.selectionModel = model;
+  }
+  
+  /**
+   * Returns the selection model the renderer uses to determine whether
+   * a data item is selected or not.
+   */
+  public SeriesDatasetSelectionModel 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() {
+    XYPlot  plot       = getPlot();
+    Dataset newDataset = JFreeChartUtil.getDatasetForRenderer(plot,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}
+   */
+  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));
+    return new SeriesDatasetSelectionModel((XYDataset)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 getSelectionPaint(0);
+  }
+
+  /**
+   * Sets the color, the selected data <b>of the primary series</b>
+   * is rendered with.
+   * @param paint color for the selected data
+   */
+  public void setSelectionPaint(Paint paint) {
+    setSelectionPaint(0, 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
+   * 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
+   */
+  public void setPlot(XYPlot 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}).
+   */
+  public void drawItem(Graphics2D g,
+      XYItemRendererState state,
+      Rectangle2D dataArea,
+      PlotRenderingInfo info,
+      XYPlot plot,
+      ValueAxis domainAxis,
+      ValueAxis rangeAxis,
+      XYDataset dataset,
+      int series,
+      int item,
+      CrosshairState crosshairState,
+      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(series);
+      if ( selPaint != null ) {
+        Comparable<?> seriesKey = dataset.getSeriesKey(series);
+        if ( selectionModel.isItemSelected(seriesKey, item) ) {
+          setSeriesPaint( series, selPaint, false );
+          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.");
+    } else
+      LOGGER.debug("No selection model set for renderer. All series rendererd normally.");
+  }
+}

Modified: trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -47,6 +47,7 @@
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.XYDataset;
 
+import schmitzm.jfree.chart.SelectableChartPanel;
 import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
 import schmitzm.lang.LangUtil;
 
@@ -64,6 +65,11 @@
  * 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>
+ * @deprecated This class is not used anymore because the selection rendering
+ *             is no longer realized by the origin dataset renderer (e.g. because
+ *             the selected data items should be rendered in the foregound!).
+ *             Instead the {@link SelectableChartPanel} inserts explicit
+ *             renderers to the plot to draw only the selected data items highlighted. 
  */
 public class SelectionXYLineAndShapeRenderer extends XYLineAndShapeRenderer implements SelectionRenderer<SeriesDatasetSelectionModel> {
   /** Used for log and debug messages. */
@@ -140,8 +146,10 @@
    * according to the given {@link Dataset}. Subclasses can overwrite this
    * method to create an alternative {@link SeriesDatasetSelectionModel}.
    */
-  public SeriesDatasetSelectionModel createSelectionModel(XYDataset dataset) {
-    return new SeriesDatasetSelectionModel(dataset);
+  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));
+    return new SeriesDatasetSelectionModel((XYDataset)dataset);
   }
 
   /**

Modified: trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/selection/DatasetSelectionModelProvider.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -49,10 +49,9 @@
    */
   public void setSelectionModel(E model);
   
-//  /**
-//   * Creates an adequate selection model for a dataset. An implementation should
-//   * simply call {@link DatasetSelectionModel#createInstanceFor(Dataset)}.
-//   * @param dataset a dataset
-//   */
-//  public E createSelectionModel(Dataset dataset);
+  /**
+   * Creates an adequate selection model for a dataset.
+   * @param dataset a dataset
+   */
+  public E createSelectionModel(Dataset dataset);
 }

Modified: trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -420,12 +420,22 @@
       title = new TextTitle();
       chart.setTitle( title );
     }
-    
     if ( getTitleStyle().getLabel() != null )
       title.setText( getTitleStyle().getLabel() );
     if ( getTitleStyle().getPaint() != null )
       title.setPaint( getTitleStyle().getPaint() );
 
+    // Style the chart sub title with chart description
+    if ( getDescStyle() != null ) {
+      if ( chart.getSubtitleCount() == 0 || !(chart.getSubtitle(0) instanceof TextTitle) )
+        chart.addSubtitle(0, new TextTitle());
+      TextTitle subTitle = (TextTitle)chart.getSubtitle(0);
+      if ( getDescStyle().getLabel() != null )
+        subTitle.setText( getDescStyle().getLabel() );
+      if ( getDescStyle().getPaint() != null )
+        subTitle.setPaint( getDescStyle().getPaint() );
+    }
+    
     // Style the chart axis
     Vector<Axis> chartAxis = new Vector<Axis>();
     if ( chart.getPlot() instanceof XYPlot ) {

Modified: trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -309,9 +309,18 @@
     JFreeChart chart = null;
     // XYDataset -> XYBarChart
     if (dataset instanceof XYDataset) {
+      IntervalXYDataset barDataset = null;
+      if ( dataset instanceof TableXYDataset )
+        barDataset = (IntervalXYDataset)dataset;
+      else {
+        barDataset = new XYBarDataset((XYDataset)dataset, 0.5d);
+        // copy properties to new dataset
+        JFreeChartUtil.applyDatasetProperties(barDataset,dataset);
+      }
+        
       chart = ChartFactory.createXYBarChart(
           null,null,false,null, // Title and axis will be configured in applyToChart(..)
-          (IntervalXYDataset)(dataset instanceof TableXYDataset ? (TableXYDataset)dataset : new XYBarDataset( (XYDataset) dataset, 0.5d)),
+          barDataset,
           PlotOrientation.VERTICAL,
           true,
           true,

Added: trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java	2009-08-01 21:27:39 UTC (rev 282)
+++ trunk/src/schmitzm/jfree/feature/FeatureChartPanel.java	2009-08-02 23:16:13 UTC (rev 283)
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.apache.log4j.Logger;
+import org.jfree.chart.JFreeChart;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.chart.SelectableChartPanel;
+import schmitzm.jfree.chart.renderer.PointSelectionXYRenderer;
+import schmitzm.jfree.chart.renderer.SelectionRenderer;
+import schmitzm.jfree.chart.selection.DatasetSelectionModel;
+import schmitzm.lang.LangUtil;
+
+/**
+ * This panel is a special {@link SelectableChartPanel} which uses
+ * special {@link DatasetSelectionModel DatasetSelectionModels} to
+ * connect the chart data with features.
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+ * @version 1.0
+ */
+public class FeatureChartPanel extends SelectableChartPanel {
+  /** Used for log and debug messages. */
+  private static Logger LOGGER = LangUtil.createLogger(FeatureChartPanel.class);
+
+  /**
+   * Creates a new chart panel.
+   */
+  public FeatureChartPanel(JFreeChart chart) {
+      super(chart);
+  }
+
+  /**
+   * Creates a new chart panel.
+   */
+  public FeatureChartPanel(JFreeChart chart, boolean useBuffer) {
+      super(chart, useBuffer);
+  }
+
+  /**
+   * Creates a new chart panel.
+   */
+  public FeatureChartPanel(JFreeChart chart, boolean properties,
+          boolean save, boolean print, boolean zoom, boolean tooltips) {
+      super(chart, properties, save, print, zoom, tooltips);
+  }
+
+  /**
+   * Creates a new chart panel.
+   */
+  public FeatureChartPanel(JFreeChart chart, int width, int height,
+          int minimumDrawWidth, int minimumDrawHeight, int maximumDrawWidth,
+          int maximumDrawHeight, boolean useBuffer, boolean properties,
+          boolean save, boolean print, boolean zoom, boolean tooltips) {
+      super(chart, width, height, minimumDrawWidth, minimumDrawHeight,
+              maximumDrawWidth, maximumDrawHeight, useBuffer, properties,
+              save, print, zoom, tooltips);
+  }
+
+  /**
+   * Creates an adequate selection renderer for a dataset. If provided this
+   * method returns a renderer which uses a {@link FeatureDatasetSelectionModel}
+   * for the dataset. Otherwise the super method is used.
+   * @param dataset a dataset
+   */
+  protected SelectionRenderer<?> createSelectionRenderer(Dataset dataset) {
+    // check whether dataset provides a Feature2DatasetMapping
+    // if not: create a "normal" SelectionRenderer by super-class
+    //         method (without "Feature-Synchronizing" functionality)
+    if ( dataset.getGroup() instanceof FeatureDatasetMetaData &&
+         ((FeatureDatasetMetaData)dataset.getGroup()).getMapping() != null ) {
+    
+      if ( dataset instanceof XYDataset )
+        return new PointSelectionXYRenderer() {
+          @Override
+          public FeatureSeriesDatasetSelectionModel createSelectionModel(Dataset dataset) {
+            if ( !(dataset instanceof XYDataset) )
+              throw new IllegalArgumentException(LangUtil.getSimpleClassName(this)+".createSelectionModel(.) can only be applied for XYDataset: "+LangUtil.getSimpleClassName(dataset));
+            return new FeatureSeriesDatasetSelectionModel((XYDataset)dataset);
+          }
+        };
+
+    }
+    LOGGER.warn("No Feature2DatasetMapping provided for dataset: "+LangUtil.getSimpleClassName(dataset));
+
+    return super.createSelectionRenderer(dataset);
+  }
+}



More information about the Schmitzm-commits mailing list