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

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Sun Jul 12 14:17:03 CEST 2009


Author: mojays
Date: 2009-07-12 14:17:01 +0200 (Sun, 12 Jul 2009)
New Revision: 211

Added:
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
Modified:
   trunk/src/schmitzm/jfree/JFreeChartUtil.java
   trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java
   trunk/src/schmitzm/jfree/chart/style/ChartStyleXMLFactory.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
Log:
new FeatureBasicChartStyle

Modified: trunk/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/JFreeChartUtil.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -32,8 +32,21 @@
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.renderer.AbstractRenderer;
+import org.jfree.chart.renderer.category.AreaRenderer;
+import org.jfree.chart.renderer.category.BarRenderer;
+import org.jfree.chart.renderer.category.CategoryItemRenderer;
+import org.jfree.chart.renderer.category.CategoryStepRenderer;
+import org.jfree.chart.renderer.category.LineAndShapeRenderer;
+import org.jfree.chart.renderer.category.StackedAreaRenderer;
+import org.jfree.chart.renderer.category.StackedBarRenderer;
+import org.jfree.chart.renderer.xy.StackedXYAreaRenderer2;
+import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
+import org.jfree.chart.renderer.xy.XYAreaRenderer;
+import org.jfree.chart.renderer.xy.XYBarRenderer;
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.chart.renderer.xy.XYStepAreaRenderer;
+import org.jfree.chart.renderer.xy.XYStepRenderer;
 import org.jfree.chart.title.LegendTitle;
 import org.jfree.chart.title.Title;
 import org.jfree.chart.urls.StandardXYURLGenerator;
@@ -49,6 +62,10 @@
 import schmitzm.jfree.chart.renderer.SelectionXYLineAndShapeRenderer;
 import schmitzm.jfree.chart.selection.DatasetSelectionModel;
 import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
+import schmitzm.jfree.chart.style.BasicChartStyle;
+import schmitzm.jfree.chart.style.ChartStyle;
+import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
+import schmitzm.jfree.chart.style.ChartStyle.ChartType;
 import schmitzm.jfree.feature.Feature2SeriesDatasetMapping;
 import schmitzm.jfree.feature.FeatureDatasetMetaData;
 import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
@@ -70,6 +87,9 @@
    *  hinterlegt. */
   public static ResourceProvider RESOURCE = new ResourceProvider( LangUtil.extendPackagePath(JFreeChartUtil.class,"resource.locales.JFreeResourceBundle"), Locale.ENGLISH );
 
