diff gnv-artifacts/src/main/java/de/intevation/gnv/chart/XMLChartTheme.java @ 1119:7c4f81f74c47

merged gnv-artifacts
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:00 +0200
parents dec4257ad570
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/chart/XMLChartTheme.java	Fri Sep 28 12:14:00 2012 +0200
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2010 by Intevation GmbH
+ *
+ * This program is free software under the LGPL (>=v2.1)
+ * Read the file LGPL.txt coming with the software for details
+ * or visit http://www.gnu.org/licenses/ if it does not exist.
+ */
+
+package de.intevation.gnv.chart;
+
+import de.intevation.artifacts.common.utils.Config;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Paint;
+
+import java.awt.geom.Ellipse2D;
+
+import org.apache.log4j.Logger;
+
+import org.jfree.chart.StandardChartTheme;
+
+import org.jfree.chart.plot.XYPlot;
+
+import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
+import org.jfree.chart.renderer.xy.XYBarRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+
+import org.jfree.ui.RectangleInsets;
+
+import org.jfree.util.UnitType;
+
+import org.w3c.dom.Document;
+
+/**
+ * Implementation of JFreeChart's default implementation
+ * <code>StandardChartTheme</code>. This class takes an xml document with a
+ * bunch of parameters and turns it into a <code>ChartTheme</code> to change
+ * the appearance of charts.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class XMLChartTheme
+extends      StandardChartTheme
+{
+    /**
+     * Default color.
+     */
+    private static final Color DEFAULT_COLOR = Color.BLACK;
+
+    /**
+     * Logger used for logging with log4j.
+     */
+    private Logger log = Logger.getLogger(XMLChartTheme.class);
+
+    /**
+     * Field storing the visibility of the domain crosshair
+     */
+    protected boolean domainCrosshairVisible;
+
+    /**
+     * Field storing the visibility of the range crosshair
+     */
+    protected boolean rangeCrosshairVisible;
+
+    /**
+     * Field storing the visiblity of lines.
+     */
+    protected boolean renderLines;
+
+    /**
+     * Field storing the visibility of data points
+     */
+    protected boolean renderShapes;
+
+    /**
+     * Field storing the width of a data point
+     */
+    protected int pointWidth;
+
+    /**
+     * Field storing the height of a data point.
+     */
+    protected int pointHeight;
+
+    /**
+     * Field storing the base color of a bin in a histogram chart
+     */
+    protected Paint histogramBasePaint;
+
+
+    /**
+     * Constructor
+     *
+     * @param name Name for this theme.
+     */
+    public XMLChartTheme(String name) {
+        super(name);
+    }
+
+
+    /**
+     * Setter method for the visibility of the domain crosshair.
+     *
+     * @param visible True, if domain crosshair should be visible
+     */
+    public void setDomainCrosshairVisible(boolean visible) {
+        this.domainCrosshairVisible = visible;
+    }
+
+
+    /**
+     * Getter method for retrieving the visibility of the domain crosshair.
+     *
+     * @return Visibility of the domain crosshair.
+     */
+    public boolean getDomainCrosshairVisible() {
+        return domainCrosshairVisible;
+    }
+
+
+    /**
+     * Getter method for retrieving the visibility of the range crosshair.
+     *
+     * @return Visibility of the range crosshair.
+     */
+    public boolean getRangeCrosshairVisible() {
+        return rangeCrosshairVisible;
+    }
+
+
+    /**
+     * Setter method for the visibility of the range crosshair.
+     *
+     * @param visible True, if range crosshair should be visible
+     */
+    public void setRangeCrosshairVisible(boolean visible) {
+        this.rangeCrosshairVisible = visible;
+    }
+
+
+    /**
+     * Method to set the bin color of histograms.
+     *
+     * @param c Bin color
+     */
+    public void setHistogramBasePaint(Color c) {
+        this.histogramBasePaint = c;
+    }
+
+
+    /**
+     * Getter method for retrieving the bin color.
+     *
+     * @return Bin color
+     */
+    public Paint getHistogramBasePaint() {
+        return histogramBasePaint;
+    }
+
+
+    /**
+     * Take a given xml document and read the configuration of a chart
+     * appearance.
+     *
+     * @param document XML document
+     */
+    public void applyXMLConfiguration(Document document) {
+        log.debug("create XMLChartTheme");
+
+        init(document);
+    }
+
+
+    /**
+     * Start parsing the different settings from <code>document</code>.
+     *
+     * @param document XML document
+     */
+    private void init(Document document) {
+        log.debug("init XMLChartTheme parameters");
+
+        initChartParameters(document);
+        initTitleParameters(document);
+        initSubtitleParameters(document);
+        initPlotParameters(document);
+        initAxisParameters(document);
+        initLegendParameters(document);
+        initRenderer(document);
+        initHistogramColor(document);
+    }
+
+
+    /**
+     * Read parameters configuring the title of a chart.
+     *
+     * @param document XML document
+     */
+    private void initTitleParameters(Document document) {
+        log.debug("init title parameters.");
+
+        int     size  = getInt(document, "theme/title/font/size/@value");
+        String  type  = getString(document, "theme/title/font/type/@value");
+        boolean bold  = getBool(document, "theme/title/font/bold/@value");
+
+        setExtraLargeFont(createFont(type, size, bold));
+
+        String color = getString(document, "theme/title/font/color/@value");
+        Color  c     = decodeColor(color);
+        if (c != null)
+            setTitlePaint(c);
+    }
+
+
+    /**
+     * Read parameters configuring the subtitle of a chart.
+     *
+     * @param document XML document
+     */
+    private void initSubtitleParameters(Document document) {
+        log.debug("init title parameters.");
+
+        int     size  = getInt(document, "theme/subtitle/font/size/@value");
+        String  type  = getString(document, "theme/subtitle/font/type/@value");
+        boolean bold  = getBool(document, "theme/subtitle/font/bold/@value");
+
+        setLargeFont(createFont(type, size, bold));
+
+        String col  = getString(document, "theme/subtitle/font/color/@value");
+        setSubtitlePaint(Color.decode(col));
+    }
+
+
+    /**
+     * Read parameters configuring the background color of a chart.
+     *
+     * @param document XML document
+     */
+    private void initChartParameters(Document document) {
+        log.debug("init chart parameters.");
+
+        String bg = getString(document, "theme/chart/background/color/@value");
+        Color  c  = decodeColor(bg);
+        if (c != null)
+            setChartBackgroundPaint(c);
+    }
+
+
+    /**
+     * Read parameters configuring the plot of a chart.
+     *
+     * @param document XML document
+     */
+    private void initPlotParameters(Document document) {
+        log.debug("init plot parameters.");
+
+        String tmp = null;
+        tmp        = getString(document, "theme/plot/background/color/@value");
+        Color  c   = decodeColor(tmp);
+        if (c != null)
+            setPlotBackgroundPaint(c);
+
+        tmp = getString(document, "theme/plot/outline/color/@value");
+        c   = decodeColor(tmp);
+        if (c != null)
+            setPlotOutlinePaint(c);
+
+        tmp = getString(document, "theme/plot/domaingridline/color/@value");
+        c   = decodeColor(tmp);
+        if (c != null)
+            setDomainGridlinePaint(c);
+
+        tmp = getString(document, "theme/plot/rangegridline/color/@value");
+        c   = decodeColor(tmp);
+        if (c != null)
+            setRangeGridlinePaint(c);
+
+        boolean rangeCrosshairVisible = getBool(
+            document, "theme/plot/rangecrosshair/visible/@value");
+        setRangeCrosshairVisible(rangeCrosshairVisible);
+
+        boolean domainCrosshairVisible = getBool(
+            document, "theme/plot/domaincrosshair/visible/@value");
+        setDomainCrosshairVisible(domainCrosshairVisible);
+
+        int top    = getInt(document, "theme/plot/offset/top/@value");
+        int bottom = getInt(document, "theme/plot/offset/bottom/@value");
+        int left   = getInt(document, "theme/plot/offset/left/@value");
+        int right  = getInt(document, "theme/plot/offset/right/@value");
+        setAxisOffset(new RectangleInsets(
+            UnitType.RELATIVE,
+            top, left, bottom, right)
+        );
+    }
+
+
+    /**
+     * Read parameters configuring the axes of a plot.
+     *
+     * @param document XML document
+     */
+    private void initAxisParameters(Document document) {
+        log.debug("init axis parameters.");
+
+        String tmp = null;
+        tmp        = getString(document, "theme/axis/label/color/@value");
+        Color c    = decodeColor(tmp);
+        if (c != null)
+            setAxisLabelPaint(c);
+
+        tmp = getString(document, "theme/axis/ticklabel/color/@value");
+        c   = decodeColor(tmp);
+        if (c != null)
+            setTickLabelPaint(c);
+    }
+
+
+    /**
+     * Read parameters configuring the legend of a chart.
+     *
+     * @param document XML document
+     */
+    private void initLegendParameters(Document document) {
+        log.debug("init legend parameters.");
+
+        String tmp = null;
+        tmp        = getString(document, "theme/legend/font/color/@value");
+        Color c    = decodeColor(tmp);
+        if (c != null)
+            setLegendItemPaint(c);
+
+        tmp = getString(document, "theme/legend/background/color/@value");
+        c   = decodeColor(tmp);
+        if (c != null)
+            setLegendBackgroundPaint(c);
+    }
+
+
+    /**
+     * Read parameters configuring the renderer of a plot.
+     *
+     * @param document XML document
+     */
+    private void initRenderer(Document document) {
+        log.debug("init renderer parameters.");
+
+        pointWidth  = getInt(document, "theme/plot/itemrenderer/width/@value");
+        log.debug("Read point width of " + pointWidth);
+        pointHeight = getInt(document, "theme/plot/itemrenderer/height/@value");
+        log.debug("Read point height of " + pointHeight);
+        renderLines = getBool(
+            document, "theme/plot/itemrenderer/renderLines/@value"
+        );
+        renderShapes = getBool(
+            document, "theme/plot/itemrenderer/renderPoints/@value"
+        );
+    }
+
+
+    /**
+     * Read base color of bins in histogram charts.
+     *
+     * @param document XML document
+     */
+    private void initHistogramColor(Document document) {
+        log.debug("init histogram color");
+        String tmp = getString(document, "theme/histogram/bar/color/@value");
+        Color c = decodeColor(tmp);
+
+        if (c != null)
+            setHistogramBasePaint(c);
+    }
+
+
+    /**
+     * Read a xpath expression and return the matched string.
+     *
+     * @param document Document
+     * @param xpath XPath expression
+     *
+     * @return Matched string
+     */
+    private static String getString(Document document, String xpath) {
+        return Config.getStringXPath(document, xpath);
+    }
+
+
+    /**
+     * Read a xpath and turn it into an integer.
+     *
+     * @param document Document
+     * @param xpath XPath expression
+     *
+     * @return Matched string as integer representation. Return 0 if no integer
+     * have been found at <code>xpath</code>.
+     */
+    private static int getInt(Document document, String xpath) {
+        String tmp = getString(document, xpath);
+
+        if (tmp != null)
+            return Integer.parseInt(tmp);
+        else
+            return 0;
+    }
+
+
+    /**
+     * Read a xpath and turn it into a boolean.
+     *
+     * @param document Document
+     * @param xpath XPath expression
+     *
+     * @return Matched string as boolean representation. Return false if no
+     * boolean have been found at <code>xpath</code>.
+     */
+    private static boolean getBool(Document document, String xpath) {
+        String tmp = getString(document, xpath);
+
+        if (tmp != null)
+            return Boolean.parseBoolean(tmp);
+        else
+            return false;
+    }
+
+
+    /**
+     * Turns a string into a color using {@link java.awt.Color}.
+     *
+     * @param color as string
+     *
+     * @return Color
+     */
+    protected Color decodeColor(String color) {
+        try {
+            if (color == null)
+                return null;
+
+            return Color.decode(color);
+        }
+        catch (NumberFormatException nfe) {
+            log.warn("Error while parsing color: " + color, nfe);
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Create a font with the given parameters.
+     *
+     * @param type Font type
+     * @param size Font size
+     * @param bold Font weight
+     *
+     * @return Font
+     */
+    protected Font createFont(String type, int size, boolean bold) {
+        Font font = null;
+        if (bold)
+            font = new Font(type, Font.BOLD, size);
+        else
+            font = new Font(type, Font.PLAIN, size);
+
+        return font;
+    }
+
+
+    /**
+     * Apply settings of this <code>ChartTheme</code> to the given
+     * <code>XYPlot</code>.
+     *
+     * @param plot XYPlot
+     */
+    @Override
+    protected void applyToXYPlot(XYPlot plot) {
+        log.debug("apply theme parameter to XYPlot");
+
+        super.applyToXYPlot(plot);
+        plot.setDomainCrosshairVisible(this.domainCrosshairVisible);
+        plot.setRangeCrosshairVisible(this.rangeCrosshairVisible);
+
+        AbstractXYItemRenderer renderer = (AbstractXYItemRenderer)
+            plot.getRenderer();
+
+        if (renderer instanceof XYLineAndShapeRenderer)
+            applyToXYLineAndShapeRenderer(plot);
+
+        if (renderer instanceof XYBarRenderer)
+            applyToXYBarRenderer(plot);
+    }
+
+
+    /**
+     * Apply settings of this <code>ChartTheme</code> to the
+     * <code>XYLineAndShapeRenderer</code> of the given <code>XYPlot</code>.
+     *
+     * @param plot XYPlot
+     */
+    protected void applyToXYLineAndShapeRenderer(XYPlot plot) {
+        if (plot == null)
+            return;
+
+        XYLineAndShapeRenderer renderer =
+            (XYLineAndShapeRenderer) plot.getRenderer();
+
+        Ellipse2D.Double point = new Ellipse2D.Double(
+            -(pointWidth/2), -(pointHeight/2), pointWidth, pointHeight
+        );
+
+        renderer.setSeriesShape(0, point);
+        renderer.setSeriesShapesVisible(0, renderShapes);
+        renderer.setSeriesLinesVisible(0, renderLines);
+
+        plot.setRenderer(renderer);
+    }
+
+
+    /**
+     * Apply settings of this <code>ChartTheme</code> to the
+     * <code>XYBarRenderer</code> of the given <code>XYPlot</code>.
+     *
+     * @param plot XYPlot
+     */
+    protected void applyToXYBarRenderer(XYPlot plot) {
+        if (plot == null)
+            return;
+
+        XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer();
+
+        renderer.setSeriesPaint(0, histogramBasePaint);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org