[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