package org.jboss.seam.pdf.ui;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.jboss.seam.pdf.ITextUtils;
import org.jboss.seam.ui.graphicImage.GraphicImageResource;
import org.jboss.seam.ui.graphicImage.GraphicImageStore;
import org.jboss.seam.ui.graphicImage.GraphicImageStore.ImageWrapper;
import org.jboss.seam.ui.graphicImage.Image.Type;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.general.Dataset;
import com.lowagie.text.*;
import com.lowagie.text.pdf.DefaultFontMapper;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.AsianFontMapper;
public abstract class UIChart extends ITextComponent {
private Image image = null;
private JFreeChart chart = null;
private byte[] imageData;
private int height = 300;
private int width = 400;
private boolean legend;
private boolean is3D = false;
private String title;
private String borderBackgroundPaint;
private String borderPaint;
private String borderStroke;
private boolean borderVisible = true;
private String plotBackgroundPaint;
private Float plotBackgroundAlpha;
private Float plotForegroundAlpha;
private String plotOutlineStroke;
private String plotOutlinePaint;
protected Dataset dataset;
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return (String) valueBinding("title", title);
}
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return (Integer) valueBinding(FacesContext.getCurrentInstance(), "height", height);
}
public void setWidth(int width) {
this.width = width;
}
public int getWidth() {
return (Integer) valueBinding(FacesContext.getCurrentInstance(), "width", width);
}
public void setLegend(boolean legend) {
this.legend = legend;
}
public boolean getLegend() {
return (Boolean) valueBinding("legend", legend);
}
public void setIs3D(boolean is3D) {
this.is3D = true;
}
public boolean getIs3D() {
return (Boolean) valueBinding("is3D", is3D);
}
public void setBorderBackgroundPaint(String backgroundPaint) {
this.borderBackgroundPaint = backgroundPaint;
}
public String getBorderBackgroundPaint() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "borderBackgroundPaint", borderBackgroundPaint);
}
public void setBorderPaint(String borderPaint) {
this.borderPaint = borderPaint;
}
public String getBorderPaint() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "borderPaint", borderPaint);
}
public void setBorderStroke(String borderStroke) {
this.borderStroke = borderStroke;
}
public String getBorderStroke() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "borderStroke", borderStroke);
}
public void setBorderVisible(boolean borderVisible) {
this.borderVisible = borderVisible;
}
public boolean getBorderVisible() {
return (Boolean) valueBinding(FacesContext.getCurrentInstance(), "borderVisible", borderVisible);
}
public void setPlotBackgroundAlpha(Float plotBackgroundAlpha) {
this.plotBackgroundAlpha = plotBackgroundAlpha;
}
public Float getPlotBackgroundAlpha() {
return (Float) valueBinding(FacesContext.getCurrentInstance(), "plotBackgroundAlpha", plotBackgroundAlpha);
}
public void setPlotBackgroundPaint(String plotBackgroundPaint) {
this.plotBackgroundPaint = plotBackgroundPaint;
}
public String getPlotBackgroundPaint() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "plotBackgroundPaint", plotBackgroundPaint);
}
public void setPlotForegroundAlpha(Float plotForegroundAlpha) {
this.plotForegroundAlpha = plotForegroundAlpha;
}
public Float getPlotForegroundAlpha() {
return (Float) valueBinding(FacesContext.getCurrentInstance(), "plotForegroundAlpha", plotForegroundAlpha);
}
public void setPlotOutlinePaint(String plotOutlinePaint) {
this.plotOutlinePaint = plotOutlinePaint;
}
public String getPlotOutlinePaint() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "plotOutlinePaint", plotOutlinePaint);
}
public void setPlotOutlineStroke(String plotOutlineStroke) {
this.plotOutlineStroke = plotOutlineStroke;
}
public String getPlotOutlineStroke() {
return (String) valueBinding(FacesContext.getCurrentInstance(), "plotOutlineStroke", plotOutlineStroke);
}
public void setDataset(Dataset dataset) {
this.dataset = dataset;
}
public Dataset getDataset() {
return (Dataset) valueBinding(FacesContext.getCurrentInstance(), "dataset", dataset);
}
public void setChart(JFreeChart chart) {
this.chart = chart;
}
public JFreeChart getChart() {
return (JFreeChart) valueBinding(FacesContext.getCurrentInstance(), "chart", chart);
}
@Override
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
super.restoreState(context, values[0]);
height = (Integer) values[1];
width = (Integer) values[2];
borderBackgroundPaint = (String) values[3];
borderPaint = (String) values[4];
borderStroke = (String) values[5];
borderVisible = (Boolean) values[6];
plotBackgroundPaint = (String) values[7];
plotBackgroundAlpha = (Float) values[8];
plotForegroundAlpha = (Float) values[9];
plotOutlineStroke = (String) values[10];
plotOutlinePaint = (String) values[11];
title = (String) values[12];
is3D = (Boolean) values[13];
legend = (Boolean) values[14];
}
@Override
public Object saveState(FacesContext context) {
Object[] values = new Object[15];
values[0] = super.saveState(context);
values[1] = height;
values[2] = width;
values[3] = borderBackgroundPaint;
values[4] = borderPaint;
values[5] = borderStroke;
values[6] = borderVisible;
values[7] = plotBackgroundPaint;
values[8] = plotBackgroundAlpha;
values[9] = plotForegroundAlpha;
values[10] = plotOutlineStroke;
values[11] = plotOutlinePaint;
values[12] = title;
values[13] = is3D;
values[14] = legend;
return values;
}
public static Paint findColor(String name) {
if (name == null || name.length() == 0) {
return null;
}
UIComponent component = FacesContext.getCurrentInstance().getViewRoot()
.findComponent(name);
if (component != null) {
if (component instanceof UIColor) {
return ((UIColor) component).getPaint();
} else {
throw new RuntimeException();
}
}
return ITextUtils.colorValue(name);
}
public static Stroke findStroke(String id) {
if (id == null || id.length() == 0) {
return null;
}
UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent(id);
if (component instanceof UIStroke) {
return ((UIStroke) component).getStroke();
} else {
throw new RuntimeException();
}
}
public abstract JFreeChart createChart(FacesContext context);
@Override
public void createITextObject(FacesContext context) {
if (getBorderBackgroundPaint() != null) {
chart.setBackgroundPaint(findColor(getBorderBackgroundPaint()));
}
if (getBorderPaint() != null) {
chart.setBorderPaint(findColor(getBorderPaint()));
}
if (getBorderStroke() != null) {
chart.setBorderStroke(findStroke(getBorderStroke()));
}
chart.setBorderVisible(getBorderVisible());
configurePlot(chart.getPlot());
try {
UIDocument doc = (UIDocument) findITextParent(getParent(),
UIDocument.class);
if (doc != null) {
PdfWriter writer = (PdfWriter) doc.getWriter();
PdfContentByte cb = writer.getDirectContent();
PdfTemplate tp = cb.createTemplate(getWidth(), getHeight());
UIFont font = (UIFont) findITextParent(this, UIFont.class);
DefaultFontMapper fontMapper;
if (font == null) {
fontMapper = new DefaultFontMapper();
} else {
fontMapper = new AsianFontMapper(font.getName(), font.getEncoding());
}
Graphics2D g2 = tp.createGraphics(getWidth(), getHeight(), fontMapper);
chart.draw(g2, new Rectangle2D.Double(0, 0, getWidth(), getHeight()));
g2.dispose();
image = new ImgTemplate(tp);
} else {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ChartUtilities.writeChartAsJPEG(stream, chart, getWidth(),
getHeight());
imageData = stream.toByteArray();
stream.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void configurePlot(Plot plot) {
if (getPlotBackgroundAlpha() != null) {
plot.setBackgroundAlpha(getPlotBackgroundAlpha());
}
if (getPlotForegroundAlpha() != null) {
plot.setForegroundAlpha(getPlotForegroundAlpha());
}
if (getPlotBackgroundPaint() != null) {
plot.setBackgroundPaint(findColor(getPlotBackgroundPaint()));
}
if (getPlotOutlinePaint() != null) {
plot.setOutlinePaint(findColor(getPlotOutlinePaint()));
}
if (getPlotOutlineStroke() != null) {
plot.setOutlineStroke(findStroke(getPlotOutlineStroke()));
}
}
public PlotOrientation plotOrientation(String orientation) {
if (orientation != null && orientation.equalsIgnoreCase("horizontal")) {
return PlotOrientation.HORIZONTAL;
} else {
return PlotOrientation.VERTICAL;
}
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
dataset = getDataset();
// bypass super to avoid createITextObject() before the chart is ready
if (dataset == null) {
dataset = createDataset();
}
chart = getChart();
if (chart == null) {
chart = createChart(context);
}
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
// call create here so that we'll have a valid chart
createITextObject(context);
if (imageData != null) {
ResponseWriter response = context.getResponseWriter();
response.startElement("img", null);
GraphicImageStore store = GraphicImageStore.instance();
String key = store.put(new ImageWrapper(imageData, Type.IMAGE_JPEG));
String url = context.getExternalContext().getRequestContextPath()
+ GraphicImageResource.GRAPHIC_IMAGE_RESOURCE_PATH + "/"
+ key + Type.IMAGE_JPEG.getExtension();
response.writeAttribute("src", url, null);
response.writeAttribute("height", getHeight(), null);
response.writeAttribute("width", getWidth(), null);
response.endElement("img");
}
super.encodeEnd(context);
}
@Override
public Object getITextObject() {
return image;
}
@Override
public void handleAdd(Object arg0) {
throw new RuntimeException("No children allowed");
}
@Override
public void removeITextObject() {
image = null;
chart = null;
}
public abstract Dataset createDataset();
}