+  /** Instance of {@link ChartStyleXMLFactory}. */
+  public static final ChartStyleXMLFactory<ChartStyle> CHART_STYLE_FACTORY = new ChartStyleXMLFactory<ChartStyle>();
+
   /**
    * Sets all chart legends (in)visible.
    * @param chart   a chart to apply
@@ -100,6 +120,110 @@
   }
 
   /**
+   * Creates a {@link XYItemRenderer} for the given stepped and stacked
+   * properties.
+   * @param type    chart type
+   * @param stepped stepped property
+   * @param stacked stacked property
+   */
+  public static XYItemRenderer createXYRenderer(BasicChartStyle style) {
+    return createXYRenderer(
+        style.getType(),
+        style.isStepped(),
+        style.isStacked()
+    );
+  }
+  
+  /**
+   * Creates a {@link XYItemRenderer} for the given stepped and stacked
+   * properties.
+   * @param type    chart type
+   * @param stepped stepped property
+   * @param stacked stacked property
+   */
+  public static XYItemRenderer createXYRenderer(ChartType type, boolean stepped, boolean stacked) {
+    switch ( type ) {
+      case LINE: // "stacked" is not available for line charts
+                 if ( stacked )
+                   LOGGER.warn("Stacked property can not be applied to line charts. Property ignored!");
+                 // Create renderer according to "stepped"
+                 if ( stepped )
+                   return new XYStepRenderer();
+                 // normal line renderer
+                 return new XYLineAndShapeRenderer(true, false);
+      case AREA: // Apply stacked
+                 if ( stacked ) {
+                   // "stacked" and "stepped" can not be applied the same time
+                   if ( stepped )
+                     LOGGER.warn("A stacked area chart can not be stepped the same time (use a stacked bar chart instead). Stepped propery ignored!");
+                   // Stacked area renderer
+                   return new StackedXYAreaRenderer2();
+                 }
+                 // Stepped area renderer
+                 if ( stepped )
+                   return new XYStepAreaRenderer(XYStepAreaRenderer.AREA);
+                 // Neither stepped nor stepped
+                 return new XYAreaRenderer(XYAreaRenderer.AREA);
+      case BAR: // bar charts are automatically stepped,
+                // so only "stacked" is applied
+                if ( stacked )
+                  return new StackedXYBarRenderer();
+                // Normal bar renderer
+                return new XYBarRenderer();
+    }
+    throw new UnsupportedOperationException("XYItemRenderer could not be created for chart type: "+type); 
+  }
+
+  
+  /**
+   * Creates a {@link CategoryItemRenderer} for the given stepped and stacked
+   * properties.
+   * @param type    chart type
+   * @param stepped stepped property
+   * @param stacked stacked property
+   */
+  public static CategoryItemRenderer createCategoryRenderer(BasicChartStyle style) {
+    return createCategoryRenderer(
+        style.getType(),
+        style.isStepped(),
+        style.isStacked()
+    );
+  }
+  
+  /**
+   * Creates a {@link CategoryItemRenderer} for the given stepped and stacked
+   * properties.
+   * @param type    chart type
+   * @param stepped stepped property
+   * @param stacked stacked property
+   */
+  public static CategoryItemRenderer createCategoryRenderer(ChartType type, boolean stepped, boolean stacked) {
+    switch ( type ) {
+      case LINE: // "stacked" is not available for line charts
+                 if ( stacked )
+                   LOGGER.warn("Stacked property can not be applied to line charts. Property ignored!");
+                 // Create renderer according to "stepped"
+                 if ( stepped )
+                   return new CategoryStepRenderer();
+                 // normal line renderer
+                 return new LineAndShapeRenderer(true, false);
+      case AREA: // category area chart is automatically stepped,
+                 // so only "stacked" is applied
+                 if ( stacked )
+                   return new StackedAreaRenderer(false);
+                 // Normal area renderer
+                 return new AreaRenderer();
+      case BAR: // bar charts are automatically stepped,
+                // so only "stacked" is applied
+                if ( stacked )
+                  return new StackedBarRenderer(false);
+                // Normal bar renderer
+                return new BarRenderer();
+    }
+    throw new UnsupportedOperationException("CategoryItemRenderer could not be created for chart type: "+type); 
+  }
+
+  /**
    * Creates a {@link XYDataset} for 2 attributes of a {@link FeatureCollection}.
    * @param fc    a {@link FeatureCollection}
    * @param seriesKey   a (unique) key for the {@link XYSeries} in the dataset

Modified: trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/chart/style/BasicChartStyle.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -12,12 +12,17 @@
 
 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.chart.renderer.category.CategoryStepRenderer;
 import org.jfree.chart.renderer.category.StackedAreaRenderer;
 import org.jfree.chart.renderer.category.StackedBarRenderer;
 import org.jfree.chart.renderer.xy.StackedXYAreaRenderer2;
 import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
+import org.jfree.chart.renderer.xy.XYAreaRenderer;
+import org.jfree.chart.renderer.xy.XYItemRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
 import org.jfree.chart.renderer.xy.XYStepAreaRenderer;
 import org.jfree.chart.renderer.xy.XYStepRenderer;
 import org.jfree.data.category.CategoryDataset;
@@ -26,13 +31,16 @@
 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 line, area an bar charts.
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
-public class BasicChartStyle extends AbstractChartStyle {
+public class BasicChartStyle extends AbstractChartStyle {
   /** Stores whether the chart is stacked. Line charts can never be stacked. */
   protected boolean stacked = false;
   /** Stores whether the chart is stepped. Bar charts are always stepped. */
@@ -89,6 +97,13 @@
     setStacked( stacked );
     setStepped( stepped );
     setOrientation( orientation );
