[Schmitzm-commits] r826 - in trunk/src/schmitzm/jfree: chart/style feature feature/style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed May 5 15:29:49 CEST 2010


Author: mojays
Date: 2010-05-05 15:29:49 +0200 (Wed, 05 May 2010)
New Revision: 826

Added:
   trunk/src/schmitzm/jfree/chart/style/PieChartStyle.java
   trunk/src/schmitzm/jfree/feature/Feature2PieDatasetMapping.java
Modified:
   trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
   trunk/src/schmitzm/jfree/chart/style/ChartRendererStyle.java
   trunk/src/schmitzm/jfree/chart/style/ChartType.java
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
   trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
Log:
- new attribute in FeatureChartStyle to extend the "series attribute" functionality (generate the series legend title from another "series legend title attribute")
- started to implement PieCharts (NOT YET FINISHED and NOT YES USABLE!)

Modified: trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -48,10 +48,13 @@
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.axis.Axis;
 import org.jfree.chart.labels.CategoryToolTipGenerator;
+import org.jfree.chart.labels.PieSectionLabelGenerator;
 import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
+import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
 import org.jfree.chart.labels.StandardXYToolTipGenerator;
 import org.jfree.chart.labels.XYToolTipGenerator;
 import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.PiePlot;
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.renderer.AbstractRenderer;
@@ -59,7 +62,9 @@
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.chart.title.TextTitle;
 import org.jfree.chart.urls.CategoryURLGenerator;
+import org.jfree.chart.urls.PieURLGenerator;
 import org.jfree.chart.urls.StandardCategoryURLGenerator;
+import org.jfree.chart.urls.StandardPieURLGenerator;
 import org.jfree.chart.urls.StandardXYURLGenerator;
 import org.jfree.chart.urls.XYURLGenerator;
 
@@ -79,12 +84,15 @@
   protected XYToolTipGenerator TIPGEN_XY = new StandardXYToolTipGenerator();
   /** Tooltip generator used for Category-Charts. */
   protected CategoryToolTipGenerator TIPGEN_CAT = new StandardCategoryToolTipGenerator();
+  /** Tooltip generator used for Pie-Charts. */
+  protected PieSectionLabelGenerator TIPGEN_PIE = new StandardPieSectionLabelGenerator();
   /** URL generator used for XY-Charts. */
   protected XYURLGenerator URLGEN_XY = new StandardXYURLGenerator();
   /** URL generator used for Category-Charts. */
   protected CategoryURLGenerator URLGEN_CAT = new StandardCategoryURLGenerator();
-  
-  
+  /** URL generator used for Pie-Charts. */
+  protected PieURLGenerator URLGEN_PIE = new StandardPieURLGenerator();
+    
   /** Logger for this class */
   protected final Category LOGGER = LangUtil.createLogger(this);
   /** Holds a (unique) ID for the style. */
@@ -469,6 +477,18 @@
         if ( renderer != null && rendererStyle != null )
           rendererStyle.applyToRenderer((AbstractRenderer)renderer);
       }
+// TODO: Fuer PieCharts hier weiter implementieren
+//    } else if ( chart.getPlot() instanceof PiePlot ) {
+//      PiePlot plot = (PiePlot)chart.getPlot();
+//      plot.setLegendLabelToolTipGenerator( hasTooltips() ? TIPGEN_PIE : null );
+//      plot.setLegendLabelURLGenerator( hasURLs() ? URLGEN_PIE : null );
+//      // Orientation is ignored (not applicable for PieChart)
+//
+//      // style renderer
+//      ChartRendererStyle  rendererStyle = getRendererStyle(0);
+//      if ( rendererStyle != null )
+//        rendererStyle.applyToRenderer((AbstractRenderer)renderer);
+//      }
     }
     
     // style plot

Modified: trunk/src/schmitzm/jfree/chart/style/ChartRendererStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/ChartRendererStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/chart/style/ChartRendererStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -39,6 +39,7 @@
 import org.jfree.chart.labels.StandardCategorySeriesLabelGenerator;
 import org.jfree.chart.labels.StandardXYSeriesLabelGenerator;
 import org.jfree.chart.labels.XYSeriesLabelGenerator;
