org.pentaho.platform.uifoundation.chart.DialWidgetDefinition.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.uifoundation.chart.DialWidgetDefinition.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License, version 2 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * This program 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 General Public License for more details.
 *
 *
 * Copyright 2006 - 2013 Pentaho Corporation.  All rights reserved.
 */

package org.pentaho.platform.uifoundation.chart;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.jfree.chart.plot.DialShape;
import org.jfree.chart.plot.MeterInterval;
import org.jfree.data.Range;
import org.jfree.ui.RectangleEdge;
import org.pentaho.commons.connection.DataUtilities;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.commons.connection.PentahoDataTransmuter;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.uifoundation.messages.Messages;
import org.pentaho.platform.util.messages.LocaleHelper;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * This class represents the definition of a dashboard dial. It holds:
 * <ul>
 * <li>The value to be displayed on the dial</li>
 * <li>Minimum value of the dial</li>
 * <li>Maximum value of the dial</li>
 * <li>A list of intervals with the dial. Each interval specifies a minimum, maximum and information about how the
 * interval should be painted.</li>
 * <li>Painting information
 * <ul>
 * <li>Background paint</li>
 * <li>Dial paint</li>
 * <li>Needle paint</li>
 * </ul>
 * </ul>
 * 
 * <p/>
 * This class does not generate an image of the dial, it just defines the properties of the dial.
 * <p/>
 * Dial definitions are stored in xml documents in the solution folders with *.dial.xml extensions. These
 * definition files store XML representations of all the settings here. Typically the value to be displayed is
 * provided at runtime by a query or business rule, but the value can also read from the definition file.
 * <p/>
 * The definitions are read by org.pentaho.core.ui.component.DashboardWidgetComponent objects, which create
 * instances of this object and set the properties defined here.
 * <p/>
 * The DashboardWidgetComponent objects pass this, now populated, object to
 * 
 * The dial image is generated by {@link org.pentaho.core.ui.component.JFreeChartEngine}
 * <p/>
 * 
 * Example Dial <br/>
 * <img src="doc-files/DialWidgetDefinition-1.png">
 */
public class DialWidgetDefinition extends WidgetDefinition implements ChartDefinition {

    private static final long serialVersionUID = 2232742163326878608L;

    private final ArrayList intervals = new ArrayList();

    private final RectangleEdge titlePosition = RectangleEdge.TOP;

    private Paint chartBackgroundPaint = Color.WHITE;

    private Paint plotBackgroundPaint = Color.GRAY;

    private Paint needlePaint = Color.blue;

    private DialShape dialShape = DialShape.CHORD;

    private Font titleFont;

    private final List subTitles = new ArrayList();

    private boolean rangeLimited;

    private int tickSize = 5;

    private Paint tickPaint = Color.blue;

    private Paint valuePaint = Color.BLUE;

    private Font valueFont;

    private String units;

    private Font legendFont = null;

    private boolean legendBorderVisible = true;

    private RectangleEdge legendPosition = RectangleEdge.BOTTOM;

    private Node attributes = null;

    private Float backgroundAlpha;

    private Float foregroundAlpha;

    // private IPentahoSession session;

    public DialWidgetDefinition(final double value, final double minimum, final double maximum,
            final boolean rangeLimited) {
        super(value, minimum, maximum);
        this.rangeLimited = rangeLimited;
    }