+  }
+
+  /**
+   * Throws an {@link UnsupportedOperationException}.
+   */
+  protected void throwUnsupportedTypeException() {
+    throw new IllegalArgumentException("Only ChartType.LINE, ChartType.AREA or ChartType.BAR allowed for "+LangUtil.getSimpleClassName(this)+"!");
   }
 
   /**
@@ -98,7 +113,8 @@
    *            {@link ChartType#LINE}, {@link ChartType#AREA} or
    *            {@link ChartType#BAR}
    */
-  public void setType(ChartType type) {
+  public void setType(ChartType type) {
+    super.setType(type);
     switch( type ) {
       // supported types
       case LINE: stacked = false;
@@ -107,7 +123,7 @@
                  break;
       case AREA: break;
       // unsupported types
-      default: throw new IllegalArgumentException("Only ChartType.LINE, ChartType.AREA or ChartType.BAR allowed for BasicChartStyle!");
+      default: throwUnsupportedTypeException();
     }
     super.setType(type);
   }
@@ -147,7 +163,7 @@
 
   /**
    * Sets whether the chart is stepped. Sets the {@link #stepped} property
-   * to {@code true} for bar charts, even {@code aStepped} is {@code false}.
+   * to {@code true} for bar charts, even {@code stepped} is {@code false}.
    */
   public void setStepped(boolean stepped) {
     if ( type == ChartType.BAR && !stepped) {
@@ -163,11 +179,8 @@
   }
 
   /**
-   * Generates a chart using the given data and the style represented by this
-   * class.
-   *
+   * Creates a chart for the given {@link Dataset} and applies the style.
    * @param dataset the data for the chart
-   * @return JFreeChart
    * @exception UnsupportedOperationException if the style can not be applied
    *            to the given dataset
    */
@@ -180,10 +193,30 @@
                  break;
       case BAR:  chart = createBarChart(dataset);
                  break;
+      // unsupported types
+      default: throwUnsupportedTypeException();
     }
-    
+    applyToChart(chart);
     return chart;
-  }
+  }
+  
+  /**
+   * Applies the style to an existing chart.
+   * @param chart chart the style is applied to
+   * @exception UnsupportedOperationException if the style can not be applied
+   *            to the given dataset
+   */
+  public void applyToChart(JFreeChart chart) {
+    super.applyToChart(chart);
+    // apply the stacked and stepped property
+    if ( chart.getPlot() instanceof XYPlot )
+      chart.getXYPlot().setRenderer( JFreeChartUtil.createXYRenderer(this) );
+    else if ( chart.getPlot() instanceof CategoryPlot )
+      chart.getCategoryPlot().setRenderer( JFreeChartUtil.createCategoryRenderer(this) );
+    else
+      LOGGER.warn("Properties of BasicChartStyle can not be applied to plot: "+chart.getPlot());
+  }
+  
 
   /**
    * Creates a line chart from an {@link XYDataset} or {@link CategoryDataset}
@@ -203,8 +236,8 @@
           tooltips,
           urls
       );
-      if ( stepped )
-        chart.getXYPlot().setRenderer(  new XYStepRenderer() );
+//      if ( stepped )
+//        chart.getXYPlot().setRenderer( new XYStepRenderer() );
     }
     // CategoryDataset -> LineChart
     if (dataset instanceof CategoryDataset) {
@@ -218,8 +251,8 @@
           tooltips,
           urls
       );
-      if ( stepped )
-        chart.getCategoryPlot().setRenderer(  new CategoryStepRenderer() );
+//      if ( stepped )
+//        chart.getCategoryPlot().setRenderer(  new CategoryStepRenderer() );
     }
     return chart;
   }
@@ -242,17 +275,17 @@
           tooltips,
           urls
           );
-      if (stacked) {
-        if (dataset instanceof TableXYDataset)
-          chart.getXYPlot().setRenderer(new StackedXYAreaRenderer2());
-        else
-          throw new UnsupportedOperationException("Chart creation: Stacked area charts can not be applied on XYDataset. TableXYDataset needed!");
-        if (stepped)
-          throw new UnsupportedOperationException("Chart creation: A stacked area chart can not be stepped the same time. Use a stacked bar chart instead!");
-      } else  {
-        if (stepped)
-          chart.getXYPlot().setRenderer(new XYStepAreaRenderer(XYStepAreaRenderer.AREA));
-      }
+//      if (stacked) {
+//        if (dataset instanceof TableXYDataset)
+//          chart.getXYPlot().setRenderer(new StackedXYAreaRenderer2());
+//        else
+//          throw new UnsupportedOperationException("Chart creation: Stacked area charts can not be applied on XYDataset. TableXYDataset needed!");
+//        if (stepped)
+//          throw new UnsupportedOperationException("Chart creation: A stacked area chart can not be stepped the same time. Use a stacked bar chart instead!");
+//      } else  {
+//        if (stepped)
+//          chart.getXYPlot().setRenderer(new XYStepAreaRenderer(XYStepAreaRenderer.AREA));
+//      }
     }
     // CategoryDataset -> AreaChart
     if (dataset instanceof CategoryDataset) {
@@ -266,10 +299,10 @@
           tooltips,
           urls
       );
-      if ( stepped )
-        throw new UnsupportedOperationException("Chart creation: Stepped area style can not be applied on CategoryDataset. Use a bar chart instead!");
-      if ( stacked )
-        chart.getCategoryPlot().setRenderer(  new StackedAreaRenderer(false) );
+//      if ( stepped )
+//        throw new UnsupportedOperationException("Chart creation: Stepped area style can not be applied on CategoryDataset. Use a bar chart instead!");
+//      if ( stacked )
+//        chart.getCategoryPlot().setRenderer(  new StackedAreaRenderer(false) );
     }
 
     return chart;
@@ -294,12 +327,12 @@
           true,
           true
       );
-      if ( stacked ) {
-        if ( dataset instanceof TableXYDataset )
-          chart.getXYPlot().setRenderer(new StackedXYBarRenderer());
-        else
-          throw new UnsupportedOperationException("Chart creation: Stacked bar charts can not be applied on XYDataset. TableXYDataset needed!");
-      }
+//      if ( stacked ) {
+//        if ( dataset instanceof TableXYDataset )
+//          chart.getXYPlot().setRenderer(new StackedXYBarRenderer());
+//        else
+//          throw new UnsupportedOperationException("Chart creation: Stacked bar charts can not be applied on XYDataset. TableXYDataset needed!");
+//      }
     }
     // CategoryDataset -> BarChart
     if (dataset instanceof CategoryDataset) {
@@ -313,8 +346,8 @@
           tooltips,
           urls
       );
-      if ( stacked )
-        chart.getCategoryPlot().setRenderer(  new StackedBarRenderer(false) );
+//      if ( stacked )
+//        chart.getCategoryPlot().setRenderer(  new StackedBarRenderer(false) );
     }
 
     return chart;

Modified: trunk/src/schmitzm/jfree/chart/style/ChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/ChartStyleXMLFactory.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/chart/style/ChartStyleXMLFactory.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -29,14 +29,14 @@
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
-public class ChartStyleXMLFactory {
+public class ChartStyleXMLFactory<E extends ChartStyle> {
   /**
    * Reads a chart definition from XML element. The chart style ID
    * is taken from "id" attribute.
    * @param element the XML element
    * @param factory factory to create the style with
    */