+import org.jfree.chart.plot.PiePlot;
 import org.jfree.chart.renderer.AbstractRenderer;
 import org.jfree.chart.renderer.category.AbstractCategoryItemRenderer;
 import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
@@ -437,6 +438,77 @@
   }
   
   
+// TODO: Fuer PieCharts hier weiter implementieren
+//  /**
+//   * Applies the rendering style to a pie plot.<br>
+//   * <b>Note</b>:
+//   * <ul>
+//   *   <li>Because PieCharts have no multiple series, only the "series" style
+//   *       with index 0 (of the RendererStyle) is taken into account./li>
+//   * </ul>
+//   * @param renderer a renderer
+//   */
+//  public void applyToRenderer(PiePlot piePlot) {
+//    if (piePlot == null) {
+//      LOGGER.debug("No renderer to be customised.");
+//      return;
+//    }
+//
+//    // Apply item label visibility (only the first "series" is
+//    // taken into account)
+//    // TODO: can not be applied to PiePlot, only the lines can be
+//    //       set in/visible
+//    if ( isSeriesItemLabelsVisible(0) != null )
+//      piePlot.setLabelLinksVisible(isSeriesItemLabelsVisible(0));
+//    
+//    // Apply shape visibility
+//    for (int series : seriesShapesVisible.keySet())
+//      try {
+//        if ( isSeriesShapesVisible(series) != null ) {
+//            final Shape shape = isSeriesShapesVisible(series) ? 
+//              AbstractRenderer.DEFAULT_SHAPE
+//              : null;
+//            renderer.setSeriesShape(series,
+//                      shape,
+//                      false);
+////          LOGGER.debug("Setting shape = "+shape +" for series "+series);
+//        }
+//        
+//      } catch (Exception err) {
+//        LOGGER.warn("Renderer contains not series "+series+". Shapes visibility can not be applied.");
+//      }
+//
+//    // Apply rendering color
+//    for (int series : seriesPaint.keySet())
+//      try {
+//        if ( getSeriesPaint(series) != null )
+//          renderer.setSeriesPaint(series, getSeriesPaint(series), false);
+//      } catch (Exception err) {
+//        LOGGER.warn("Renderer contains not series "+series+". Paint can not be applied.");
+//      }
+//
+//    // Apply legend visibility
+//    for (int series : seriesLegendVisible.keySet())
+//      try {
+//        if ( isSeriesLegendVisible(series) != null )
+//          renderer.setSeriesVisibleInLegend(series, isSeriesLegendVisible(series), false);
+//      } catch (Exception err) {
+//        LOGGER.warn("Renderer contains not series "+series+". Legend visibility can not be applied.");
+//      }
+//
+//    // Other properties must be applied according to the specific renderer type
+//    if (renderer instanceof XYBarRenderer)
+//      applyToBarRenderer((XYBarRenderer)renderer);
+//    if (renderer instanceof AbstractXYItemRenderer)
+//      applyToXYItemRenderer((AbstractXYItemRenderer)renderer);
+//    if (renderer instanceof AbstractCategoryItemRenderer)
+//      applyToCategoryItemRenderer((AbstractCategoryItemRenderer)renderer);
+//    
+//    // notify the listeners about style change
+//    JFreeChartUtil.fireChangeEvent(renderer);
+//    
+//  }
+
   /**
    * This class implements a label generator based on the
    * <b>legend label</b> definitions of this style, which can be used also

Modified: trunk/src/schmitzm/jfree/chart/style/ChartType.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/ChartType.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/chart/style/ChartType.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -188,6 +188,7 @@
 		switch (this) {
 		case SCATTER:
 			return false;
+		case PIE:
 		case BAR:
 		case LINE:
 		case AREA:

Added: trunk/src/schmitzm/jfree/chart/style/PieChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/PieChartStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/chart/style/PieChartStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+/*
+ *  SDSS Framework - This file is part of the Spatial Decision Support System Framework Platform
+ *
+ *  BasicChartStyle.java
+ *
+ *  Responsible developper: Andreas Enders, Geographical Institut, Hydrology Research Group, Meckenheimer Allee 166, 53115 Bonn, Germany
+ *                                          IMPETUS Project, www.impetus.uni-koeln.de
+ *  Contact Information:                    info at andreas-enders.de
+ */
+
+package schmitzm.jfree.chart.style;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.general.PieDataset;
+import org.jfree.data.xy.IntervalXYDataset;
+import org.jfree.data.xy.TableXYDataset;
+import org.jfree.data.xy.XYBarDataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.lang.LangUtil;
+
+/**
+ * This class provides a basis chart style for pie charts.
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+ * @version 1.0
+ */
+public class PieChartStyle extends AbstractChartStyle {
+
+  /**
+   * Creates a normal pie style with default values.
+   * @param id   a (unique) ID for the style
+   */
+  public PieChartStyle(String id) {
+    this(id, null, null, null, true, true, true);
+  }
+
+  /**
+   * Creates a chart style.
+   * @param id       a (unique) ID for the style
+   * @param title    title for the chart
+   * @param xTitle   title for the chart's X-axis
+   * @param yTitle   title for the chart's Y-axis
+   * @param legend   flag whether a legend is generated
+   * @param tooltips flag whether toolstips are generated
+   * @param urls     flag whether URLs are generated
+   */
+  public PieChartStyle(String id, 
+                       String title,   String xTitle,    String yTitle,
+                       boolean legend, boolean tooltips, boolean urls) {
+    super(id, ChartType.PIE, title, xTitle, yTitle, legend, tooltips, urls);
+  }
+
+  /**
+   * Creates a (deep) clone of this chart style.
+   */
+  @Override
+  public PieChartStyle copy() {
+    return (PieChartStyle) copyTo( new PieChartStyle("") );
+  }
+  
+  /**
+   * Copies all properties of this chart style to another
+   * chart style.
+   * @param dest destination object (if {@code null} the copy
+   *             is created by {@link #copy()})
+   * @return {@code dest} or the new instance
+   * @exception IllegalArgumentException if {@code dest} is no
+   *            {@link AbstractChartStyle}
+   */
+  @Override
+  public ChartStyle copyTo(ChartStyle dest) {
+    // copy the super class properties
+    dest = super.copyTo(dest);
+    if ( dest instanceof PieChartStyle ) {
+      PieChartStyle destBCS = (PieChartStyle) dest;
+      // copy this classes properties
+      // ...
+    }
+    return dest;
+  }
+
+  /**
+   * Creates a chart for the given {@link Dataset} and applies the style.
+   * @param dataset the data for the chart
+   * @exception UnsupportedOperationException if the style can not be applied
+   *            to the given dataset
+   */
+  public JFreeChart applyToDataset(Dataset dataset) {
+    if ( !(dataset instanceof PieDataset) )
+      throw new UnsupportedOperationException(LangUtil.getSimpleClassName(this)+" can only be applied to PieDataset!");
+    return applyToDataset((PieDataset)dataset);
+  }
+
+  /**
+   * Creates a chart for the given {@link Dataset} and applies the style.
+   * @param dataset the data for the chart
+   * @exception UnsupportedOperationException if the style can not be applied
+   *            to the given dataset
+   */
+  public JFreeChart applyToDataset(PieDataset dataset) {
+    JFreeChart chart = ChartFactory.createPieChart(null, dataset, legend, tooltips, urls);
+    applyToChart(chart);
+    return chart;  }
+  
+  /**
+   * Applies the style to an existing chart.
+   * @param chart chart the style is applied to
+   */
+  public void applyToChart(JFreeChart chart) {
+    // apply the pie chart properties
+    // ...
+    super.applyToChart(chart);
+  }
+  
+
+  /**
+   * Creates a line chart from an {@link XYDataset} or {@link CategoryDataset}
+   * @param dataset Dataset
+   */
+  private JFreeChart createLineChart(Dataset dataset) {
+    JFreeChart chart = null;
+    // XYDataset -> XYLineChart
+    if (dataset instanceof XYDataset) {
+      chart = ChartFactory.createXYLineChart(
+          null,null,null, // Title and axis will be configured in applyToChart(..)
+          (XYDataset)dataset,
+          orientation,
+          legend,
+          tooltips,
+          urls
+      );
+    }
+    // CategoryDataset -> LineChart
+    if (dataset instanceof CategoryDataset) {
+      chart = ChartFactory.createLineChart(
+          null,null,null, // Title and axis will be configured in applyToChart(..)
+          (CategoryDataset)dataset,
+          orientation,
+          legend,
+          tooltips,
+          urls
+      );
+    }
+    return chart;
+  }
+}