    /**
     * TODO PROBLEM HERE! If you use this constructor, the XML schema for the chart attributes is different than if
     * you use the constructor with the arguments public DialWidgetDefinition( Document document, double value, int
     * width, int height, IPentahoSession session). This constructor expects the chart attribute nodes to be children
     * of the <chart-attributes> node, whereas the latter constructor expects the attributes to be children of a
     * <dial> node. This does not help us with our parity situation, and should be deprecated and reconciled.
     * 
     * @param data
     * @param byRow
     * @param chartAttributes
     * @param width
     * @param height
     * @param session
     */
    public DialWidgetDefinition(final IPentahoResultSet data, final boolean byRow, final Node chartAttributes,
            final int width, final int height, final IPentahoSession session) {
        this(0.0, Double.MIN_VALUE, Double.MAX_VALUE, false);

        attributes = chartAttributes;

        if (data != null) {
            if (byRow) {
                setDataByRow(data);
            } else {
                setDataByColumn(data);
            }
        }

        // set legend font
        setLegendFont(chartAttributes.selectSingleNode(ChartDefinition.LEGEND_FONT_NODE_NAME));

        // set legend border visible
        setLegendBorderVisible(chartAttributes.selectSingleNode(ChartDefinition.DISPLAY_LEGEND_BORDER_NODE_NAME));
        // set the alfa layers
        Node backgroundAlphaNode = chartAttributes.selectSingleNode(ChartDefinition.BACKGROUND_ALPHA_NODE_NAME);
        Node foregroundAlphaNode = chartAttributes.selectSingleNode(ChartDefinition.FOREGROUND_ALPHA_NODE_NAME);

        if (backgroundAlphaNode != null) {
            setBackgroundAlpha(chartAttributes.selectSingleNode(ChartDefinition.BACKGROUND_ALPHA_NODE_NAME));
        }
        if (foregroundAlphaNode != null) {
            setForegroundAlpha(chartAttributes.selectSingleNode(ChartDefinition.FOREGROUND_ALPHA_NODE_NAME));
        }
        DialWidgetDefinition.createDial(this, chartAttributes, width, height, session);
    }

    /**
     * TODO: PROBLEM HERE! See the note on the constructor above.
     * 
     * @param document
     * @param value
     * @param width
     * @param height
     * @param session
     */
    public DialWidgetDefinition(final Document document, final double value, final int width, final int height,
            final IPentahoSession session) {
        this(value, Double.MIN_VALUE, Double.MAX_VALUE, false);

        // get the dial node from the document
        attributes = document.selectSingleNode("//dial"); //$NON-NLS-1$

        deriveMinMax(value);

        // create the dial definition object
        DialWidgetDefinition.createDial(this, attributes, width, height, session);
    }

    public static Log getLogger() {
        return LogFactory.getLog(DialWidgetDefinition.class);
    }

