diff flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 2161:c68f4f227c09

Somewhat unified Annotation handling, use jfreechart-house-toolkit instead of custom StickyAxisAnnotation. flys-artifacts/trunk@3747 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Mon, 23 Jan 2012 10:44:34 +0000
parents 2336927cb096
children 105097966111
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Mon Jan 23 07:55:17 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Mon Jan 23 10:44:34 2012 +0000
@@ -31,12 +31,12 @@
 import org.jfree.chart.LegendItem;
 import org.jfree.chart.LegendItemCollection;
 import org.jfree.chart.annotations.XYBoxAnnotation;
+import org.jfree.chart.annotations.XYLineAnnotation;
 import org.jfree.chart.annotations.XYTextAnnotation;
 import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.axis.ValueAxis;
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
 import org.jfree.data.Range;
 import org.jfree.data.xy.XYSeries;
@@ -44,6 +44,7 @@
 import org.jfree.data.xy.XYDataset;
 
 import org.jfree.ui.RectangleInsets;
+import org.jfree.ui.TextAnchor;
 
 import de.intevation.artifacts.CallContext;
 
@@ -56,6 +57,7 @@
 import de.intevation.flys.jfree.FLYSAnnotation;
 import de.intevation.flys.jfree.StableXYDifferenceRenderer;
 import de.intevation.flys.jfree.StickyAxisAnnotation;
+import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation;
 import de.intevation.flys.jfree.StyledAreaSeriesCollection;
 import de.intevation.flys.jfree.StyledXYSeries;
 
@@ -507,8 +509,6 @@
         recoverEmptyPlot(plot);
         preparePointRanges(plot);
 
-        addAnnotationsToRenderer(plot);
-
         //debugAxis(plot);
 
         localizeAxes(plot);
@@ -516,7 +516,7 @@
         autoZoom(plot);
 
         // These have to go after the autozoom.
-        addBoxAnnotations(plot);
+        addAnnotationsToRenderer(plot);
 
         return chart;
     }
@@ -972,61 +972,41 @@
         return null;
     }
 
+    public LegendItem createLegendItem(Document theme, String name) {
+        // OPTIMIZE Pass font, parsed Theme items.
+        ThemeAccess themeAccess = new ThemeAccess(theme);
+        Color color = themeAccess.parseLineColorField();
+        LegendItem li = new LegendItem(name, color);
+        li.setLabelFont(createLegendLabelFont());
+        return li;
+    }
+
 
     /**
-     * Add annotations to Renderer.
+     * Get "lowest" X Value for first axis. This value is exactly at the
+     * border of the plot.
+     * @return lowest value on first 'x'-axis.
      */