-  public ChartStyle createStyleFromXML(Element element) {
+  public E createStyleFromXML(Element element) {
     return( createStyleFromXML(element,null) );
   }
 
@@ -46,7 +46,7 @@
    * @param id      the ID for the style (if {@code null} the
    *                ID is taken from "id" attribute)
    */
-  public ChartStyle createStyleFromXML(Element element, String id) {
+  public E createStyleFromXML(Element element, String id) {
     if ( id == null )
       id = XMLUtil.getAttribute(element, "id", String.valueOf(new Random().nextInt()));
     
@@ -54,8 +54,10 @@
     String               typeStr   = XMLUtil.getAttribute(element, "type");
     ChartStyle.ChartType chartType = ChartStyleUtil.getChartType(typeStr);
 
+    // create default style for given type
+    E chartStyle = createDefaultChartStyle(id, chartType);
     // apply the "rest" of the XML definition to style
-    ChartStyle chartStyle = createDefaultChartStyle(id, chartType);
+    applyStyleFromXML(chartStyle, element);
     
     return chartStyle;
   }
@@ -65,11 +67,11 @@
    * @param id   a (unique) ID for the style
    * @param type a chart type
    */
-  public ChartStyle createDefaultChartStyle(String id, ChartType type) {
+  public E createDefaultChartStyle(String id, ChartType type) {
     switch ( type ) {
       case AREA:  
       case LINE:  
-      case POINT: return new BasicChartStyle(id, type);
+      case POINT: return (E) new BasicChartStyle(id, type);
     }
     throw new UnsupportedOperationException("Style for this chart type not yet supported: "+type);
   }
@@ -79,8 +81,13 @@
    * to an existing {@link ChartStyle} object.
    * @param chartStyle an existing chart style ({@code null} not permitted!)
    * @param element    element to read the properties from
+   * @exception UnsupportedOperationException if {@code chartStyle} or {@code element}
+   *            is {@code null}
    */
-  public void applyStyleFromXML(ChartStyle chartStyle, Element element) {
+  public void applyStyleFromXML(E chartStyle, Element element) {
+    if ( chartStyle == null || element == null )
+      throw new UnsupportedOperationException("Chart style and element must be given to apply the chart style from XML!");
+    
     // Legend visible
     chartStyle.setLegend( XMLUtil.getBooleanAttribute(element,"legend",true) );
     chartStyle.setTooltips( XMLUtil.getBooleanAttribute(element,"tooltips",true) );
@@ -106,11 +113,11 @@
       throw new UnsupportedOperationException("Unknown orientation definition: "+orientationStr);
 
     // Title style
+    if ( element.getChild("title") != null );
+      chartStyle.setTitleStyle( createLabelStyleFromXML(element.getChild("title") ) );
+    // Description style
     if ( element.getChild("desc") != null );
       chartStyle.setDescStyle( createLabelStyleFromXML(element.getChild("desc") ) );
-    // Title style
-    if ( element.getChild("title") != null );
-      chartStyle.setTitleStyle( createLabelStyleFromXML(element.getChild("title") ) );
     // Domain axis
     if ( element.getChild("domainAxis") != null );
       chartStyle.setAxisStyle( ChartStyle.DOMAIN_AXIS,createAxisStyleFromXML(element.getChild("domainAxis") ) );
@@ -129,9 +136,31 @@
     // Plot
     if ( element.getChild("plot") != null );
       chartStyle.setPlotStyle( createPlotStyleFromXML(element.getChild("plot") ) );
+
+    // apply type specific properties
+    if ( chartStyle instanceof BasicChartStyle )
+      applyStyleFromXML((BasicChartStyle)chartStyle, element);
+      
   }
   
   /**
+   * Applies the {@link BasicChartStyle} properties from XML (<b>not the {@link ChartStyle}
+   * properties!)</b>) to an existing {@link BasicChartStyle} object.
+   * @param chartStyle an existing chart style ({@code null} not permitted!)
+   * @param element    element to read the properties from
+   */
+  private void applyStyleFromXML(BasicChartStyle chartStyle, Element element) {
+    // stepped property
+    Boolean stepped = XMLUtil.getBooleanAttribute(element, "stepped");
+    if ( stepped != null )
+      chartStyle.setStepped(stepped);
+    // stacked property
+    Boolean stacked = XMLUtil.getBooleanAttribute(element, "stacked");
+    if ( stacked != null )
+      chartStyle.setStacked(stacked);
+  }
+  
+  /**
    * Reads the {@link ChartLabelStyle} properties from an XML element.
    * <ul>
    *   <li>Attribute "paint": color of the label</li>
@@ -189,7 +218,7 @@
     // values format and angle from child element <valueLabels>
     Element valuesElem = element.getChild("valueLabels");
     if ( valuesElem != null ) {
-      Double valuesAngle = XMLUtil.getDoubleAttribute(valuesElem, "angle");
+      Double valuesAngle = XMLUtil.getDoubleAttribute(valuesElem, "valuesAngle");
       if ( valuesAngle != null )
         style.setValuesAngle( valuesAngle );
       String formatStr = XMLUtil.getAttribute(valuesElem, "numberFormat");

Added: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -0,0 +1,99 @@
+/** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package schmitzm.jfree.feature.style;
+
+import org.geotools.feature.FeatureCollection;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.general.Dataset;
+
+import schmitzm.jfree.chart.style.BasicChartStyle;
+
+/**
+ * This class extends the {@link BasicChartStyle} with the properties
+ * of the {@link FeatureChartStyle}.<br>
+ * After instantiation the 2 feature attributes used to define the chart
+ * data must be set by {@link #setAttributeName(int, String)}. Without
+ * setting the attributes the style can not be applied to a feature collection!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class FeatureBasicChartStyle extends BasicChartStyle implements FeatureChartStyle {
+  /** Used to maintain the {@link FeatureChartStyle} properties. */
+  protected Dummy dummyFeatureChartStyle = null;
+  
+  /**
+   * Creates a normal line style with default values.
+   * @param id a (unique) ID for the style
+   */
+  public FeatureBasicChartStyle(String id) {
+    this(id, ChartType.LINE);
+  }
+
+  /**
+   * Creates a normal, vertical line, bar or area style.
+   * @param id   a (unique) ID for the style
+   * @param type type of the chart layout
+   */
+  public FeatureBasicChartStyle(String id, ChartType type) {
+    super(id, type);
+    dummyFeatureChartStyle = new Dummy(id, 2);
+  }
+
+  /**
+   * Returns the attribute count needed to specify the chart data
+   * from feature collection.
+   * @return always 2
+   */
+  @Override
+  public int getAttributeCount() {
+    return dummyFeatureChartStyle.getAttributeCount();
+  }
+
+  /**
+   * Returns the name of a feature attribute needed to create a
+   * chart for this style.
+   * @param idx axis index
+   * @see ChartStyle#DOMAIN_AXIS
+   * @see ChartStyle#RANGE_AXIS
+   * @see ChartStyle#RANGE_AXIS2
+   */
+  public String getAttributeName(int idx) {
+    return dummyFeatureChartStyle.getAttributeName(idx);
+  }
+
+  /**
+   * Sets the name of a feature attribute needed to create a
+   * chart for this style.
+   * @param idx axis index
+   * @param attrName feature attribute name 
+   * @see ChartStyle#DOMAIN_AXIS
+   * @see ChartStyle#RANGE_AXIS
+   * @see ChartStyle#RANGE_AXIS2
+   */
+  public void setAttributeName(int idx, String attrName) {
+    dummyFeatureChartStyle.setAttributeName(idx,attrName);
+  }
+
+  /**
+   * 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)}.
+   * @see schmitzm.jfree.feature.style.FeatureChartStyle#applyToFeatureCollection(org.geotools.feature.FeatureCollection)
+   */
+  @Override
+  public JFreeChart applyToFeatureCollection(FeatureCollection fc) {
+    Dataset dataset = null; // TODO: Create dataset from FeatureCollection by utility method
+    return applyToDataset(dataset);
+  }
+
+
+}

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -11,9 +11,20 @@
 
 package schmitzm.jfree.feature.style;
 
+import java.awt.Paint;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.geotools.feature.FeatureCollection;
 import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.general.Dataset;
 
+import schmitzm.jfree.chart.style.AbstractChartStyle;
+import schmitzm.jfree.chart.style.ChartAxisStyle;
+import schmitzm.jfree.chart.style.ChartLabelStyle;
+import schmitzm.jfree.chart.style.ChartPlotStyle;
+import schmitzm.jfree.chart.style.ChartRendererStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
 
 /**
@@ -24,9 +35,15 @@
  */
 public interface FeatureChartStyle extends ChartStyle {
   /**
+   * Returns the number of feature attributes needed to create a
+   * chart for this style.
+   */
+  public int getAttributeCount();
+
+  /**
    * Returns the name of a feature attribute needed to create a
    * chart for this style.
-   * @param idx axis index (
+   * @param idx axis index
    * @see ChartStyle#DOMAIN_AXIS
    * @see ChartStyle#RANGE_AXIS
    * @see ChartStyle#RANGE_AXIS2
@@ -34,11 +51,16 @@
   public String getAttributeName(int idx);
   
   /**
-   * Returns the number of feature attributes needed to create a
+   * Sets the name of a feature attribute needed to create a
    * chart for this style.
+   * @param idx axis index
+   * @param attrName feature attribute name 
+   * @see ChartStyle#DOMAIN_AXIS
+   * @see ChartStyle#RANGE_AXIS
+   * @see ChartStyle#RANGE_AXIS2
    */
-  public int getAttributeCount();
-  
+  public void setAttributeName(int idx, String attrName);
+
   /**
    * Creates a chart according to the given 
    * @param fc  a feature collection
@@ -47,4 +69,87 @@
    *            does not provide the required attributes)
    */
   public JFreeChart applyToFeatureCollection(FeatureCollection fc);
+
+  
+  /**
+   * This class defines a dummy implementation of {@link FeatureChartStyle} just
+   * to maintain the properties of the interface {@link FeatureChartStyle}, so
+   * sub classes of {@link FeatureChartStyle} which usually are derived from
+   * a normal {@link ChartStyle} implementation must not implement the
+   * {@link FeatureChartStyle} maintenance each. Instead they can create an
+   * instance of this dummy an pipe their method implementations to the
+   * dummy!<br>
+   * <br>
+   * The {@link #applyToFeatureCollection(FeatureCollection)} and 
+   * {@link #applyToDataset(Dataset)} methods are not implemented by the dummy,
+   * but throw an exception instead!! 
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+   */
+  public static class Dummy extends AbstractChartStyle implements FeatureChartStyle {
+    /** Holds the attributes needed to specify the chart data
+     *  from feature collection. */
+    protected List<String> attrNames = null;
+    
+    /**
+     * Creates a new dummy. This constructor is protected so that only derived
+     * classes can instantiate a dummy!
+     * @param id        a (unique) ID for the style
+     * @param attrCount attribute count needed to specify the chart data
+     *                  from feature collection
+     */
+    protected Dummy(String id, int attrCount) {
+      super(id);
+      this.attrNames = new ArrayList<String>(attrCount);
+    }
+    
+    /**
+     * Returns the attribute count needed to specify the chart data
+     * from feature collection.
+     */
+    public int getAttributeCount() {
+      return attrNames.size();
+    }
+
+    /**
+     * Returns the name of a feature attribute needed to create a
+     * chart for this style.
+     * @param idx axis index
+     * @see ChartStyle#DOMAIN_AXIS
+     * @see ChartStyle#RANGE_AXIS
+     * @see ChartStyle#RANGE_AXIS2
+     */
+    public String getAttributeName(int idx) {
+      return attrNames.get(idx);
+    }
+
+    /**
+     * Sets the name of a feature attribute needed to create a
+     * chart for this style.
+     * @param idx axis index
+     * @param attrName feature attribute name 
+     * @see ChartStyle#DOMAIN_AXIS
+     * @see ChartStyle#RANGE_AXIS
+     * @see ChartStyle#RANGE_AXIS2
+     */
+    public void setAttributeName(int idx, String attrName) {
+      attrNames.set(idx, attrName);
+    }
+
+    /**
+     * Does nothing, but always throws a {@link UnsupportedOperationException},
+     * because the dummy can not provide this functionality.
+     */
+    public JFreeChart applyToDataset(Dataset dataset) {
+      throw new UnsupportedOperationException("FeatureChartStyle.Dummy does not implement applyToDataset(..)");
+    }
+
+    /**
+     * Does nothing, but always throws a {@link UnsupportedOperationException},
+     * because the dummy can not provide this functionality.
+     */
+    public JFreeChart applyToFeatureCollection(FeatureCollection fc) {
+      throw new UnsupportedOperationException("FeatureChartStyle.Dummy does not implement applyToFeatureCollection(..)");
+    }
+
+}
 }

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2009-07-12 09:32:24 UTC (rev 210)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2009-07-12 12:17:01 UTC (rev 211)
@@ -11,11 +11,16 @@
 
 package schmitzm.jfree.feature.style;
 
+import java.util.List;
+
 import org.geotools.feature.FeatureCollection;
 import org.jdom.Element;
 
+import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
 import schmitzm.jfree.chart.style.ChartStyle.ChartType;
+import schmitzm.lang.LangUtil;
+import schmitzm.xml.XMLUtil;
 
 /**
  * This class defines a factory to create a chart style from XML
@@ -23,32 +28,50 @@
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
-public class FeatureChartStyleXMLFactory extends ChartStyleXMLFactory {
-  /**
-   * Reads a chart definition from XML element. The chart style ID
-   * is taken from "id" attribute.
-   * @param element the XML element
-   * @param factory factory to create the style with
-   */
-  @Override
-  public FeatureChartStyle createStyleFromXML(Element element) {
-    return( createStyleFromXML(element,null) );
-  }
+public class FeatureChartStyleXMLFactory extends ChartStyleXMLFactory<FeatureChartStyle> {
 
   /**
-   * Reads a chart definition from XML element.
-   * @param element the XML element
-   * @param id      the ID for the style (if {@code null} the
-   *                ID is taken from "id" attribute)
+   * Applies the chart style definition from XML (<b>except the type and id!!</b>)
+   * to an existing {@link ChartStyle} object.
+   * @param chartStyle an existing chart style ({@code null} not permitted!)
+   * @param element    element to read the properties from
    */
   @Override
-  public FeatureChartStyle createStyleFromXML(Element element, String id) {
-    // apply the "rest" of the XML definition to style
-    FeatureChartStyle chartStyle = (FeatureChartStyle)super.createStyleFromXML(element, id);
+  public void applyStyleFromXML(FeatureChartStyle chartStyle, Element element) {
+    // Apply the normal style properties
+    super.applyStyleFromXML(chartStyle, element);
     
-    // TODO: Apply the feature properties to style!
+    // Attribute definitions in <attributes> element
+    Element featureElement = element.getChild("featureAttributes");
+    if ( featureElement == null )
+      throw new UnsupportedOperationException("<featureAttributes> element necessary for FeatureChartStyle!");
+
+    // Read all feature attribute definitions below <featureAttributes>
+    for (Element featureAttrElem : (List<Element>)featureElement.getChildren() ) {
+      String elementName     = featureAttrElem.getName();
+      String featureAttrName = XMLUtil.getAttribute(featureAttrElem, "name");
+      if ( featureAttrName == null )
+        throw new UnsupportedOperationException("Attribute 'name' necessary for <"+featureAttrElem+"> element of FeatureChartStyle!");
+      // Apply feature attribute name to style
+      try {
+        if ( "domainAttr".equals(elementName) )
+          chartStyle.setAttributeName(ChartStyle.DOMAIN_AXIS, featureAttrName);
+        else if ( "rangeAttr".equals(elementName) )
+          chartStyle.setAttributeName(ChartStyle.RANGE_AXIS, featureAttrName);
+        else if ( "rangeAttr2".equals(elementName) )
+          chartStyle.setAttributeName(ChartStyle.RANGE_AXIS2, featureAttrName);
+      } catch (ArrayIndexOutOfBoundsException err) {
+        throw new UnsupportedOperationException("<"+elementName+"> not applicable for "+LangUtil.getSimpleClassName(chartStyle));
+      }
+    }
     
-    return chartStyle;
+    // Check whether all needed feature attributes are specified
+    int attrCount = chartStyle.getAttributeCount();
+    for (int i=0; i<attrCount; i++) {
+      String attrName = chartStyle.getAttributeName(i);
+      if ( attrName == null || "".equals(attrName) )
+        throw new UnsupportedOperationException("<featureAttributes> requires "+attrCount+" feature attribute definition for "+LangUtil.getSimpleClassName(chartStyle));
+    }
   }
 
   /**
@@ -58,12 +81,12 @@
    */
   @Override
   public FeatureChartStyle createDefaultChartStyle(String id, ChartType type) {
-    // TODO: Create special FeatureChartStyles
-//    switch ( type ) {
-//      case AREA:  
-//      case LINE:  
-//      case POINT: return new BasicChartStyle(id, type);
-//    }
+    // Create special FeatureChartStyles
+    switch ( type ) {
+      case AREA:  
+      case LINE:  
+      case POINT: return new FeatureBasicChartStyle(id, type);
+    }
     throw new UnsupportedOperationException("Style for this chart type not yet supported for features: "+type);
   }
 }



More information about the Schmitzm-commits mailing list