/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.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 Lesser General Public License for more details.
*
* Copyright (c) 2006 - 2009 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.plugin.jfreereport.reportcharts;
import java.awt.Color;
import java.awt.Font;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.Plot;
import org.jfree.data.general.Dataset;
import org.jfree.data.general.PieDataset;
import org.jfree.util.Rotation;
import org.pentaho.reporting.libraries.base.util.StringUtils;
public class PieChartExpression extends AbstractChartExpression
{
private static final int EXPLODE_VALUE = 0;
private static final int EXPLODE_MIN = 1;
private static final int EXPLODE_MAX = 2;
private static final long serialVersionUID = 5755617219149952355L;
private boolean rotationClockwise;
private String explodeSegment;
private Double explodePct;
private boolean ignoreNulls;
private boolean ignoreZeros;
private String pieLabelFormat;
private boolean circular;
private String pieLegendLabelFormat;
private Color shadowPaint;
private Double shadowXOffset;
private Double shadowYOffset;
public PieChartExpression()
{
rotationClockwise = true;
pieLegendLabelFormat = StandardPieSectionLabelGenerator.DEFAULT_SECTION_LABEL_FORMAT;
pieLabelFormat = "{2}";
ignoreZeros = true;
ignoreNulls = true;
circular = true;
setItemsLabelVisible(Boolean.TRUE);
}
public Color getShadowPaint()
{
return shadowPaint;
}
public void setShadowPaint(final Color shadowPaint)
{
this.shadowPaint = shadowPaint;
}
public Double getShadowXOffset()
{
return shadowXOffset;
}
public void setShadowXOffset(final Double shadowXOffset)
{
this.shadowXOffset = shadowXOffset;
}
public Double getShadowYOffset()
{
return shadowYOffset;
}
public void setShadowYOffset(final Double shadowYOffset)
{
this.shadowYOffset = shadowYOffset;
}
public boolean isRotationClockwise()
{
return rotationClockwise;
}
public void setRotationClockwise(final boolean value)
{
rotationClockwise = value;
}
public boolean isIgnoreNulls()
{
return ignoreNulls;
}
public void setIgnoreNulls(final boolean value)
{
ignoreNulls = value;
}
public boolean isIgnoreZeros()
{
return ignoreZeros;
}
public void setIgnoreZeros(final boolean value)
{
ignoreZeros = value;
}
public String getExplodeSegment()
{
return explodeSegment;
}
public void setExplodeSegment(final String value)
{
explodeSegment = value;
}
public Double getExplodePct()
{
return explodePct;
}
public void setExplodePct(final Double value)
{
explodePct = value;
}
public String getPieLabelFormat()
{
return pieLabelFormat;
}
public void setPieLabelFormat(final String value)
{
pieLabelFormat = value;
}
public String getPieLegendLabelFormat()
{
return pieLegendLabelFormat;
}
public void setPieLegendLabelFormat(final String value)
{
pieLegendLabelFormat = value;
}
public boolean getIsCircular()
{
return circular;
}
public void setCircular(final boolean value)
{
circular = value;
}
protected JFreeChart computeChart(final Dataset dataset)
{
PieDataset pieDataset = null;
if (dataset instanceof PieDataset)
{
pieDataset = (PieDataset) dataset;
}
if (isThreeD())
{
return ChartFactory.createPieChart3D(computeTitle(), pieDataset, isShowLegend(), false, false);
}
else
{
return ChartFactory.createPieChart(computeTitle(), pieDataset, isShowLegend(), false, false);
}
}
protected void configureExplode(final PiePlot pp)
{
final PieDataset pieDS = pp.getDataset();
final int explodeType = computeExplodeType();
if (explodeType == EXPLODE_VALUE)
{
try
{
final int actualSegment = Integer.parseInt(explodeSegment);
if (actualSegment >= 0)
{
pp.setExplodePercent(pieDS.getKey(actualSegment), explodePct.doubleValue());
}
}
catch (Exception ignored)
{
}
return;
}
// Calculate min and max...
if (pieDS != null)
{
final int itemCount = pieDS.getItemCount();
Number maxNum = new Double(Integer.MIN_VALUE);
Number minNum = new Double(Integer.MAX_VALUE);
int maxSegment = -1;
int minSegment = -1;
for (int i = 0; i < itemCount; i++)
{
final Number nbr = pieDS.getValue(i);
if (nbr.doubleValue() > maxNum.doubleValue())
{
maxNum = nbr;
maxSegment = i;
}
if (nbr.doubleValue() < minNum.doubleValue())
{
minNum = nbr;
minSegment = i;
}
}
if (explodeType == EXPLODE_MIN)
{ //$NON-NLS-1$
if (minSegment >= 0)
{
pp.setExplodePercent(pieDS.getKey(minSegment), explodePct.doubleValue());
}
}
else
{
if (maxSegment >= 0)
{
pp.setExplodePercent(pieDS.getKey(maxSegment), explodePct.doubleValue());
}
}
}
}
private int computeExplodeType()
{
if ("minValue".equals(explodeSegment))
{
return EXPLODE_MIN;
}
else if ("maxValue".equals(explodeSegment))
{
return EXPLODE_MAX;
}
return EXPLODE_VALUE;
}
protected void configureChart(final JFreeChart chart)
{
super.configureChart(chart);
final Plot plot = chart.getPlot();
final PiePlot pp = (PiePlot) plot;
final PieDataset pieDS = pp.getDataset();
pp.setDirection(rotationClockwise ? Rotation.CLOCKWISE : Rotation.ANTICLOCKWISE);
if ((explodeSegment != null) && (explodePct != null))
{
configureExplode(pp);
}
if (StringUtils.isEmpty(getTooltipFormula()) == false)
{
pp.setToolTipGenerator(new FormulaPieTooltipGenerator(getRuntime(), getTooltipFormula()));
}
if (StringUtils.isEmpty(getUrlFormula()) == false)
{
pp.setURLGenerator(new FormulaPieURLGenerator(getRuntime(), getUrlFormula()));
}
pp.setIgnoreNullValues(ignoreNulls);
pp.setIgnoreZeroValues(ignoreZeros);
if (Boolean.FALSE.equals(getItemsLabelVisible()))
{
pp.setLabelGenerator(null);
}
else
{
final StandardPieSectionLabelGenerator labelGen = new StandardPieSectionLabelGenerator(pieLabelFormat);
pp.setLabelGenerator(labelGen);
final StandardPieSectionLabelGenerator legendGen = new StandardPieSectionLabelGenerator(pieLegendLabelFormat);
pp.setLegendLabelGenerator(legendGen);
}
if (StringUtils.isEmpty(getLabelFont()) == false)
{
pp.setLabelFont(Font.decode(getLabelFont()));
}
if (pieDS != null)
{
final String[] colors = getSeriesColor();
for (int i = 0; i < colors.length; i++)
{
if (i < pieDS.getItemCount())
{
pp.setSectionPaint(pieDS.getKey(i), parseColorFromString(colors[i]));
}
else
{
break;
}
}
}
if (shadowPaint != null)
{
pp.setShadowPaint(shadowPaint);
}
if (shadowXOffset != null)
{
pp.setShadowXOffset(shadowXOffset.doubleValue());
}
if (shadowYOffset != null)
{
pp.setShadowYOffset(shadowYOffset.doubleValue());
}
pp.setCircular(circular);
}
}