diff flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 1931:7c52e9cb2a72

Allow more than two datasets and more flexibility with axes in plots. Based on patch by S. Teichmann. flys-artifacts/trunk@3312 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Thu, 24 Nov 2011 07:20:46 +0000
parents de0c2bbb27f9
children 17e18948fe5e
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -10,8 +10,10 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 
 import org.w3c.dom.Document;
 
@@ -31,6 +33,7 @@
 import org.jfree.data.Range;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.data.xy.XYDataset;
 
 import org.jfree.ui.RectangleInsets;
 
@@ -52,11 +55,8 @@
     /** The logger that is used in this generator. */
     private static Logger logger = Logger.getLogger(XYChartGenerator.class);
 
-    /** SeriesCollection used for the first axis. */
-    protected XYSeriesCollection first;
-
-    /** SeriesCollection used for the second axis. */
-    protected XYSeriesCollection second;
+    /** Map of datasets ("index"). */
+    protected SortedMap<Integer, List<XYDataset>> datasets;
 
     /** List of annotations to insert in plot. */
     protected List<FLYSAnnotation> annotations;
@@ -71,6 +71,13 @@
     public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f;
 
 
+    public XYChartGenerator() {
+        xRanges  = new HashMap<Integer, Range>();
+        yRanges  = new HashMap<Integer, Range>();
+        datasets = new TreeMap<Integer, List<XYDataset>>();
+    }
+
+
     /**
      * Returns the title of a chart.
      *
@@ -157,10 +164,9 @@
             false,
             false);
 
+        XYPlot plot = (XYPlot) chart.getPlot();
         chart.setBackgroundPaint(Color.WHITE);
-        chart.getPlot().setBackgroundPaint(Color.WHITE);
-
-        XYPlot plot = (XYPlot) chart.getPlot();
+        plot.setBackgroundPaint(Color.WHITE);
 
         addDatasets(plot);
         addAnnotations(plot);
@@ -169,6 +175,7 @@
         localizeAxes(plot);
 
         removeEmptyRangeAxes(plot);
+        createAxes(plot);
         adjustAxes(plot);
 
         preparePointRanges(plot);
@@ -181,73 +188,67 @@
 
 
     /**
-     * Add first and second dataset to plot.
+     * Add datasets to plot.
      * @param plot plot to add datasets to.
      */
     protected void addDatasets(XYPlot plot) {
-        if (first != null) {
-            logger.debug("Set the first axis dataset.");
-            plot.setDataset(0, first);
-        }
-        if (second != null) {
-            logger.debug("Set the second axis dataset.");
-            plot.setDataset(1, second);
-        }
-    }
-
-
-    public void addFirstAxisSeries(XYSeries series, boolean visible) {
-        if (first == null) {
-            first = new XYSeriesCollection();
-        }
-
-        if (series != null) {
-            if (visible) {
-                first.addSeries(series);
+        int count = 0;
+        for (Map.Entry<Integer, List<XYDataset>> entry: datasets.entrySet()) {
+            List<Integer> axisList = new ArrayList<Integer>(1);
+            axisList.add(entry.getKey());
+            for (XYDataset dataset: entry.getValue()) {
+                int index = count++;
+                plot.setDataset(index, dataset);
+                plot.mapDatasetToRangeAxes(index, axisList);
             }
-
-            combineYRanges(new Range(series.getMinY(), series.getMaxY()), 0);
-            combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
         }
     }
 
 
-    public void addSecondAxisSeries(XYSeries series, boolean visible) {
-        if (second == null) {
-            second = new XYSeriesCollection();
-        }
-
-        if (series != null) {
-            if (visible) {
-                second.addSeries(series);
-            }
-
-            combineYRanges(new Range(series.getMinY(), series.getMaxY()), 1);
-            combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
-        }
-    }
-
-
-    private void combineXRanges(Range range, int index) {
-        Integer key = Integer.valueOf(index);
-
-        if (xRanges == null) {
-            xRanges = new HashMap<Integer, Range>();
-            xRanges.put(key, range);
+    /**
+     * Add given series.
+     * @param series the dataseries to include in plot.
+     * @param index  index of the series and of its axis.
+     * @param visible whether or not the data should be plotted.
+     */
+    public void addAxisSeries(XYSeries series, int index, boolean visible) {
+        if (series == null) {
             return;
         }
 
-        Range newX = null;
-        Range oldX = xRanges.get(key);
+        if (visible) {
+            XYSeriesCollection collection = new XYSeriesCollection(series);
 
-        if (oldX != null) {
-            newX = Range.combine(oldX, range);
-        }
-        else {
-            newX = range;
+            List<XYDataset> dataset = datasets.get(index);
+
+            if (dataset == null) {
+                dataset = new ArrayList<XYDataset>();
+                datasets.put(index, dataset);
+            }
+
+            dataset.add(collection);
         }
 
-        xRanges.put(key, newX);
+        // Do this also when not visible to have axis scaled by default such
+        // that every data-point could be seen (except for annotations).
+        combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
+        combineYRanges(new Range(series.getMinY(), series.getMaxY()), index);
+    }
+
+    /**
+     * Effect: extend range of x axis to include given limits.
+     * @param range the given ("minimal") range.
+     * @param index index of axis to be merged.
+     */
+    private void combineXRanges(Range range, int index) {
+
+        Range old = xRanges.get(index);
+
+        if (old != null) {
+            range = Range.combine(old, range);
+        }
+
+        xRanges.put(index, range);
     }
 
 
@@ -255,25 +256,14 @@
      * @param range the new range.
      */
     private void combineYRanges(Range range, int index) {
-        Integer key = Integer.valueOf(index);
 
-        if (yRanges == null) {
-            yRanges = new HashMap<Integer, Range>();
-            yRanges.put(key, range);
-            return;
+        Range old = yRanges.get(index);
+
+        if (old != null) {
+            range = Range.combine(old, range);
         }
 
-        Range newY = null;
-        Range oldY = yRanges.get(key);
-
-        if (oldY != null) {
-            newY = Range.combine(oldY, range);
-        }
-        else {
-            newY = range;
-        }
-
-        yRanges.put(key, newY);
+        yRanges.put(index, range);
     }
 
 
@@ -293,17 +283,47 @@
     }
 
 
+    /**
+     * Create y-axes.
+     */
+    public void createAxes(XYPlot plot) {
+        logger.debug("XYChartGenerator.createAxes");
+        Integer last = datasets.lastKey();
+
+        if (last != null) {
+            for (int i = last; i >= 0; --i) {
+                if (datasets.containsKey(i)) {
+                    plot.setRangeAxis(i, createYAxis(i));
+                }
+            }
+        }
+    }
+
+    /**
+     * Create Y (range) axis for given index.
+     * Shall be overriden by subclasses.
+     */
+    protected NumberAxis createYAxis(int index) {
+        NumberAxis axis = new NumberAxis("default axis");
+        return axis;
+    }
+
     private void removeEmptyRangeAxes(XYPlot plot) {
-        if (first == null) {
-            plot.setRangeAxis(0, null);
-        }
+        Integer last = datasets.lastKey();
 
-        if (second == null) {
-            plot.setRangeAxis(1, null);
+        if (last != null) {
+            for (int i = last-1; i >= 0; --i) {
+                if (!datasets.containsKey(i)) {
+                    plot.setRangeAxis(i, null);
+                }
+            }
         }
     }
 
 
+    /**
+     * Expands X and Y axes if only a point is shown.
+     */
     private void preparePointRanges(XYPlot plot) {
         for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) {
             Integer key = Integer.valueOf(i);
@@ -325,6 +345,9 @@
     }
 
 
+    /**
+     * Expand range by percent.
+     */
     public static Range expandRange(Range range, double percent) {
         if (range == null) {
             return null;
@@ -479,14 +502,18 @@
 
 
     /**
-     * Adjusts the axes of a plot.
+     * Adjusts the axes of a plot (the first axis does not include zero).
      *
      * @param plot The XYPlot of the chart.
      */
     protected void adjustAxes(XYPlot plot) {
         NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
-
-        yAxis.setAutoRangeIncludesZero(false);
+        if (yAxis == null) {
+            logger.warn("No Axis to setAutoRangeIncludeZero.");
+        }
+        else {
+            yAxis.setAutoRangeIncludesZero(false);
+        }
     }
 
 
@@ -508,14 +535,6 @@
         plot.setRangeGridlinesVisible(true);
 
         plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
-
-        if (plot.getDataset(0) != null) {
-            plot.mapDatasetToRangeAxis(0, 0);
-        }
-
-        if (plot.getDataset(1) != null) {
-            plot.mapDatasetToRangeAxis(1, 1);
-        }
     }
 
 
@@ -581,12 +600,14 @@
 
 
     protected void applyThemes(XYPlot plot) {
-        if (first != null) {
-            applyThemes(plot, first, 0);
-        }
 
-        if (second != null) {
-            applyThemes(plot, second, 1);
+        for (Map.Entry<Integer, List<XYDataset>> entry: datasets.entrySet()) {
+            int axis = entry.getKey();
+            for (XYDataset dataset: entry.getValue()) {
+                if (dataset instanceof XYSeriesCollection) {
+                    applyThemes(plot, (XYSeriesCollection)dataset, axis);
+                }
+            }
         }
     }
 

http://dive4elements.wald.intevation.org