Added: trunk/src/schmitzm/jfree/feature/Feature2PieDatasetMapping.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/Feature2PieDatasetMapping.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/Feature2PieDatasetMapping.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.FeatureCollection;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.PieDataset;
+import org.opengis.feature.simple.SimpleFeature;
+
+/**
+ * This class implements the mapping between {@link PieDataset} items (pie pieces in chart)
+ * and the corresponding {@link SimpleFeature Features}.
+ * The structure of this mapping assumes that is only one dataset item
+ * for one feature and only one feature for each dataset item.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class Feature2PieDatasetMapping extends Feature2DatasetMapping<PieDataset,Comparable<?>,Comparable<?>> {
+  /**
+   * Creates a mapping. 
+   * @param fc a {@link FeatureCollection} (can be {@code null})
+   * @param dataset a {@link PieDataset} 
+   */
+  public Feature2PieDatasetMapping(FeatureCollection fc, PieDataset dataset) {
+    super(fc, dataset);
+  }
+
+  /**
+   * Returns an empty string because a {@link PieDataset} has only one
+   * series and there is nothing like "series key" for this.
+   */
+  public Comparable<?> getPrimarySeriesKey() {
+    return "";
+  }
+  
+}

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -499,6 +499,23 @@
     }
 
     /**
+     * Defines the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     * @param attrName feature attribute name
+     */
+    public void setSeriesLegendTitleAttributeName(String attrName) {
+      dummyFeatureChartStyle.setSeriesLegendTitleAttributeName(attrName);
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     */
+    public String getSeriesLegendTitleAttributeName() {
+      return dummyFeatureChartStyle.getSeriesLegendTitleAttributeName();
+    }
+
+    /**
      * Creates an appropriate {@link Dataset} for the attributes defined
      * by this style (according to the attributes types in the given
      * {@link FeatureCollection}) and calls {@link #applyToDataset(Dataset)}.

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -345,6 +345,18 @@
    */
   public <T> T filterSeriesAttributeNoDataValue(T value);
 
+  /**
+   * Defines the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   * @param attrName feature attribute name
+   */
+  public void setSeriesLegendTitleAttributeName(String attrName);
+  
+  /**
+   * Returns the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   */
+  public String getSeriesLegendTitleAttributeName();
 
   /**
    * Creates a chart according to the given
@@ -434,6 +446,12 @@
     protected Set<Object> seriesAttrNoDataValues = new HashSet<Object>();
 
     /**
+     * Holds the name of the attribute, whose values define the legend
+     * title for the series defined by {@link #seriesAttrName}.
+     */
+    protected String seriesLegendTitleAttrName = null;
+
+    /**
      * Creates a new dummy. This constructor is protected so that only derived
      * classes can instantiate a dummy! There is no limit for the number of
      * attributes which can be defined by the style.
@@ -1009,6 +1027,23 @@
     }
 
     /**
+     * Defines the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     * @param attrName feature attribute name
+     */
+    public void setSeriesLegendTitleAttributeName(String attrName) {
+      seriesLegendTitleAttrName = attrName;
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     */
+    public String getSeriesLegendTitleAttributeName() {
+      return seriesLegendTitleAttrName;
+    }
+
+    /**
      * Does nothing, but always throws a {@link UnsupportedOperationException},
      * because the dummy can not provide this functionality.
      */

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -121,6 +121,9 @@
       nullAliases = XMLUtil.getSetAttribute(seriesAttrElem, "nullAliases");
       if (nullAliases != null)
         chartStyle.setSeriesAttributeNoDataValues(nullAliases);
+      String seriesLegendLableAttrName = XMLUtil.getAttribute(seriesAttrElem, "titleAttrName");
+      if (seriesLegendLableAttrName != null)
+        chartStyle.setSeriesLegendTitleAttributeName(seriesLegendLableAttrName);
     }
 }
 
