changeset 2074:a026d005accd

Moved JFreeChart specific classes to de.intevation.flys.jfree and added required imports. flys-artifacts/trunk@3585 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 04 Jan 2012 14:43:48 +0000 (2012-01-04)
parents 27ada2e4243d
children f42b0e624e97
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/EnhancedLineAndShapeRenderer.java flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/StyledAreaSeriesCollection.java flys-artifacts/src/main/java/de/intevation/flys/exports/StyledXYSeries.java flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledAreaSeriesCollection.java flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledXYSeries.java
diffstat 14 files changed, 560 insertions(+), 529 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/ChangeLog	Wed Jan 04 14:43:48 2012 +0000
@@ -1,3 +1,24 @@
+2012-01-04  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/exports/StyledXYSeries.java,
+	  src/main/java/de/intevation/flys/exports/StyledAreaSeriesCollection.java,
+	  src/main/java/de/intevation/flys/exports/EnhancedLineAndShapeRenderer.java:
+	  Moved to de.intevation.flys.jfree.
+
+	* src/main/java/de/intevation/flys/jfree/StyledXYSeries.java,
+	  src/main/java/de/intevation/flys/jfree/StyledAreaSeriesCollection.java,
+	  src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java:
+	  Moved from de.intevation.flys.exports.
+
+	* src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java,
+	  src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java,
+	  src/main/java/de/intevation/flys/exports/XYChartGenerator.java,
+	  src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java,
+	  src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java:
+	  Added necessary imports.
+
 2012-01-04  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/exports/EnhancedLineAndShapeRenderer.java:
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -21,6 +21,7 @@
 
 import de.intevation.flys.jfree.FLYSAnnotation;
 import de.intevation.flys.jfree.StickyAxisAnnotation;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 
 /**
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -10,15 +10,16 @@
 
 import org.w3c.dom.Document;
 
+import de.intevation.artifacts.DataProvider;
+
 import de.intevation.artifactdatabase.state.ArtifactAndFacet;
 
-
 import de.intevation.flys.model.CrossSectionLine;
 
 import de.intevation.flys.artifacts.model.FacetTypes;
 import de.intevation.flys.artifacts.model.CrossSectionFacet;
-
-import de.intevation.artifacts.DataProvider;
+import de.intevation.flys.jfree.StyledAreaSeriesCollection;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 /**
  * An OutGenerator that generates cross section graphs.
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -25,6 +25,7 @@
 
 import de.intevation.flys.utils.FLYSUtils;
 import de.intevation.flys.jfree.FLYSAnnotation;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 /**
  * An OutGenerator that generates discharge curves.
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -14,6 +14,7 @@
 import de.intevation.flys.artifacts.model.WKms;
 
 import de.intevation.flys.jfree.FLYSAnnotation;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 
 /**
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -21,6 +21,7 @@
 import de.intevation.flys.artifacts.resources.Resources;
 
 import de.intevation.flys.jfree.FLYSAnnotation;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 
 /**
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/EnhancedLineAndShapeRenderer.java	Wed Jan 04 14:25:10 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-package de.intevation.flys.exports;
-
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Rectangle2D;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-
-import org.jfree.chart.axis.ValueAxis;
-import org.jfree.chart.entity.EntityCollection;
-import org.jfree.chart.plot.CrosshairState;
-import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.data.xy.XYDataset;
-import org.jfree.ui.RectangleEdge;
-import org.jfree.util.BooleanList;
-import org.jfree.util.ShapeUtilities;
-
-
-public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer {
-
-    private static final Logger logger =
-        Logger.getLogger(EnhancedLineAndShapeRenderer.class);
-
-    protected BooleanList isMinimumShapeVisible;
-    protected BooleanList isMaximumShapeVisible;
-
-    protected Map<Integer, Double> seriesMinimum;
-    protected Map<Integer, Double> seriesMaximum;
-
-
-    public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) {
-        super(lines, shapes);
-        this.isMinimumShapeVisible = new BooleanList();
-        this.isMaximumShapeVisible = new BooleanList();
-        this.seriesMinimum         = new HashMap<Integer, Double>();
-        this.seriesMaximum         = new HashMap<Integer, Double>();
-    }
-
-
-    public boolean getItemShapeVisible(XYDataset dataset, int series, int item){
-        if (super.getItemShapeVisible(series, item)) {
-            return true;
-        }
-
-        if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) {
-            return true;
-        }
-
-        if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) {
-            return true;
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted
-     * method getItemShapeVisible() which now takes an XYDataset. So, 99% of
-     * code equal the code in XYLineAndShapeRenderer.
-     */
-    @Override
-    protected void drawSecondaryPass(
-        Graphics2D       g2,
-        XYPlot           plot,
-        XYDataset        dataset,
-        int              pass,
-        int              series,
-        int              item,
-        ValueAxis        domainAxis,
-        Rectangle2D      dataArea,
-        ValueAxis        rangeAxis,
-        CrosshairState   crosshairState,
-        EntityCollection entities
-    ) {
-        Shape entityArea = null;
-
-        // get the data point...
-        double x1 = dataset.getXValue(series, item);
-        double y1 = dataset.getYValue(series, item);
-        if (Double.isNaN(y1) || Double.isNaN(x1)) {
-            return;
-        }
-
-        PlotOrientation orientation = plot.getOrientation();
-        RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
-        RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
-        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
-        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
-
-        if (getItemShapeVisible(dataset, series, item)) {
-            Shape shape = getItemShape(series, item);
-            if (orientation == PlotOrientation.HORIZONTAL) {
-                shape = ShapeUtilities.createTranslatedShape(shape, transY1,
-                        transX1);
-            }
-            else if (orientation == PlotOrientation.VERTICAL) {
-                shape = ShapeUtilities.createTranslatedShape(shape, transX1,
-                        transY1);
-            }
-            entityArea = shape;
-            if (shape.intersects(dataArea)) {
-                if (getItemShapeFilled(series, item)) {
-                    if (getUseFillPaint()) {
-                        g2.setPaint(getItemFillPaint(series, item));
-                    }
-                    else {
-                        g2.setPaint(getItemPaint(series, item));
-                    }
-                    g2.fill(shape);
-                }
-                if (getDrawOutlines()) {
-                    if (getUseOutlinePaint()) {
-                        g2.setPaint(getItemOutlinePaint(series, item));
-                    }
-                    else {
-                        g2.setPaint(getItemPaint(series, item));
-                    }
-                    g2.setStroke(getItemOutlineStroke(series, item));
-                    g2.draw(shape);
-                }
-            }
-        }
-
-        double xx = transX1;
-        double yy = transY1;
-        if (orientation == PlotOrientation.HORIZONTAL) {
-            xx = transY1;
-            yy = transX1;
-        }
-
-        // draw the item label if there is one...
-        if (isItemLabelVisible(series, item)) {
-            drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
-                    (y1 < 0.0));
-        }
-
-        int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
-        int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
-        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex,
-                rangeAxisIndex, transX1, transY1, orientation);
-
-        // add an entity for the item, but only if it falls within the data
-        // area...
-        if (entities != null && isPointInRect(dataArea, xx, yy)) {
-            addEntity(entities, entityArea, dataset, series, item, xx, yy);
-        }
-    }
-
-
-    public void setIsMinimumShapeVisisble(int series, boolean isVisible) {
-        this.isMinimumShapeVisible.setBoolean(series, isVisible);
-    }
-
-
-    public boolean isMinimumShapeVisible(int series) {
-        return isMinimumShapeVisible.getBoolean(series);
-    }
-
-
-    public void setIsMaximumShapeVisible(int series, boolean isVisible) {
-        this.isMaximumShapeVisible.setBoolean(series, isVisible);
-    }
-
-
-    public boolean isMaximumShapeVisible(int series) {
-        return isMaximumShapeVisible.getBoolean(series);
-    }
-
-
-    public boolean isMinimum(XYDataset dataset, int series, int item) {
-        return dataset.getYValue(series, item) == getMinimum(dataset, series);
-    }
-
-
-    public double getMinimum(XYDataset dataset, int series) {
-        Integer key = Integer.valueOf(series);
-        Double  old = seriesMinimum.get(Integer.valueOf(series));
-
-        if (old != null) {
-            return old.doubleValue();
-        }
-
-        logger.debug("Compute minimum of Series: " + series);
-
-        double min = Double.MAX_VALUE;
-
-        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
-            double tmpValue = dataset.getYValue(series, i);
-
-            if (tmpValue < min) {
-                min = tmpValue;
-            }
-        }
-
-        seriesMinimum.put(key, Double.valueOf(min));
-
-        return min;
-    }
-
-
-    public boolean isMaximum(XYDataset dataset, int series, int item) {
-        return dataset.getYValue(series, item) == getMaximum(dataset, series);
-    }
-
-
-    public double getMaximum(XYDataset dataset, int series) {
-        Integer key = Integer.valueOf(series);
-        Double  old = seriesMaximum.get(Integer.valueOf(series));
-
-        if (old != null) {
-            return old.doubleValue();
-        }
-
-        logger.debug("Compute maximum of Series: " + series);
-
-        double max = -Double.MAX_VALUE;
-
-        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
-            double tmpValue = dataset.getYValue(series, i);
-
-            if (tmpValue > max) {
-                max = tmpValue;
-            }
-        }
-
-        seriesMaximum.put(key, Double.valueOf(max));
-
-        return max;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -22,6 +22,8 @@
 import de.intevation.flys.artifacts.model.WQKms;
 
 import de.intevation.flys.jfree.FLYSAnnotation;