-    protected void addAnnotationsToRenderer(XYPlot plot) {
-        plot.clearAnnotations();
-
-        if (annotations == null) {
-            logger.debug("No Annotations given.");
-            return;
+    protected double getLowestXValue(XYPlot plot) {
+        ValueAxis axis = plot.getDomainAxis();
+        if (axis == null) {
+            logger.warn("No X-Axis to find lowest value for.");
         }
-
-        Font labelFont = createLegendLabelFont();
-
-        LegendItemCollection lic = new LegendItemCollection();
-        LegendItemCollection old = plot.getFixedLegendItems();
-
-        XYItemRenderer renderer = plot.getRenderer(0);
-
-        for (FLYSAnnotation fa: annotations) {
-            Document theme = fa.getTheme();
-
-            ThemeAccess themeAccess = new ThemeAccess(theme);
-
-            Color color   = themeAccess.parseLineColorField();
-            int lineWidth = themeAccess.parseLineWidth();
+        return axis.getRange().getLowerBound();
+    }
 
-            LegendItem li = new LegendItem(fa.getLabel(), color);
-            li.setLabelFont(labelFont);
-
-            lic.add(li);
 
-            for (XYTextAnnotation ta: fa.getTextAnnotations()) {
-                if(ta instanceof StickyAxisAnnotation) {
-                    StickyAxisAnnotation sta = (StickyAxisAnnotation)ta;
-                    sta.applyTheme(themeAccess);
-                    renderer.addAnnotation(sta);
-                }
-                else {
-                    ta.setPaint(color);
-                    ta.setOutlineStroke(new BasicStroke((float) lineWidth));
-                    renderer.addAnnotation(ta);
-                }
-            }
+    /**
+     * Get "lowest" X Value for first axis. This value is exactly at the
+     * border of the plot.
+     * @return highest value on first 'x'-axis.
+     */
+    protected double getUppestXValue(XYPlot plot) {
+        ValueAxis axis = plot.getDomainAxis();
+        if (axis == null) {
+            logger.warn("No first Y-Axis to find uppest value for.");
         }
-
-        // (Re-)Add prior legend entries.
-        if (old != null) {
-            old.addAll(lic);
-        }
-        else {
-            old = lic;
-        }
-
-        plot.setFixedLegendItems(old);
+        return axis.getRange().getUpperBound();
     }
 
 
@@ -1084,9 +1064,74 @@
     }
 
 
-    /** Add box annotations (currently, only hyk zones). */
-    public void addBoxAnnotations(XYPlot plot) {
-        logger.debug("XYChartGenerator.addBoxAnnotations");
+    /**
+     * Add a text and a line annotation.
+     */
+    public void addStickyAnnotation(
+        StickyAxisAnnotation annotation,
+        XYPlot plot,
+        Area area,
+        ThemeAccess.LineStyle lineStyle,
+        ThemeAccess.TextStyle textStyle
+    ) {
+        // OPTIMIZE pre-calculate area-related values
+        final float TEXT_OFF = 0.03f;
+        final float LINE_OFF = 0.02f;
+
+        XYLineAnnotation lineAnnotation = null;
+        XYTextAnnotation textAnnotation = null;
+
+        if (annotation.atX()) {
+            textAnnotation = new CollisionFreeXYTextAnnotation(
+                annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF));
+            // OPTIMIZE externalize the calculation involving PI.
+            textAnnotation.setRotationAngle(270f*Math.PI/180f);
+            // Style the line.
+            if (lineStyle != null) {
+                lineAnnotation = new XYLineAnnotation(annotation.getPos(),
+                    area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF),
+                    new BasicStroke(lineStyle.getWidth()),lineStyle.getColor());
+            }
+            else {
+                lineAnnotation = new XYLineAnnotation(annotation.getPos(),
+                    area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF));
+            }
+        }
+        else {
+            textAnnotation = new CollisionFreeXYTextAnnotation(
+                annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos());
+            // Style the line.
+            if (lineStyle != null) {
+                lineAnnotation = new XYLineAnnotation(area.atLeft(),
+                    annotation.getPos(), area.ofLeft(LINE_OFF),
+                    annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
+                    lineStyle.getColor());
+            }
+            else {
+                lineAnnotation = new XYLineAnnotation(area.atLeft(),
+                    annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos());
+            }
+        }
+
+        // Style the text.
+        if (textStyle != null) {
+            textStyle.apply(textAnnotation);
+        }
+
+        // Add the Annotations to renderer.
+        textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+        textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
+
+        plot.getRenderer().addAnnotation(textAnnotation,
+            org.jfree.ui.Layer.BACKGROUND);
+        plot.getRenderer().addAnnotation(lineAnnotation,
+            org.jfree.ui.Layer.BACKGROUND);
+    }
+
+
+    /** Add annotations (Sticky, Text and hyk zones). */
+    public void addAnnotationsToRenderer(XYPlot plot) {
+        logger.debug("XYChartGenerator.addAnnotationsToRenderer");
 
         if (annotations == null) {
             logger.debug("XYChartGenerator.addBoxAnnotations: no annotations.");
@@ -1096,47 +1141,72 @@
         // Paints for the boxes/lines.
         Stroke basicStroke = new BasicStroke(1.0f);
 
-        Paint linePaint = new Color(255,0,0,60);
-        Paint fillPaint = new Color(0,255,0,60);
-        Paint tranPaint = new Color(0,0,0,0);
+        Paint linePaint = new Color(255,  0,0,60);
+        Paint fillPaint = new Color(0,  255,0,60);
+        Paint tranPaint = new Color(0,    0,0, 0);
 
-        // Pre-calculated positions on y axis.
-        double fillPercent = 0.03;
-        double low = getLowestYValue(plot);
-        double up  = getUppestYValue(plot);
-        double upb = low + (up - low) * fillPercent;
-        double upt = low + (up - low) * fillPercent/2.0d;
+        // OPTMIMIZE: Pre-calculate positions
+        Area area = new Area(
+            plot.getDomainAxis(0).getRange(),
+            plot.getRangeAxis().getRange());
 
+        // Walk over all Annotation sets.
+        for (FLYSAnnotation fa: annotations) {
 
-        for (FLYSAnnotation fa: annotations) {
             // Access text styling, if any.
             Document theme = fa.getTheme();
             ThemeAccess.TextStyle textStyle = null;
+            ThemeAccess.LineStyle lineStyle = null;
+
+            // Get Themeing information and add legend item.
             if (theme != null) {
                 ThemeAccess themeAccess = new ThemeAccess(theme);
                 textStyle = themeAccess.parseTextStyle();
+                lineStyle = themeAccess.parseLineStyle();
+                LegendItemCollection lic = new LegendItemCollection();
+                LegendItemCollection old = plot.getFixedLegendItems();
+                lic.add(createLegendItem(theme, fa.getLabel()));
+                // (Re-)Add prior legend entries.
+                if (old != null) {
+                    old.addAll(lic);
+                }
+                else {
+                    old = lic;
+                }
+                plot.setFixedLegendItems(old);
             }
 
-            // For each zone, create a box to fill with color, a box to draw
-            // the lines and a text to display the type.
+            // The 'Sticky' Annotations (at axis, with line and text).
+            for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) {
+                addStickyAnnotation(sta, plot, area, lineStyle, textStyle);
+            }
+
+            // The not yet implemented other Text Annotations.
+            for (XYTextAnnotation ta: fa.getTextAnnotations()) {
+                // TODO implement, one we have textannotations
+            }
+
+            // Hyks.
             for (HYKFactory.Zone zone: fa.getBoxes()) {
+                // For each zone, create a box to fill with color, a box to draw
+                // the lines and a text to display the type.
                 fillPaint = colorForHYKZone(zone.getName());
 
-                XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), low,
-                    zone.getTo(), upb, basicStroke, tranPaint, fillPaint);
-                XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), low,
-                    zone.getTo(), up, basicStroke, fillPaint, tranPaint);
+                XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(),
+                    zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint);
+                XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(),
+                    zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint);
 
                 XYTextAnnotation tex = new XYTextAnnotation(zone.getName(),
                     zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d,
-                    upt);
+                    area.ofGround(0.015f));
                 if (textStyle != null) {
                     textStyle.apply(tex);
                 }
 
-                plot.getRenderer().addAnnotation(boxA);
-                plot.getRenderer().addAnnotation(boxB);
-                plot.getRenderer().addAnnotation(tex);
+                plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND);
+                plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND);
+                plot.getRenderer().addAnnotation(tex,  org.jfree.ui.Layer.BACKGROUND);
             }
         }
     }
@@ -1553,5 +1623,39 @@
 
         return axisSections;
     }
+
+
+    /** Two Ranges that span a rectangular area. */
+    public static class Area {
+        protected Range xRange;
+        protected Range yRange;
+
+        public Area(Range rangeX, Range rangeY) {
+            this.xRange = rangeX;
+            this.yRange = rangeY;
+        }
+
+        public double ofLeft(double percent) {
+            return xRange.getLowerBound()
+                + xRange.getLength() * percent;
+        }
+
+        public double ofGround(double percent) {
+            return yRange.getLowerBound()
+                + yRange.getLength() * percent;
+        }
+
+        public double atTop() {
+            return yRange.getUpperBound();
+        }
+
+        public double atGround() {
+            return yRange.getLowerBound();
+        }
+
+        public double atLeft() {
+            return xRange.getLowerBound();
+        }
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org