    /*
     * public ThermometerWidgetDefinition createThermometer( Document doc ) { // TODO implement this to return a
     * ThermometerWidgetDefinition object return null; }
     */
    /**
     * Create a dial definition object from an XML document
     * 
     * @param doc
     *          definition XML document
     * @return Dial definition object
     */
    public static void createDial(final DialWidgetDefinition widgetDefinition, final Node dialNode, final int width,
            final int height, final IPentahoSession session) {

        Node node = dialNode.selectSingleNode("units"); //$NON-NLS-1$
        if (node != null) {
            String units = node.getText();
            widgetDefinition.setUnits(units);
        }

        // set the background Paint
        Paint paint = JFreeChartEngine.getPaint(dialNode.selectSingleNode("background-color")); //$NON-NLS-1$
        if (paint == null) {
            Element backgroundNode = (Element) dialNode.selectSingleNode("chart-background"); //$NON-NLS-1$
            if (backgroundNode != null) {
                String backgroundType = backgroundNode.attributeValue("type"); //$NON-NLS-1$
                if ("texture".equals(backgroundType)) { //$NON-NLS-1$
                    paint = JFreeChartEngine.getTexturePaint(backgroundNode, width, height, session);
                } else if ("gradient".equals(backgroundType)) { //$NON-NLS-1$
                    paint = JFreeChartEngine.getGradientPaint(backgroundNode, width, height);
                }
            }
        } else {
            // log a deprecation warning for background-color ...
            DialWidgetDefinition.getLogger().warn(Messages.getInstance().getString("CHART.WARN_DEPRECATED_PROPERTY", //$NON-NLS-1$
                    "background-color", "chart-background")); //$NON-NLS-1$ //$NON-NLS-2$    
            DialWidgetDefinition.getLogger().warn(
                    Messages.getInstance().getString("CHART.WARN_PROPERTY_WILL_NOT_VALIDATE", "background-color")); //$NON-NLS-1$ //$NON-NLS-2$     
        }

        if (paint != null) {
            widgetDefinition.setChartBackgroundPaint(paint);
        }

        // set the dial background Paint
        paint = JFreeChartEngine.getPaint(dialNode.selectSingleNode("plot-background-color")); //$NON-NLS-1$
        if (paint == null) {
            Element backgroundNode = (Element) dialNode.selectSingleNode("plot-background"); //$NON-NLS-1$
            if (backgroundNode != null) {
                String backgroundType = backgroundNode.attributeValue("type"); //$NON-NLS-1$
                if ("texture".equals(backgroundType)) { //$NON-NLS-1$
                    paint = JFreeChartEngine.getTexturePaint(backgroundNode, width, height, session);
                } else if ("gradient".equals(backgroundType)) { //$NON-NLS-1$
                    paint = JFreeChartEngine.getGradientPaint(backgroundNode, width, height);
                }
            }
        } else {
            // log a deprecation warning for plot-background-color ...
            DialWidgetDefinition.getLogger().warn(Messages.getInstance().getString("CHART.WARN_DEPRECATED_PROPERTY", //$NON-NLS-1$
                    "plot-background-color", "plot-background")); //$NON-NLS-1$ //$NON-NLS-2$    
            DialWidgetDefinition.getLogger().warn(Messages.getInstance()
                    .getString("CHART.WARN_PROPERTY_WILL_NOT_VALIDATE", "plot-background-color")); //$NON-NLS-1$ //$NON-NLS-2$     
        }

        if (paint != null) {
            widgetDefinition.setPlotBackgroundPaint(paint);
        }

        // set the needle Paint
        paint = JFreeChartEngine.getPaint(dialNode.selectSingleNode("needle-color")); //$NON-NLS-1$
        if (paint != null) {
            widgetDefinition.setNeedlePaint(paint);
        }

        // set the tick Paint
        paint = JFreeChartEngine.getPaint(dialNode.selectSingleNode("tick-color")); //$NON-NLS-1$
        if (paint != null) {
            widgetDefinition.setTickPaint(paint);
        }

        Node tmpNode = dialNode.selectSingleNode("tick-interval"); //$NON-NLS-1$
        if (tmpNode != null) {
            widgetDefinition.setTickSize(Integer.parseInt(dialNode.selectSingleNode("tick-interval").getText())); //$NON-NLS-1$
        }

        // set the value Paint
        paint = JFreeChartEngine.getPaint(dialNode.selectSingleNode("value-color")); //$NON-NLS-1$
        if (paint != null) {
            widgetDefinition.setValuePaint(paint);
        }

        // TODO get this from the XML document
        widgetDefinition.setDialShape(DialShape.CHORD);

        Node titleFontNode = dialNode.selectSingleNode("title-font"); //$NON-NLS-1$
        if (titleFontNode != null) {
            Node fontNode = titleFontNode.selectSingleNode("font"); //$NON-NLS-1$
            if (fontNode != null) {
                String titleFontStr = fontNode.getText().trim();
                if (!"".equals(titleFontStr)) { //$NON-NLS-1$
                    Node titleFontSizeNode = titleFontNode.selectSingleNode("size"); //$NON-NLS-1$
                    int size = titleFontSizeNode != null ? Integer.parseInt(titleFontSizeNode.getText()) : 12;
                    widgetDefinition.setTitleFont(new Font(titleFontStr, Font.BOLD, size));
                }
            } else {
                String titleFontStr = titleFontNode.getText().trim();
                if (!"".equals(titleFontStr)) { //$NON-NLS-1$
                    widgetDefinition.setTitleFont(new Font(titleFontStr, Font.ITALIC, 24));
                }
            }
        }

        Node valueFontNode = dialNode.selectSingleNode("domain-tick-font"); //$NON-NLS-1$
        if (valueFontNode != null) {
            Node fontNode = valueFontNode.selectSingleNode("font"); //$NON-NLS-1$
            if (fontNode != null) {
                String fontStr = fontNode.getText().trim();
                if (!"".equals(fontStr)) { //$NON-NLS-1$
                    Node valueFontSizeNode = valueFontNode.selectSingleNode("size"); //$NON-NLS-1$
                    int size = valueFontSizeNode != null ? Integer.parseInt(valueFontSizeNode.getText()) : 12;
                    widgetDefinition.setValueFont(new Font(fontStr, Font.BOLD, size));
                }
            } else {
                String fontStr = valueFontNode.getText().trim();
                if (!"".equals(fontStr)) { //$NON-NLS-1$
                    widgetDefinition.setValueFont(new Font(fontStr, Font.ITALIC, 24));
                }
            }
        }

        // set any intervals that are defined in the document

        // A list of interval nodes should not be allowed to exist as a child of the main XML element (for XML schema
        // to
        // be well constructed and validate the XML .
        // We have deprecated <interval> as a child of the main node , and now require an <intervals> parent node
        // under which <intervals> can exist.

        List intervals = dialNode.selectNodes("interval"); //$NON-NLS-1$

        if ((intervals == null) || (intervals.isEmpty())) {
            Node intervalsNode = dialNode.selectSingleNode("intervals"); //$NON-NLS-1$
            if (intervalsNode != null) {
                intervals = intervalsNode.selectNodes("interval"); //$NON-NLS-1$
            }
        } else {
            // log a deprecation warning for this property...
            DialWidgetDefinition.getLogger()
                    .warn(Messages.getInstance().getString("CHART.WARN_DEPRECATED_CHILD", "interval", "intervals")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$    
            DialWidgetDefinition.getLogger()
                    .warn(Messages.getInstance().getString("CHART.WARN_PROPERTY_WILL_NOT_VALIDATE", "interval")); //$NON-NLS-1$ //$NON-NLS-2$     
        }

        if (intervals != null) {

            Iterator intervalIterator = intervals.iterator();
            while (intervalIterator.hasNext()) {
                // get the interval node
                Node intervalNode = (Node) intervalIterator.next();

                // get the interval name
                String label = intervalNode.selectSingleNode("label").getText(); //$NON-NLS-1$

                // get the range of the interval
                double minimum = Double.parseDouble(intervalNode.selectSingleNode("minimum").getText()); //$NON-NLS-1$
                double maximum = Double.parseDouble(intervalNode.selectSingleNode("maximum").getText()); //$NON-NLS-1$
                Range range = new Range(minimum, maximum);

                Paint backgroundPaint = JFreeChartEngine.getPaint(intervalNode.selectSingleNode("color")); //$NON-NLS-1$
                if (backgroundPaint == null) {
                    Element backgroundNode = (Element) intervalNode.selectSingleNode("interval-background"); //$NON-NLS-1$
                    if (backgroundNode != null) {
                        String backgroundType = backgroundNode.attributeValue("type"); //$NON-NLS-1$
                        if ("texture".equals(backgroundType)) { //$NON-NLS-1$
                            backgroundPaint = JFreeChartEngine.getTexturePaint(backgroundNode, width, height,
                                    session);
                        } else if ("gradient".equals(backgroundType)) { //$NON-NLS-1$
                            backgroundPaint = JFreeChartEngine.getGradientPaint(backgroundNode, width, height);
                        }
                    }
                }

                // get the text color of the interval
                String textColor = intervalNode.selectSingleNode("text-color").getText(); //$NON-NLS-1$
                Stroke outlineStroke;
                if (intervalNode.selectSingleNode("stroke-width") != null) { //$NON-NLS-1$
                    outlineStroke = new BasicStroke(
                            Float.parseFloat(intervalNode.selectSingleNode("stroke-width").getText())); //$NON-NLS-1$
                } else {
                    outlineStroke = new BasicStroke();
                }
                Paint outlinePaint = JFreeChartEngine.getPaint(textColor);

                // create the interval object
                MeterInterval interval = new MeterInterval(label, range, outlinePaint, outlineStroke,
                        backgroundPaint);

                // add the interval to the widget
                widgetDefinition.addInterval(interval);
            }
        }

        // get the chart subtitles

        // A list of <subtitle> nodes should not be allowed to exist as a child of the main XML element (for XML schema
        // to
        // be well constructed and validate the XML .
        // We have deprecated <subtitle> as a child of the main node , and now require a <subtitles> parent node
        // under which <subtitle> can exist.

        List subtitles = dialNode.selectNodes(ChartDefinition.SUBTITLE_NODE_NAME);

        if ((subtitles == null) || (subtitles.isEmpty())) {
            Node subTitlesNode = dialNode.selectSingleNode(ChartDefinition.SUBTITLES_NODE_NAME);
            if (subTitlesNode != null) {
                subtitles = subTitlesNode.selectNodes(ChartDefinition.SUBTITLE_NODE_NAME);
            }
        } else {
            // log a deprecation warning for this property...
            DialWidgetDefinition.getLogger().warn(Messages.getInstance().getString("CHART.WARN_DEPRECATED_CHILD", //$NON-NLS-1$
                    ChartDefinition.SUBTITLE_NODE_NAME, ChartDefinition.SUBTITLES_NODE_NAME));
            DialWidgetDefinition.getLogger().warn(Messages.getInstance()
                    .getString("CHART.WARN_PROPERTY_WILL_NOT_VALIDATE", ChartDefinition.SUBTITLE_NODE_NAME)); //$NON-NLS-1$  
        }

        if (subtitles != null) {
            widgetDefinition.addSubTitles(subtitles);
        }

    }

    public void setUnits(final String units) {
        this.units = units;
    }

    public String getUnits() {
        return units;
    }

    private void setDataByColumn(final IPentahoResultSet data) {
        setDataByRow(PentahoDataTransmuter.pivot(data));
    }

    private void setDataByRow(final IPentahoResultSet data) {

        if (data == null) {
            noDataMessage = Messages.getInstance().getString("CHART.USER_NO_DATA_AVAILABLE"); //$NON-NLS-1$
            return;
        }

        Object[] rowData = data.next();

        List<Number> numericRowData = DataUtilities.toNumbers(rowData, LocaleHelper.getNumberFormat(),
                LocaleHelper.getCurrencyFormat());

        double newValue = numericRowData.get(0).doubleValue();

        // Do we have a value, minimum and maximum?
        if (rowData.length >= 3) {

            this.setMinimum(numericRowData.get(1).doubleValue());
            this.setMaximum(numericRowData.get(2).doubleValue());

        } else {

            deriveMinMax(newValue);

        }

        this.setValue(newValue);

    }

    public void deriveMinMax(final double value) {

        double min = 0;
        double max = 100;
        Node node = attributes.selectSingleNode("range-limited"); //$NON-NLS-1$
        rangeLimited = (node == null) || ("true".equalsIgnoreCase(node.getText())); //$NON-NLS-1$

        max = 0.1;
        double absValue = Math.abs(value);
        // based on the current value, to to select some sensible min and
        // max values
        while (max < absValue) {
            max *= 2;
            if (max < absValue) {
                min *= 2.5;
                max *= 2.5;
            }
            if (max < absValue) {
                min *= 2;
                max *= 2;
            }
        }
        if (value > 0) {
            min = 0;
        } else {
            min = -max;
        }
        setMaximum(max);
        setMinimum(min);
    }

    /**
     * Add an interval (MeterInterval) to the dial definition. The interval defines a range and how it should be
     * painted.
     * <p/>
     * The dial images here have three intervals. The lowest interval has a minimum of 0 and a maximum of 30.
     * <p/>
     * Intervals have a color. In this image the lowest interval color is set to red. <br/>
     * <img src="doc-files/DialWidgetDefinition-5.png">
     * <p/>
     * Intervals have a text color. In this image the lowest interval text color is set to red. This affects the
     * outer rim, the interval value text <br/>
     * <img src="doc-files/DialWidgetDefinition-6.png">
     * 
     * @param interval
     *          A MeterInterval that defines an interval (range) on the dial
     */
    public void addInterval(final MeterInterval interval) {
        intervals.add(interval);
        Range range = interval.getRange();
        double min = range.getLowerBound();
        double max = range.getUpperBound();
        if (rangeLimited && (intervals.size() == 1)) {
            setMinimum(min);
            setMaximum(max);
        } else {
            if (min < getMinimum()) {
                setMinimum(min);
            }
            if (max > getMaximum()) {
                setMaximum(max);
            }
        }
    }

    /**
     * Sets the value to be displayed on the dial image
     * 
     * @param value
     *          The value to be displayed
     */

    public void setValue(final double value) {
        setValue(new Double(value));
        if (rangeLimited) {
            if (value < getMinimum()) {
                setValue(getMinimum());
            } else if (value > getMaximum()) {
                setValue(getMaximum());
            }
        } else {
            if (value < getMinimum()) {
                setMinimum(value);
            } else if (value > getMaximum()) {
                setMaximum(value);
            }
        }
    }

    /**
     * Return the java.awt.Paint object to be used to paint the backound of the dial.
     * 
     * @return The Paint to be used
     */
    public Paint getPlotBackgroundPaint() {
        return plotBackgroundPaint;
    }

    /**
     * Return the java.awt.Paint object to be used to paint the backound of the dial.
     * <p/>
     * In this image the background paint has been set to red <br/>
     * <img src="doc-files/DialWidgetDefinition-2.png">
     * 
     * @return The Paint to used for the background of the image
     */
    public void setPlotBackgroundPaint(final Paint plotBackgroundPaint) {
        this.plotBackgroundPaint = plotBackgroundPaint;
    }

    /**
     * Return the java.awt.Paint used to paint the needle of the dial image
     * 
     * @return The Paint to use for the needle of this dial
     */
    public Paint getNeedlePaint() {
        return needlePaint;
    }

    /**
     * Sets the java.awt.Paint object to be used to paint the needle of the dial image.
     * <p/>
     * In this image the needle paint has been set to red. <br/>
     * <img src="doc-files/DialWidgetDefinition-4.png">
     * 
     * @param needlePaint
     *          The Paint to use for ths needle of this dial
     */
    public void setNeedlePaint(final Paint needlePaint) {
        this.needlePaint = needlePaint;
    }

    /**
     * Return the shape to be used for the dial.
     * 
     * @return DialShape The DialShape for this dial
     */
    public DialShape getDialShape() {
        return dialShape;
    }

    /**
     * Return the java.awt.Font to be used to display the dial title
     * 
     * @return Font The Font for the title of this dial
     */
    public Font getTitleFont() {
        if (titleFont != null) {
            return titleFont;
        } else {
            return new Font("sans-serif", Font.PLAIN, 14); //$NON-NLS-1$
        }
    }

    public void setTitleFont(final Font tFont) {
        titleFont = tFont;

    }

    /**
     * Sets the shape to be used for the dial. This affects the area of dial outside the range that the needle
     * covers.
     * <table>
     * <tr>
     * <td><center>CIRCLE</center></td>
     * <td><center>CHORD</center></td>
     * <td><center>PIE</center></td>
     * </tr>
     * <tr>
     * <td><img src="doc-files/DialWidgetDefinition-3.png"></td>
     * <td><img src="doc-files/DialWidgetDefinition-8.png"></td>
     * <td><img src="doc-files/DialWidgetDefinition-9.png"></td>
     * </tr>
     * </table>
     * 
     * @param dialShape
     *          The shape for this dial
     */
    public void setDialShape(final DialShape dialShape) {
        this.dialShape = dialShape;
    }

    /**
     * Return a list of the intervals for the dial. Each object in the list is a MeterInterval object.
     * 
     * @return List The list of MeterInterval objects for this dial
     */

    public List getIntervals() {
        return intervals;
    }

    public Paint[] getPaintSequence() {
        return null;
    }

    public Image getPlotBackgroundImage() {
        return null;
    }

    public List getSubtitles() {
        return subTitles;
    }

    public void addSubTitles(final List subTitleNodes) {
        if (subTitleNodes != null) {
            Iterator iter = subTitleNodes.iterator();
            while (iter.hasNext()) {
                addSubTitle(((Node) iter.next()).getText());
            }
        }
    }

    public void addSubTitle(final String subTitle) {
        subTitles.add(subTitle);
    }

    public Paint getChartBackgroundPaint() {
        // TODO Auto-generated method stub
        return chartBackgroundPaint;
    }

    public Image getChartBackgroundImage() {
        // TODO Auto-generated method stub
        return null;
    }

    public boolean isBorderVisible() {
        // TODO Auto-generated method stub
        return false;
    }

    public Paint getBorderPaint() {
        // TODO Auto-generated method stub
        return null;
    }

    public RectangleEdge getTitlePosition() {
        return titlePosition;
    }

    public RectangleEdge getLegendPosition() {
        return legendPosition;
    }

    /**
     * @param chartBackgroundPaint
     *          The chartBackgroundPaint to set.
     */
    public void setChartBackgroundPaint(final Paint chartBackgroundPaint) {
        this.chartBackgroundPaint = chartBackgroundPaint;
    }

    public int getHeight() {
        // TODO Auto-generated method stub
        return 200;
    }

    public int getWidth() {
        // TODO Auto-generated method stub
        return 200;
    }

    public String getTitle() {
        return null;
    }

    public boolean isLegendIncluded() {
        // TODO Auto-generated method stub
        return false;
    }

    public boolean isThreeD() {
        // TODO Auto-generated method stub
        return false;
    }

    public Paint getValuePaint() {
        return valuePaint;
    }

    public Paint getTickPaint() {
        return tickPaint;
    }

    public int getTickSize() {
        return tickSize;
    }

    public void setValuePaint(final Paint valuePaint) {
        this.valuePaint = valuePaint;
    }

    public void setTickPaint(final Paint tickPaint) {
        this.tickPaint = tickPaint;
    }

    public void setTickSize(final int tickSize) {
        this.tickSize = tickSize;
    }

    @Override
    public Font getValueFont() {
        return valueFont;
    }

    public void setValueFont(final Font valueFont) {
        this.valueFont = valueFont;
    }

    public boolean isDisplayLabels() {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * Return the java.awt.Font to be used to display the legend items
     * 
     * @return Font The font for the legend items
     */
    public Font getLegendFont() {
        // TODO Auto-generated method stub
        return legendFont;
    }

    /**
     * Set java.awt.Font to be used to display the legend items
     * 
     * @param Font
     *          The java.awt.Font for the legend items
     */
    public void setLegendFont(final Font legendFont) {
        this.legendFont = legendFont;
    }

    public void setLegendFont(final Node legendFontNode) {
        Font font = JFreeChartEngine.getFont(legendFontNode);
        if (font != null) {
            setLegendFont(font);
        }
    }

    public void setLegendBorderVisible(final Node legendBorderVisibleNode) {
        if (legendBorderVisibleNode != null) {
            boolean legBorderVisible = (new Boolean(legendBorderVisibleNode.getText())).booleanValue();
            setLegendBorderVisible(legBorderVisible);
        }
    }

    /**
     * @param boolean legendBorderVisible Set the visibility of the legend border.
     */
    public void setLegendBorderVisible(final boolean legendBorderVisible) {
        this.legendBorderVisible = legendBorderVisible;
    }

    /**
     * Return the boolen that states if the legend border is visible
     * 
     * @return boolean Is the legend border visible
     */
    public boolean isLegendBorderVisible() {
        return legendBorderVisible;
    }

    public Float getBackgroundAlpha() {
        return backgroundAlpha;
    }

    public void setBackgroundAlpha(Node backgroundAlphaNode) {
        if (backgroundAlphaNode != null) {
            Float backgroundAlphaValue = new Float(backgroundAlphaNode.getText());
            this.backgroundAlpha = backgroundAlphaValue;
        }

    }

    public Float getForegroundAlpha() {
        return foregroundAlpha;
    }

    public void setForegroundAlpha(Node foregroundAlphaNode) {
        if (foregroundAlphaNode != null) {
            Float foregroundAlphaValue = new Float(foregroundAlphaNode.getText());
            this.foregroundAlpha = foregroundAlphaValue;
        }

    }

}