/* ================================================================
* Cewolf : Chart enabling Web Objects Framework
* ================================================================
*
* Project Info: http://cewolf.sourceforge.net
* Project Lead: Guido Laures (guido@laures.de);
*
* (C) Copyright 2002, by Guido Laures
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
package de.laures.cewolf.taglib;
import java.awt.Image;
import java.awt.Paint;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.*;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.general.Dataset;
import org.jfree.ui.RectangleEdge;
import de.laures.cewolf.ChartHolder;
import de.laures.cewolf.ChartPostProcessor;
import de.laures.cewolf.ChartValidationException;
import de.laures.cewolf.DatasetProduceException;
import de.laures.cewolf.PostProcessingException;
import de.laures.cewolf.event.ChartImageRenderListener;
import de.laures.cewolf.util.ImageHelper;
import de.laures.cewolf.util.RenderedImage;
/**
* Serializable implementaton of a ChartDefinition.
* @author glaures
* @see de.laures.cewolf.ChartHolder
*/
public abstract class AbstractChartDefinition
implements ChartHolder, Serializable, ChartImageRenderListener {
protected String title;
protected String xAxisLabel, yAxisLabel;
protected String type;
protected boolean xAxisInteger = false, yAxisInteger = false;
protected boolean xTickMarksVisible = true, yTickMarksVisible = true;
protected boolean xTickLabelsVisible = true, yTickLabelsVisible = true;
protected boolean borderVisible = false;
protected boolean plotBorderVisible = true;
private boolean antialias = true;
private String background;
private float backgroundImageAlpha = 1.0f;
private Paint backgroundPaint, plotBackgroundPaint, borderPaint, plotBorderPaint;
private int legendAnchor = TaglibConstants.ANCHOR_SOUTH;
protected boolean showLegend = true;
private List postProcessors = new ArrayList();
private List postProcessorsParams = new ArrayList();
private JFreeChart chart;
protected abstract JFreeChart produceChart() throws DatasetProduceException, ChartValidationException;
//gets first legend in the list
public LegendTitle getLegend()
{
//i need to find the legend now.
LegendTitle legend = null;
List subTitles = chart.getSubtitles();
Iterator iter = subTitles.iterator();
while (iter.hasNext())
{
Object o = iter.next();
if (o instanceof LegendTitle)
{
legend = (LegendTitle) o;
break;
}
}
return legend;
}
//removes first legend in the list
public void removeLegend()
{
List subTitles = chart.getSubtitles();
Iterator iter = subTitles.iterator();
while (iter.hasNext())
{
Object o = iter.next();
if (o instanceof LegendTitle)
{
iter.remove();
break;
}
}
}
/**
* This method triggers the dataset and chart production. It is only
* from outside if there is no cached image available in the the image cache.
*/
public JFreeChart getChart() throws DatasetProduceException, ChartValidationException, PostProcessingException {
if (chart == null) {
chart = produceChart();
chart.setAntiAlias(antialias);
if (background != null) {
Image image = ImageHelper.loadImage(background);
chart.setBackgroundImage(image);
chart.setBackgroundImageAlpha(backgroundImageAlpha);
}
if (backgroundPaint != null) {
chart.setBackgroundPaint(backgroundPaint);
}
if (plotBackgroundPaint != null) {
chart.getPlot().setBackgroundPaint(plotBackgroundPaint);
}
if (borderPaint != null) {
chart.setBorderPaint(borderPaint);
}
if (plotBorderPaint != null) {
chart.getPlot().setOutlinePaint(plotBorderPaint);
}
chart.setBorderVisible(borderVisible);;
chart.getPlot().setOutlineVisible(plotBorderVisible);;
if (showLegend) {
LegendTitle legend = this.getLegend();
switch (legendAnchor)
{
case TaglibConstants.ANCHOR_NORTH :
legend.setPosition(RectangleEdge.TOP);
break;
case TaglibConstants.ANCHOR_WEST :
legend.setPosition(RectangleEdge.LEFT);
break;
case TaglibConstants.ANCHOR_EAST :
legend.setPosition(RectangleEdge.RIGHT);
break;
default :
legend.setPosition(RectangleEdge.BOTTOM);
}
} else {
this.removeLegend();
}
Plot plot = chart.getPlot();
if (plot instanceof CategoryPlot) {
CategoryPlot cplot = (CategoryPlot) plot;
for (int i=0; i<cplot.getRangeAxisCount(); i++) {
ValueAxis axis = cplot.getRangeAxis(i);
if (axis instanceof NumberAxis) {
if (yAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(yTickMarksVisible);
axis.setTickLabelsVisible(yTickLabelsVisible);
}
}
for (int i=0; i<cplot.getDomainAxisCount(); i++) {
cplot.getDomainAxis(i).setTickMarksVisible(xTickMarksVisible);
cplot.getDomainAxis(i).setTickLabelsVisible(xTickLabelsVisible);
}
} else if (plot instanceof FastScatterPlot) {
FastScatterPlot fsplot = (FastScatterPlot) plot;
ValueAxis axis = fsplot.getDomainAxis();
if (axis instanceof NumberAxis) {
if (xAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(xTickMarksVisible);
axis.setTickLabelsVisible(xTickLabelsVisible);
}
axis = fsplot.getRangeAxis();
if (axis instanceof NumberAxis) {
if (yAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(yTickMarksVisible);
}
} else if (plot instanceof ThermometerPlot) {
ValueAxis axis = ((ThermometerPlot) plot).getRangeAxis();
if (axis instanceof NumberAxis) {
if (yAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(yTickMarksVisible);
axis.setTickLabelsVisible(yTickLabelsVisible);
}
} else if (plot instanceof XYPlot) {
XYPlot xyplot = (XYPlot) plot;
for (int i=0; i<xyplot.getRangeAxisCount(); i++) {
ValueAxis axis = xyplot.getRangeAxis(i);
if (axis instanceof NumberAxis) {
if (yAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(yTickMarksVisible);
axis.setTickLabelsVisible(yTickLabelsVisible);
}
}
for (int i=0; i<xyplot.getDomainAxisCount(); i++) {
ValueAxis axis = xyplot.getDomainAxis(i);
if (axis instanceof NumberAxis) {
if (xAxisInteger)
((NumberAxis) axis).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
if (axis != null) {
axis.setTickMarksVisible(xTickMarksVisible);
axis.setTickLabelsVisible(xTickLabelsVisible);
}
}
}
// postProcessing
for (int i = 0; i < postProcessors.size(); i++) {
ChartPostProcessor cpp = (ChartPostProcessor) postProcessors.get(i);
try {
cpp.processChart(chart, (Map) postProcessorsParams.get(i));
} catch (Throwable t) {
t.printStackTrace();
throw new PostProcessingException(t.getClass().getName() + " raised by post processor '" +
cpp + "'.\nPost processing of this post processor " + "has been ignored.");
}
}
}
return chart;
}
/**
* Sets the antialias.
* @param antialias The antialias to set
*/
public void setAntialias (boolean antialias) {
this.antialias = antialias;
}
/**
* Sets the background.
* @param background The background to set
*/
public void setBackground (String background) {
this.background = background;
}
/**
* Sets the backgroundImageAlpha.
* @param backgroundImageAlpha The backgroundImageAlpha to set
*/
public void setBackgroundImageAlpha (float backgroundImageAlpha) {
this.backgroundImageAlpha = backgroundImageAlpha;
}
/**
* Sets the legendAnchor.
* @param legendAnchor The legendAnchor to set
*/
public void setLegendAnchor (int legendAnchor) {
this.legendAnchor = legendAnchor;
}
/**
* Sets the background paint.
* @param paint The background paint to set
*/
public void setBackgroundPaint (Paint paint) {
this.backgroundPaint = paint;
}
/**
* Sets the plot's background paint.
* @param paint The plot's background paint to set
*/
public void setPlotBackgroundPaint (Paint paint) {
this.plotBackgroundPaint = paint;
}
/**
* Sets the showLegend.
* @param showLegend The showLegend to set
*/
public void setShowLegend (boolean showLegend) {
this.showLegend = showLegend;
}
/**
* Sets the title.
* @param title The title to set
*/
public void setTitle (String title) {
this.title = title;
}
/**
* Sets the type.
* @param type The type to set
*/
public void setType (String type) {
this.type = type;
}
/**
* Sets the xAxisLabel.
* @param xAxisLabel The xAxisLabel to set
*/
public void setXAxisLabel (String xAxisLabel) {
this.xAxisLabel = xAxisLabel;
}
/**
* Sets the yAxisLabel.
* @param yAxisLabel The yAxisLabel to set
*/
public void setYAxisLabel (String yAxisLabel) {
this.yAxisLabel = yAxisLabel;
}
/**
* Whether the domain (X) axis should show integer values only.
*/
public void setXaxisinteger (boolean xAxisInteger) {
this.xAxisInteger = xAxisInteger;
}
/**
* Whether the range (Y) axis should show integer values only.
*/
public void setYaxisinteger (boolean yAxisInteger) {
this.yAxisInteger = yAxisInteger;
}
/**
* Whether the domain (X) axis should show any tick marks.
*/
public void setXtickmarksvisible (boolean xTickMarksVisible) {
this.xTickMarksVisible = xTickMarksVisible;
}
/**
* Whether the range (Y) axis should show any tick marks.
*/
public void setYtickmarksvisible (boolean yTickMarksVisible) {
this.yTickMarksVisible = yTickMarksVisible;
}
/**
* Whether the domain (X) axis should show any tick labels.
*/
public void setXticklabelsvisible (boolean xTickLabelsVisible) {
this.xTickLabelsVisible = xTickLabelsVisible;
}
/**
* Whether the range (Y) axis should show any tick labels.
*/
public void setYticklabelsvisible (boolean yTickLabelsVisible) {
this.yTickLabelsVisible = yTickLabelsVisible;
}
/**
* Whether the chart is drawn with a border.
*/
public void setBorderVisible (boolean borderVisible) {
this.borderVisible = borderVisible;
}
/**
* Whether the plot is drawn with a border.
*/
public void setPlotBorderVisible (boolean plotBorderVisible) {
this.plotBorderVisible = plotBorderVisible;
}
/**
* Sets the chart border paint.
*/
public void setBorderPaint (Paint paint) {
this.borderPaint = paint;
}
/**
* Sets the plot border paint.
*/
public void setPlotBorderPaint (Paint paint) {
this.plotBorderPaint = paint;
}
public void addPostProcessor (ChartPostProcessor cpp) {
postProcessors.add(cpp);
}
public void addPostProcessorParams (Map params) {
postProcessorsParams.add(params);
}
/**
* Callback right after a new image gets rendered.
* Implemented so if postprocessors implement the ImageRenderListener interface then they will be called back also
*
* @param renderedImage The fresh image just got rendered
*/
public void onImageRendered (RenderedImage renderedImage) {
// if the postprocessor implements ImageRenderListener interface call it!
for (int i = 0; i < postProcessors.size(); i++) {
ChartPostProcessor cpp = (ChartPostProcessor)postProcessors.get(i);
if (cpp instanceof ChartImageRenderListener) {
((ChartImageRenderListener) cpp).onImageRendered(renderedImage);
}
}
}
}