+import de.intevation.flys.jfree.StyledAreaSeriesCollection;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 import de.intevation.flys.utils.FLYSUtils;
 import de.intevation.flys.utils.DataUtil;
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/StyledAreaSeriesCollection.java	Wed Jan 04 14:25:10 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-package de.intevation.flys.exports;
-
-import java.awt.Color;
-import java.awt.Stroke;
-import java.awt.BasicStroke;
-
-import org.apache.log4j.Logger;
-
-import org.w3c.dom.Document;
-
-import org.jfree.data.xy.XYSeriesCollection;
-
-import de.intevation.flys.utils.ThemeUtil;
-import de.intevation.flys.jfree.StableXYDifferenceRenderer;
-
-
-/**
- * One or more dataseries to draw a polygon (either "open up/downwards", or
- * the area between two curves), a theme-document and further display options.
- * The theme-document will later "style" the graphical representation.
- * The display options can be used to control the z-order and the axis of the 
- * dataset.
- */
-public class StyledAreaSeriesCollection extends XYSeriesCollection {
-    /** Mode, how to draw/which areas to fill. */
-    public enum FILL_MODE {UNDER, ABOVE, BETWEEN};
-
-    /** MODE in use. */
-    protected FILL_MODE mode;
-
-    /** The theme-document with attributes about actual visual representation. */
-    protected Document theme;
-
-    /** Own logger. */
-    private static final Logger logger =
-        Logger.getLogger(StyledAreaSeriesCollection.class);
-
-
-    /**
-     * @param theme the theme-document.
-     */
-    public StyledAreaSeriesCollection(Document theme) {
-        this.theme = theme;
-        this.mode = FILL_MODE.BETWEEN;
-   }
-
-
-    /** Gets the Fill mode. */
-    public FILL_MODE getMode() {
-        return this.mode;
-    }
-
-
-    /** Sets the Fill mode. */
-    public void setMode(FILL_MODE fMode) {
-        this.mode = fMode;
-    }
-
-
-    /**
-     * Applies line color, size and type attributes to renderer, also
-     * whether to draw lines and/or points.
-     */
-    public StableXYDifferenceRenderer applyTheme(
-        StableXYDifferenceRenderer renderer
-    ) {
-        applyFillColor(renderer);
-        applyShowShape(renderer);
-        applyOutlineColor(renderer);
-        applyOutlineStyle(renderer);
-
-        return renderer;
-    }
-
-
-    /**
-     * Blindly (for now) apply the postiviepaint of renderer.
-     */
-    protected void applyFillColor(StableXYDifferenceRenderer renderer) {
-        // Get color.
-        Color paint = ThemeUtil.parseFillColorField(theme);
-        // Get half-transparency flag.
-        if (ThemeUtil.parseTransparency(theme)) {
-            paint = new Color(paint.getRed(), paint.getGreen(), paint.getBlue(),
-                128);
-        }
-        if (paint != null && this.getMode() == FILL_MODE.ABOVE) {
-            renderer.setPositivePaint(paint);
-            renderer.setNegativePaint(new Color(0,0,0,0));
-        }
-        else if (paint != null && this.getMode() == FILL_MODE.UNDER) {
-            renderer.setNegativePaint(paint);
-            renderer.setPositivePaint(new Color(0,0,0,0));
-        }
-        else {
-            if (paint == null) paint = new Color(177, 117, 102);
-            renderer.setPositivePaint(paint);
-            renderer.setNegativePaint(paint);
-        }
-    }
-
-    /**
-     * Blindly (for now) apply the postiviepaint of renderer.
-     */
-    protected void applyShowShape(StableXYDifferenceRenderer renderer) {
-        boolean show = ThemeUtil.parseShowBorder(theme);
-        renderer.setDrawOutline(show);
-    }
-
-    protected void applyShowLine(StableXYDifferenceRenderer renderer) {
-        boolean show = ThemeUtil.parseShowLine(theme);
-        renderer.setShapesVisible(show);
-    }
-
-    /**
-     *
-     */
-    protected void applyOutlineColor(StableXYDifferenceRenderer renderer) {
-        Color c = ThemeUtil.parseLineColorField(theme);
-        renderer.setOutlinePaint(c);
-    }
-
-    protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) {
-        int size = ThemeUtil.parseLineWidth(theme);
-    }
-
-    protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) {
-        float[] dashes = ThemeUtil.parseLineStyle(theme);
-        int size       = ThemeUtil.parseLineWidth(theme);
-
-        Stroke stroke = null;
-
-        if (dashes.length <= 1) {
-            stroke = new BasicStroke(Integer.valueOf(size));
-        }
-        else {
-            stroke = new BasicStroke(Integer.valueOf(size),
-                BasicStroke.CAP_BUTT,
-                BasicStroke.JOIN_ROUND,
-                1.0f,
-                dashes,
-                0.0f);
-        }
-
-        renderer.setOutlineStroke(stroke);
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/StyledXYSeries.java	Wed Jan 04 14:25:10 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-package de.intevation.flys.exports;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.geom.Ellipse2D;
-
-import org.apache.log4j.Logger;
-
-import org.w3c.dom.Document;
-
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.data.xy.XYSeries;
-
-import de.intevation.flys.utils.ThemeUtil;
-
-/**
- * Dataseries in two dimensions with additional theme-document and further
- * display options.
- * The theme-document will later "style" the graphical representation.
- * The display options can be used to control the z-order and the axis of the 
- * dataseries.
- */
-public class StyledXYSeries extends XYSeries {
-
-    protected Document theme;
-
-    private static final Logger logger = Logger.getLogger(StyledXYSeries.class);
-
-
-    public StyledXYSeries(String key, Document theme) {
-        this(key, true, theme);
-    }
-
-
-    /**
-     * @param sorted whether or not to sort the points. Sorting will move NANs
-     *               to one extrema which can cause problems in certain
-     *               algorithms.
-     */
-    public StyledXYSeries(String key, boolean sorted, Document theme) {
-        super(key, sorted);
-        this.theme = theme;
-    }
-
-
-    /**
-     * Applies line color, size and type attributes to renderer, also
-     * whether to draw lines and/or points.
-     */
-    public XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx){
-        applyLineColor(r, idx);
-        applyLineSize(r, idx);
-        applyLineType(r, idx);
-        applyShowLine(r, idx);
-        applyShowPoints(r, idx);
-        applyShowMinimum(r, idx);
-        applyShowMaximum(r, idx);
-
-        return r;
-    }
-
-
-    /** Set line color to renderer. */
-    protected void applyLineColor(XYLineAndShapeRenderer r, int idx) {
-        Color c = ThemeUtil.parseLineColorField(theme);
-        r.setSeriesPaint(idx, c);
-    }
-
-
-    protected void applyLineSize(XYLineAndShapeRenderer r, int idx) {
-        int size = ThemeUtil.parseLineWidth(theme);
-        r.setSeriesStroke(
-            idx,
-            new BasicStroke(Integer.valueOf(size)));
-    }
-
-
-    protected void applyLineType(XYLineAndShapeRenderer r, int idx) {
-        int size = ThemeUtil.parseLineWidth(theme);
-        float[] dashes = ThemeUtil.parseLineStyle(theme);
-
-        // Do not apply the dashed style.
-        if (dashes.length <= 1) {
-            return;
-        }
-
-        r.setSeriesStroke(
-            idx,
-            new BasicStroke(Integer.valueOf(size),
-                            BasicStroke.CAP_BUTT,
-                            BasicStroke.JOIN_ROUND,
-                            1.0f,
-                            dashes,
-                            0.0f));
-    }
-
-
-    /**
-     * Sets form and visibility of points.
-     */
-    protected void applyShowPoints(XYLineAndShapeRenderer r, int idx) {
-        boolean show = ThemeUtil.parseShowPoints(theme);
-        int size = ThemeUtil.parseLineWidth(theme);
-        r.setSeriesShape(idx, new Ellipse2D.Double(- size,
-                                                   - size,
-                                                   2 * size,
-                                                   2 * size));
-        r.setSeriesShapesVisible(idx, show);
-        r.setDrawOutlines(true);
-    }
-
-
-    protected void applyShowLine(XYLineAndShapeRenderer r, int idx) {
-        boolean show = ThemeUtil.parseShowLine(theme);
-        r.setSeriesLinesVisible(idx, show);
-    }
-
-
-    protected void applyShowMinimum(XYLineAndShapeRenderer r, int idx) {
-        if (!(r instanceof EnhancedLineAndShapeRenderer)) {
-            return;
-        }
-
-        boolean visible = ThemeUtil.parseShowMinimum(theme);
-
-        EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r;
-        er.setIsMinimumShapeVisisble(idx, visible);
-    }
-
-
-    protected void applyShowMaximum(XYLineAndShapeRenderer r, int idx) {
-        if (!(r instanceof EnhancedLineAndShapeRenderer)) {
-            return;
-        }
-
-        boolean visible = ThemeUtil.parseShowMaximum(theme);
-
-        EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r;
-        er.setIsMaximumShapeVisible(idx, visible);
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Wed Jan 04 14:25:10 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Wed Jan 04 14:43:48 2012 +0000
@@ -52,9 +52,12 @@
 
 
 import de.intevation.flys.exports.ChartExportHelper;
+import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer;
 import de.intevation.flys.jfree.FLYSAnnotation;
 import de.intevation.flys.jfree.StableXYDifferenceRenderer;
 import de.intevation.flys.jfree.StickyAxisAnnotation;
+import de.intevation.flys.jfree.StyledAreaSeriesCollection;
+import de.intevation.flys.jfree.StyledXYSeries;
 
 import de.intevation.flys.utils.ThemeAccess;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java	Wed Jan 04 14:43:48 2012 +0000
@@ -0,0 +1,236 @@
+package de.intevation.flys.jfree;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.entity.EntityCollection;
+import org.jfree.chart.plot.CrosshairState;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYDataset;
+import org.jfree.ui.RectangleEdge;
+import org.jfree.util.BooleanList;
+import org.jfree.util.ShapeUtilities;
+
+
+public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer {
+
+    private static final Logger logger =
+        Logger.getLogger(EnhancedLineAndShapeRenderer.class);
+
+    protected BooleanList isMinimumShapeVisible;
+    protected BooleanList isMaximumShapeVisible;
+
+    protected Map<Integer, Double> seriesMinimum;
+    protected Map<Integer, Double> seriesMaximum;
+
+
+    public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) {
+        super(lines, shapes);
+        this.isMinimumShapeVisible = new BooleanList();
+        this.isMaximumShapeVisible = new BooleanList();
+        this.seriesMinimum         = new HashMap<Integer, Double>();
+        this.seriesMaximum         = new HashMap<Integer, Double>();
+    }
+
+
+    public boolean getItemShapeVisible(XYDataset dataset, int series, int item){
+        if (super.getItemShapeVisible(series, item)) {
+            return true;
+        }
+
+        if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) {
+            return true;
+        }
+
+        if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) {
+            return true;
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted
+     * method getItemShapeVisible() which now takes an XYDataset. So, 99% of
+     * code equal the code in XYLineAndShapeRenderer.
+     */
+    @Override
+    protected void drawSecondaryPass(
+        Graphics2D       g2,
+        XYPlot           plot,
+        XYDataset        dataset,
+        int              pass,
+        int              series,
+        int              item,
+        ValueAxis        domainAxis,
+        Rectangle2D      dataArea,
+        ValueAxis        rangeAxis,
+        CrosshairState   crosshairState,
+        EntityCollection entities
+    ) {
+        Shape entityArea = null;
+
+        // get the data point...
+        double x1 = dataset.getXValue(series, item);
+        double y1 = dataset.getYValue(series, item);
+        if (Double.isNaN(y1) || Double.isNaN(x1)) {
+            return;
+        }
+
+        PlotOrientation orientation = plot.getOrientation();
+        RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
+        RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
+        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
+        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
+
+        if (getItemShapeVisible(dataset, series, item)) {
+            Shape shape = getItemShape(series, item);
+            if (orientation == PlotOrientation.HORIZONTAL) {
+                shape = ShapeUtilities.createTranslatedShape(shape, transY1,
+                        transX1);
+            }
+            else if (orientation == PlotOrientation.VERTICAL) {
+                shape = ShapeUtilities.createTranslatedShape(shape, transX1,
+                        transY1);
+            }
+            entityArea = shape;
+            if (shape.intersects(dataArea)) {
+                if (getItemShapeFilled(series, item)) {
+                    if (getUseFillPaint()) {
+                        g2.setPaint(getItemFillPaint(series, item));
+                    }
+                    else {
+                        g2.setPaint(getItemPaint(series, item));
+                    }
+                    g2.fill(shape);
+                }
+                if (getDrawOutlines()) {
+                    if (getUseOutlinePaint()) {
+                        g2.setPaint(getItemOutlinePaint(series, item));
+                    }
+                    else {
+                        g2.setPaint(getItemPaint(series, item));
+                    }
+                    g2.setStroke(getItemOutlineStroke(series, item));
+                    g2.draw(shape);
+                }
+            }
+        }
+
+        double xx = transX1;
+        double yy = transY1;
+        if (orientation == PlotOrientation.HORIZONTAL) {
+            xx = transY1;
+            yy = transX1;
+        }
+
+        // draw the item label if there is one...
+        if (isItemLabelVisible(series, item)) {
+            drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
+                    (y1 < 0.0));
+        }
+
+        int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
+        int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
+        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex,
+                rangeAxisIndex, transX1, transY1, orientation);
+
+        // add an entity for the item, but only if it falls within the data
+        // area...
+        if (entities != null && isPointInRect(dataArea, xx, yy)) {
+            addEntity(entities, entityArea, dataset, series, item, xx, yy);
+        }
+    }
+
+
+    public void setIsMinimumShapeVisisble(int series, boolean isVisible) {
+        this.isMinimumShapeVisible.setBoolean(series, isVisible);
+    }
+
+
+    public boolean isMinimumShapeVisible(int series) {
+        return isMinimumShapeVisible.getBoolean(series);
+    }
+
+
+    public void setIsMaximumShapeVisible(int series, boolean isVisible) {
+        this.isMaximumShapeVisible.setBoolean(series, isVisible);
+    }
+
+
+    public boolean isMaximumShapeVisible(int series) {
+        return isMaximumShapeVisible.getBoolean(series);
+    }
+
+
+    public boolean isMinimum(XYDataset dataset, int series, int item) {
+        return dataset.getYValue(series, item) == getMinimum(dataset, series);
+    }
+
+
+    public double getMinimum(XYDataset dataset, int series) {
+        Integer key = Integer.valueOf(series);
+        Double  old = seriesMinimum.get(Integer.valueOf(series));
+
+        if (old != null) {
+            return old.doubleValue();
+        }
+
+        logger.debug("Compute minimum of Series: " + series);
+
+        double min = Double.MAX_VALUE;
+
+        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
+            double tmpValue = dataset.getYValue(series, i);
+
+            if (tmpValue < min) {
+                min = tmpValue;
+            }
+        }
+
+        seriesMinimum.put(key, Double.valueOf(min));
+
+        return min;
+    }
+
+
+    public boolean isMaximum(XYDataset dataset, int series, int item) {
+        return dataset.getYValue(series, item) == getMaximum(dataset, series);
+    }
+
+
+    public double getMaximum(XYDataset dataset, int series) {
+        Integer key = Integer.valueOf(series);
+        Double  old = seriesMaximum.get(Integer.valueOf(series));
+
+        if (old != null) {
+            return old.doubleValue();
+        }
+
+        logger.debug("Compute maximum of Series: " + series);
+
+        double max = -Double.MAX_VALUE;
+
+        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
+            double tmpValue = dataset.getYValue(series, i);
+
+            if (tmpValue > max) {
+                max = tmpValue;
+            }
+        }
+
+        seriesMaximum.put(key, Double.valueOf(max));
+
+        return max;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledAreaSeriesCollection.java	Wed Jan 04 14:43:48 2012 +0000
@@ -0,0 +1,148 @@
+package de.intevation.flys.jfree;
+
+import java.awt.Color;
+import java.awt.Stroke;
+import java.awt.BasicStroke;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+
+import org.jfree.data.xy.XYSeriesCollection;
+
+import de.intevation.flys.utils.ThemeUtil;
+import de.intevation.flys.jfree.StableXYDifferenceRenderer;
+
+
+/**
+ * One or more dataseries to draw a polygon (either "open up/downwards", or
+ * the area between two curves), a theme-document and further display options.
+ * The theme-document will later "style" the graphical representation.
+ * The display options can be used to control the z-order and the axis of the 
+ * dataset.
+ */
+public class StyledAreaSeriesCollection extends XYSeriesCollection {
+    /** Mode, how to draw/which areas to fill. */
+    public enum FILL_MODE {UNDER, ABOVE, BETWEEN};
+
+    /** MODE in use. */
+    protected FILL_MODE mode;
+
+    /** The theme-document with attributes about actual visual representation. */
+    protected Document theme;
+
+    /** Own logger. */
+    private static final Logger logger =
+        Logger.getLogger(StyledAreaSeriesCollection.class);
+
+
+    /**
+     * @param theme the theme-document.
+     */
+    public StyledAreaSeriesCollection(Document theme) {
+        this.theme = theme;
+        this.mode = FILL_MODE.BETWEEN;
+   }
+
+
+    /** Gets the Fill mode. */
+    public FILL_MODE getMode() {
+        return this.mode;
+    }
+
+
+    /** Sets the Fill mode. */
+    public void setMode(FILL_MODE fMode) {
+        this.mode = fMode;
+    }
+
+
+    /**
+     * Applies line color, size and type attributes to renderer, also
+     * whether to draw lines and/or points.
+     */
+    public StableXYDifferenceRenderer applyTheme(
+        StableXYDifferenceRenderer renderer
+    ) {
+        applyFillColor(renderer);
+        applyShowShape(renderer);
+        applyOutlineColor(renderer);
+        applyOutlineStyle(renderer);
+
+        return renderer;
+    }
+
+
+    /**
+     * Blindly (for now) apply the postiviepaint of renderer.
+     */
+    protected void applyFillColor(StableXYDifferenceRenderer renderer) {
+        // Get color.
+        Color paint = ThemeUtil.parseFillColorField(theme);
+        // Get half-transparency flag.
+        if (ThemeUtil.parseTransparency(theme)) {
+            paint = new Color(paint.getRed(), paint.getGreen(), paint.getBlue(),
+                128);
+        }
+        if (paint != null && this.getMode() == FILL_MODE.ABOVE) {
+            renderer.setPositivePaint(paint);
+            renderer.setNegativePaint(new Color(0,0,0,0));
+        }
+        else if (paint != null && this.getMode() == FILL_MODE.UNDER) {
+            renderer.setNegativePaint(paint);
+            renderer.setPositivePaint(new Color(0,0,0,0));
+        }
+        else {
+            if (paint == null) paint = new Color(177, 117, 102);
+            renderer.setPositivePaint(paint);
+            renderer.setNegativePaint(paint);
+        }
+    }
+
+    /**
+     * Blindly (for now) apply the postiviepaint of renderer.
+     */
+    protected void applyShowShape(StableXYDifferenceRenderer renderer) {
+        boolean show = ThemeUtil.parseShowBorder(theme);
+        renderer.setDrawOutline(show);
+    }
+
+    protected void applyShowLine(StableXYDifferenceRenderer renderer) {
+        boolean show = ThemeUtil.parseShowLine(theme);
+        renderer.setShapesVisible(show);
+    }
+
+    /**
+     *
+     */
+    protected void applyOutlineColor(StableXYDifferenceRenderer renderer) {
+        Color c = ThemeUtil.parseLineColorField(theme);
+        renderer.setOutlinePaint(c);
+    }
+
+    protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) {
+        int size = ThemeUtil.parseLineWidth(theme);
+    }
+
+    protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) {
+        float[] dashes = ThemeUtil.parseLineStyle(theme);
+        int size       = ThemeUtil.parseLineWidth(theme);
+
+        Stroke stroke = null;
+
+        if (dashes.length <= 1) {
+            stroke = new BasicStroke(Integer.valueOf(size));
+        }
+        else {
+            stroke = new BasicStroke(Integer.valueOf(size),
+                BasicStroke.CAP_BUTT,
+                BasicStroke.JOIN_ROUND,
+                1.0f,
+                dashes,
+                0.0f);
+        }
+
+        renderer.setOutlineStroke(stroke);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/StyledXYSeries.java	Wed Jan 04 14:43:48 2012 +0000
@@ -0,0 +1,142 @@
+package de.intevation.flys.jfree;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.Ellipse2D;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+
+import de.intevation.flys.utils.ThemeUtil;
+
+/**
+ * Dataseries in two dimensions with additional theme-document and further
+ * display options.
+ * The theme-document will later "style" the graphical representation.
+ * The display options can be used to control the z-order and the axis of the 
+ * dataseries.
+ */
+public class StyledXYSeries extends XYSeries {
+
+    protected Document theme;
+
+    private static final Logger logger = Logger.getLogger(StyledXYSeries.class);
+
+
+    public StyledXYSeries(String key, Document theme) {
+        this(key, true, theme);
+    }
+
+
+    /**
+     * @param sorted whether or not to sort the points. Sorting will move NANs
+     *               to one extrema which can cause problems in certain
+     *               algorithms.
+     */
+    public StyledXYSeries(String key, boolean sorted, Document theme) {
+        super(key, sorted);
+        this.theme = theme;
+    }
+
+
+    /**
+     * Applies line color, size and type attributes to renderer, also
+     * whether to draw lines and/or points.
+     */
+    public XYLineAndShapeRenderer applyTheme(XYLineAndShapeRenderer r, int idx){
+        applyLineColor(r, idx);
+        applyLineSize(r, idx);
+        applyLineType(r, idx);
+        applyShowLine(r, idx);
+        applyShowPoints(r, idx);
+        applyShowMinimum(r, idx);
+        applyShowMaximum(r, idx);
+
+        return r;
+    }
+
+
+    /** Set line color to renderer. */
+    protected void applyLineColor(XYLineAndShapeRenderer r, int idx) {
+        Color c = ThemeUtil.parseLineColorField(theme);
+        r.setSeriesPaint(idx, c);
+    }
+
+
+    protected void applyLineSize(XYLineAndShapeRenderer r, int idx) {
+        int size = ThemeUtil.parseLineWidth(theme);
+        r.setSeriesStroke(
+            idx,
+            new BasicStroke(Integer.valueOf(size)));
+    }
+
+
+    protected void applyLineType(XYLineAndShapeRenderer r, int idx) {
+        int size = ThemeUtil.parseLineWidth(theme);
+        float[] dashes = ThemeUtil.parseLineStyle(theme);
+
+        // Do not apply the dashed style.
+        if (dashes.length <= 1) {
+            return;
+        }
+
+        r.setSeriesStroke(
+            idx,
+            new BasicStroke(Integer.valueOf(size),
+                            BasicStroke.CAP_BUTT,
+                            BasicStroke.JOIN_ROUND,
+                            1.0f,
+                            dashes,
+                            0.0f));
+    }
+
+
+    /**
+     * Sets form and visibility of points.
+     */
+    protected void applyShowPoints(XYLineAndShapeRenderer r, int idx) {
+        boolean show = ThemeUtil.parseShowPoints(theme);
+        int size = ThemeUtil.parseLineWidth(theme);
+        r.setSeriesShape(idx, new Ellipse2D.Double(- size,
+                                                   - size,
+                                                   2 * size,
+                                                   2 * size));
+        r.setSeriesShapesVisible(idx, show);
+        r.setDrawOutlines(true);
+    }
+
+
+    protected void applyShowLine(XYLineAndShapeRenderer r, int idx) {
+        boolean show = ThemeUtil.parseShowLine(theme);
+        r.setSeriesLinesVisible(idx, show);
+    }
+
+
+    protected void applyShowMinimum(XYLineAndShapeRenderer r, int idx) {
+        if (!(r instanceof EnhancedLineAndShapeRenderer)) {
+            return;
+        }
+
+        boolean visible = ThemeUtil.parseShowMinimum(theme);
+
+        EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r;
+        er.setIsMinimumShapeVisisble(idx, visible);
+    }
+
+
+    protected void applyShowMaximum(XYLineAndShapeRenderer r, int idx) {
+        if (!(r instanceof EnhancedLineAndShapeRenderer)) {
+            return;
+        }
+
+        boolean visible = ThemeUtil.parseShowMaximum(theme);
+
+        EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r;
+        er.setIsMaximumShapeVisible(idx, visible);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org