@@ -179,7 +182,8 @@
     if ( style.getSeriesAttributeName() != null )
       addChildToElement(attrElem, "seriesAttr", false,
           "name", style.getSeriesAttributeName(),
-          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getSeriesAttributeNoDataValues()) 
+          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getSeriesAttributeNoDataValues()),
+          "titleAttrName", style.getSeriesLegendTitleAttributeName()
       );
 
     return root;

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -52,6 +52,8 @@
 import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.category.DefaultCategoryDataset;
 import org.jfree.data.general.Dataset;
+import org.jfree.data.general.DefaultPieDataset;
+import org.jfree.data.general.PieDataset;
 import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
@@ -65,10 +67,13 @@
 import schmitzm.jfree.JFreeChartUtil;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
+import schmitzm.jfree.chart.style.ChartLabelStyle;
+import schmitzm.jfree.chart.style.ChartRendererStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
 import schmitzm.jfree.feature.AggregationFunction;
 import schmitzm.jfree.feature.Feature2CategoryDatasetMapping;
+import schmitzm.jfree.feature.Feature2PieDatasetMapping;
 import schmitzm.jfree.feature.Feature2SeriesDatasetMapping;
 import schmitzm.jfree.feature.FeatureDatasetMetaData;
 import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
@@ -467,7 +472,7 @@
   }
 
   /**
-   * } Calculates statistics needed to normalize data. If normalization is not
+   * Calculates statistics needed to normalize data. If normalization is not
    * used, this function returns an empty map.
    * @param fc {@link FeatureCollection} where the data comes from
    * @param chartStyle {@link ChartStyle} to determine which attributes shall be
@@ -691,6 +696,15 @@
             if ( seriesID != null )
               yAttrName = yAttrName + "_" + seriesID.toString();
             dataset.addValue(yValue, yAttrName, catValue);
+            // If grouping series attribute is used, and a "legend title" attribute
+            // is set, overwrite the legend label in the chart style 
+            if ( seriesID != null && chartStyle.getSeriesLegendTitleAttributeName() != null ) {
+              // determine the series index for the current series key
+              int seriesIdx = dataset.getRowIndex(yAttrName);
+              // overwrite the series legend label in chart style
+              redefineSeriesLegendTitle(chartStyle, seriesIdx, f);
+            }
+            
             // Mapping between FID and data index in series
             mapping.setMapping(f.getID(), yAttrName, catValue);
           } else {
@@ -743,6 +757,204 @@
   }
 
   /**
+   * Creates a {@link PieDataset} for 2 attributes of a
+   * {@link FeatureCollection}. PieDataset can only be created for a
+   * <b>numeric</b> range attribute.
+   * @param fc a {@link FeatureCollection}
+   * @param style defines the attributes used to create the dataset from, as
+   *          well as the sorting and normalization properties
+   * @throws IllegalArgumentException if not exactly 2 attributes are specified
+   * @throws UnsupportedOperationException if attributes are not numeric
+   */
+  public static DefaultPieDataset createPieDataset(
+      FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+      FeatureChartStyle chartStyle) {
+    int attrCount = chartStyle.getAttributeCount();
+    if (attrCount != 2)
+      throw new IllegalArgumentException(
+          "FeatureChartStyle must define at exactly 2 attributes to create PieDataset: " +
+              attrCount);
+    
+    String catAttrName = chartStyle.getAttributeName(ChartStyle.DOMAIN_AXIS);
+    // check whether category attribute exists (numeric and not-numeric allowed)
+    checkAttributeType(fc.getSchema(), catAttrName, Comparable.class,
+                       "Domain attribute", "PieDataset");
+    // check data type of range attribute (only numeric allowed)
+    String rangeAttrName = chartStyle.getAttributeName(ChartStyle.RANGE_AXIS);
+    int    rangeAttrIdx  = ChartStyle.RANGE_AXIS;
+    checkAttributeType(fc.getSchema(), rangeAttrName, Number.class,
+                       "Range attribute", "PieDataset");
+
+    // Calculate statistics to normalize not-aggregated attributes
+    HashMap<String, QuantileBin1D> statisticsForNormalization = calcStatisticsForNotAggregatedNormalization(
+                                                                                                            fc,
+                                                                                                            chartStyle);
+    // Calculate weight sums for all weight-aggregated attributes
+    HashMap<Comparable<?>, Double>[] weightSumsForAggregation = calcWeightSumForAggregation(
+                                                                                            fc,
+                                                                                            chartStyle);
+    // Prepare set for statistics to calculate aggregation functions (one
+    // statistic for each range attribute of each domain value)
+    HashMap<Comparable<?>, QuantileBin1D> statisticsForAggregation = new HashMap<Comparable<?>, QuantileBin1D>();
+
+    // Create a new dataset and insert the series
+    DefaultPieDataset dataset = new DefaultPieDataset();
+    Feature2PieDatasetMapping mapping = new Feature2PieDatasetMapping(
+        fc, dataset);
+    dataset.setGroup(new FeatureDatasetMetaData(mapping));
+
+    // If dataset should be sorted, the features must be sorted first
+    // according to the domain attribute. The sort functionality can not be
+    // used because of the lost of the "data item to feature"-mapping (see
+    // createXYDataset(..))
+    FeatureIterator<SimpleFeature> features = null;
+    Iterator<SimpleFeature> fi = null;
+    if (chartStyle.isSortDomainAxis()) {
+      Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
+                                                                      catAttrName);
+      // Create an Iterator for the sorted Features
+      fi = sortedFeatures.iterator();
+    } else {
+      features = fc.features();
+      fi = new PipedFeatureIterator(features);
+    }
+
+    // Iterate the FeatureCollection and fill the dataset
+    try {
+      for (int fIdx = 0; fi.hasNext(); fIdx++) {
+        SimpleFeature f = fi.next();
+        // Determine the category (NULL not permitted!)
+        Comparable<?> catValue = (Comparable<?>) f.getAttribute(catAttrName);
+        // Filter out NODATA values
+        catValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS,
+                                                catValue);
+        if (catValue == null)
+          continue;
+        
+// SERIES GROUPING IS NOT SUPPORTED FOR PIE CHARTS BECAUSE THERE IST
+// ONLY ONE SERIES
+        // If grouping series attribute is used, filter out
+        // its no data values
+        Object seriesID = null;
+//        if ( chartStyle.getSeriesAttributeName() != null ) {
+//          seriesID = determineSeriesAttributeValueFromFeature(f, chartStyle);
+//          if ( seriesID == null )
+//            continue;
+//        }
+        
+        // Determine the pie piece value and fill the dataset
+        Double rangeValue = determineRangeValueFromFeature(
+                                                       f,
+                                                       catValue,
+                                                       rangeAttrIdx, 
+                                                       chartStyle,
+                                                       statisticsForNormalization,
+                                                       weightSumsForAggregation);
+        // Ignore feature if value is invalid
+        if (rangeValue == null)
+          continue;
+
+        // Fill series, if no aggregation function is defined.
+        // Otherwise fill statistic (dataset is filled later!)
+        if (chartStyle.getAttributeAggregation(rangeAttrIdx) == null) {
+          // Add data to dataset
+// SERIES GROUPING IS NOT SUPPORTED FOR PIE CHARTS BECAUSE THERE IST
+// ONLY ONE SERIES
+//          // If grouping series attribute is used, add its value
+//          // to the series ID
+//          if ( seriesID != null )
+//            yAttrName = yAttrName + "_" + seriesID.toString();
+          dataset.setValue(catValue,rangeValue);
+          // Mapping between FID and data item
+          mapping.setMapping(f.getID(), catValue);
+        } else {
+          QuantileBin1D aggrStat = statisticsForAggregation.get(catValue);
+          if (aggrStat == null) {
+            aggrStat = new DynamicBin1D();
+            statisticsForAggregation.put(catValue, aggrStat);
+          }
+          aggrStat.add(rangeValue.doubleValue());
+          // TODO: Mapping vormerken (??)
+          // Problem: siehe unten
+        }
+      }
+    } finally {
+      if (features != null) {
+        fc.close(features);
+      }
+    }
+
+    // Fill series for aggregated range attributes
+    statisticsForNormalization = calcStatisticsForAggregatedNormalization(
+                                                                          new HashMap[] { statisticsForAggregation },
+                                                                          chartStyle);
+    AggregationFunction aggrFunc = chartStyle.getAttributeAggregation(rangeAttrIdx);
+    if (aggrFunc != null) {
+      for (Comparable<?> catValue : statisticsForAggregation.keySet()) {
+        QuantileBin1D aggrStat = statisticsForAggregation.get(catValue);
+        Number rangeValue = getAggregationResult(aggrFunc, aggrStat);
+  
+        // Normalize the aggregated value
+        if (chartStyle.isAttributeNormalized(rangeAttrIdx))
+          rangeValue = normalize(rangeValue, rangeAttrName, statisticsForNormalization);
+  
+        // Fill series
+        dataset.setValue(catValue, rangeValue);
+        // TODO: Mapping setzen
+        // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
+        // werden (Feature2DatasetMapping, Zeile 124)
+        // // Mapping between FID and data index in series
+        // mapping.setMapping(f.getID() ??, yAttrName,
+        // datasetIdx++);
+      }
+    }
+    
+    return dataset;
+  }
+
+  /**
+   * Changes the series legend label in a chart style according to the
+   * value of the {@linkplain FeatureChartStyle#getSeriesLegendTitleAttributeName() legend label attribute}
+   * defined in the chart style. <br>
+   * Does nothing if the chart style does not define a series legend label
+   * attribute or the attribute value is {@code null} or empty.
+   * 
+   * @param chartStyle the chart style to update the legend title in
+   * @param seriesIdx  the series index in the {@link ChartRendererStyle} to update
+   * @param f          the feature the legend label is taken from
+   * @see FeatureChartStyle#getSeriesLegendTitleAttributeName()
+   */
+  private static boolean redefineSeriesLegendTitle(FeatureChartStyle chartStyle, int seriesIdx, SimpleFeature f) {
+    if ( chartStyle.getSeriesLegendTitleAttributeName() == null )
+      return false;
+    
+    Object seriesLabel = f.getAttribute(chartStyle.getSeriesLegendTitleAttributeName());
+    // only apply the new legend label, if the "title attribute" value is
+    // not null and not empty
+    if ( seriesLabel == null )
+      return false;
+    String seriesLabelStr = seriesLabel.toString().trim();
+    if ( "".equals(seriesLabelStr) )
+      return false;
+    
+    // Create a renderer style if it does not exist yet
+    if ( chartStyle.getRendererStyle(0) == null )
+      chartStyle.setRendererStyle(0, new ChartRendererStyle());
+    // Do not change the label if the existing label equals the
+    // new label
+    if ( seriesLabel.equals( chartStyle.getRendererStyle(0).getSeriesLegendLabel(seriesIdx) ) )
+      return false;
+     
+    // redefine the legend label for the given series
+    chartStyle.getRendererStyle(0).setSeriesLegendLabel(
+                                                        seriesIdx,
+                                                        new ChartLabelStyle(seriesLabelStr)   
+    );
+    return true;
+  }
+  
+  
+  /**
    * After loading from XML, a {@link FeatureChartStyle} contains whatever is
    * written in the XML. But the DBF Schema can change quickly by accident! This
    * method checks an {@link FeatureChartStyle} against a schema and corrects

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-05-05 13:23:18 UTC (rev 825)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-05-05 13:29:49 UTC (rev 826)
@@ -511,6 +511,24 @@
   }
 
   /**
+   * Defines the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   * @param attrName feature attribute name
+   */
+  public void setSeriesLegendTitleAttributeName(String attrName) {
+    dummyFeatureChartStyle.setSeriesLegendTitleAttributeName(attrName);
+  }
+  
+  /**
+   * Returns the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   */
+  public String getSeriesLegendTitleAttributeName() {
+    return dummyFeatureChartStyle.getSeriesLegendTitleAttributeName();
+  }
+
+
+  /**
    * Creates an appropriate {@link Dataset} for the attributes defined
    * by this style (according to the attributes types in the given
    * {@link FeatureCollection}) and calls {@link #applyToDataset(Dataset)}.



More information about the Schmitzm-commits mailing list