/*
* jGnash, a personal finance application
* Copyright (C) 2001-2008 Craig Cavanaugh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package jgnash.ui.report;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.net.URL;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import jgnash.ui.actions.BootJFreeReportAction;
import jgnash.util.Resource;
import org.jfree.report.ElementAlignment;
import org.jfree.report.Group;
import org.jfree.report.GroupFooter;
import org.jfree.report.GroupHeader;
import org.jfree.report.JFreeReport;
import org.jfree.report.JFreeReportBoot;
import org.jfree.report.PageFooter;
import org.jfree.report.ReportFooter;
import org.jfree.report.ReportHeader;
import org.jfree.report.TextElement;
import org.jfree.report.elementfactory.DateFieldElementFactory;
import org.jfree.report.elementfactory.LabelElementFactory;
import org.jfree.report.elementfactory.NumberFieldElementFactory;
import org.jfree.report.elementfactory.StaticShapeElementFactory;
import org.jfree.report.elementfactory.TextFieldElementFactory;
import org.jfree.report.function.PageOfPagesFunction;
import org.jfree.report.function.TextFormatExpression;
import org.jfree.report.modules.parser.base.ReportGenerator;
import org.jfree.report.style.ElementStyleKeys;
import org.jfree.report.style.ElementStyleSheet;
/**
* Factory methods to help with report configuration and generation
*
* @author Craig Cavanaugh
*
* $Id: ReportFactory.java 197 2008-01-01 08:13:35Z ccavanaugh $
*/
public class ReportFactory {
/** Preferences key for mono spaced font */
private final static String MONOSPACE = "monospace";
/** Preferences key for proportional spaced font */
private final static String PROPORTIONAL = "proportional";
private final static String PRELOADMODULES = "preloadmodules";
public static void bootJFreeReport() {
// Start the boot process.
if (!JFreeReportBoot.getInstance().isBootDone()) {
BootJFreeReportAction.bootJFreeReport();
}
}
/** Returns a font name for a mono spaced, PDF embeddable font
*
* @return The font name for a mono spaced font
*/
public static String getDefaultMonoFont() {
String[] knownFonts = { "Courier New", "Andale Mono", "Bitstream Vera Sans Mono", "Luxi Mono" };
for (int i = 0; i < knownFonts.length; i++) {
Font f = new Font(knownFonts[i], Font.PLAIN, 1);
if (f.getFamily().equalsIgnoreCase(knownFonts[i])) {
return knownFonts[i]; // it found it!
}
}
return "monospaced"; // fail safe
}
/** Returns a font name for a proportional, PDF embeddable font
*
* @return The font name for a proportional spaced font
*/
public static String getDefaultProportionalFont() {
String[] knownFonts = { "Times New Roman", "Bitstream Vera Serif", "Luxi Serif" };
for (int i = 0; i < knownFonts.length; i++) {
Font f = new Font(knownFonts[i], Font.PLAIN, 1);
if (f.getFamily().equalsIgnoreCase(knownFonts[i])) {
return knownFonts[i]; // it found it!
}
}
return "SansSerif"; // fail safe
}
/** Returns the name of the mono spaced font to use
* @return name of the mono spaced font to use
*/
public static String getMonoFont() {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
return p.get(MONOSPACE, getDefaultMonoFont());
}
/** Returns the name of the proportional spaced font to use
* @return name of the proportional spaced font to use
*/
public static String getProportionalFont() {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
return p.get(PROPORTIONAL, getDefaultProportionalFont());
}
/** Sets the name of the mono spaced font to use
* @param font font name to use
*/
public static void setMonoFont(String font) {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
p.put(MONOSPACE, font);
}
/** Sets the name of the proportional spaced font to use
* @param font font name to use
*/
public static void setProportionalFont(String font) {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
p.put(PROPORTIONAL, font);
}
/** Sets preload state of the report modules
* @param preload true if the report modules should be preloaded
*/
public static void setPreloadReportModules(boolean preload) {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
p.putBoolean(PRELOADMODULES, preload);
}
/** Determines if the report modules should be preloaded
* @return true if the report modules should be preloaded
*/
public static boolean getPreloadReportModules() {
Preferences p = Preferences.userNodeForPackage(ReportFactory.class);
return p.getBoolean(PRELOADMODULES, false);
}
/** Reads the report from the specified template file.
*
* @param url the template location.
* @return a JFreeReport
*/
public static JFreeReport parseReport(final URL url) {
bootJFreeReport();
JFreeReport result = null;
final ReportGenerator generator = ReportGenerator.getInstance();
try {
result = generator.parseReport(url);
} catch (Exception e) {
Resource rb = Resource.get();
Logger.getAnonymousLogger().severe(rb.getString("Message.ParseReportFail"));
e.printStackTrace();
}
return result;
}
/** Reads the report from the specified template file.
*
* @param url the template location.
* @return a JFreeReport
*/
/*public static JFreeReport parseReport(final String url) {
final URL in = Main.getEngine().getClass().getResource(url);
if (in == null) {
UIResource rb = (UIResource) UIResource.get();
Logger.getAnonymousLogger().severe(rb.getString("Message.LoadReportFail"));
return null;
}
return parseReport(in);
}*/
/**
* Adds a footer to the report.
*
* @param report the report to configure.
*/
public static void createPageFooterDateAndPage(JFreeReport report) {
Resource rb = Resource.get();
bootJFreeReport();
PageOfPagesFunction pages = new PageOfPagesFunction("page_count_text");
pages.setFormat(rb.getString("Pattern.Pages"));
report.addExpression(pages);
PageFooter footer = new PageFooter();
footer.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(16));
footer.getStyle().setStyleProperty(ElementStyleSheet.FONT, getProportionalFont());
footer.getStyle().setStyleProperty(ElementStyleSheet.FONTSIZE, new Integer(8));
footer.getStyle().setStyleProperty(ElementStyleSheet.ITALIC, Boolean.TRUE);
footer.getStyle().setStyleProperty(ElementStyleSheet.EMBEDDED_FONT, Boolean.TRUE);
DateFieldElementFactory dateFactory = new DateFieldElementFactory();
dateFactory.setFieldname("report.date");
dateFactory.setAbsolutePosition(new Point2D.Float(0, 7));
dateFactory.setMinimumSize(new Dimension(-50, 9));
dateFactory.setColor(Color.BLACK);
dateFactory.setHorizontalAlignment(ElementAlignment.LEFT);
dateFactory.setVerticalAlignment(ElementAlignment.TOP);
dateFactory.setNullString("-");
footer.addElement(dateFactory.createElement());
TextFieldElementFactory factory = new TextFieldElementFactory();
factory.setAbsolutePosition(new Point2D.Float(-50, 7));
factory.setMinimumSize(new Dimension(-50, 9));
factory.setColor(Color.BLACK);
factory.setHorizontalAlignment(ElementAlignment.RIGHT);
factory.setVerticalAlignment(ElementAlignment.TOP);
factory.setFieldname("page_count_text");
factory.setNullString("-");
footer.addElement(factory.createElement());
report.setPageFooter(footer);
}
public static void updateReportHeaderDates(JFreeReport report, Date start, Date end) {
report.setProperty("startDate", start);
report.setProperty("endDate", end);
}
public static void populateReportHeaderTitleAndDates(JFreeReport report, String title, Date start, Date end) {
Resource rb = Resource.get();
bootJFreeReport();
// export dates to the report
report.setProperty("startDate", start);
report.setProperty("endDate", end);
// create the expression
TextFormatExpression text = new TextFormatExpression();
text.setName("dateRange");
text.setPattern(rb.getString("Pattern.DateRange"));
text.setField(0, "startDate");
text.setField(1, "endDate");
report.addExpression(text);
ReportHeader header = new ReportHeader();
header.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(45));
// FontDefinition bFont = new FontDefinition(getProportionalFont(), 18, false, false, false, false, null, true);
/*header.getStyle().setStyleProperty(ElementStyleSheet.FONT, getProportionalFont());
header.getStyle().setStyleProperty(ElementStyleSheet.FONTSIZE, new Integer(9));
header.getStyle().setStyleProperty(ElementStyleSheet.ITALIC, Boolean.FALSE);
header.getStyle().setStyleProperty(ElementStyleSheet.EMBEDDED_FONT, Boolean.TRUE);*/
header.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#E0E9F1"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 40), false, true));
header.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#000000"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 40), true, false));
// header.addElement(LabelElementFactory.createLabelElement("title", new Rectangle2D.Float(0, 7, -100, 18), Color.BLACK, ElementAlignment.CENTER, bFont, title));
LabelElementFactory titleFactory = new LabelElementFactory();
titleFactory.setAbsolutePosition(new Point2D.Float(0, 7));
titleFactory.setMinimumSize(new Dimension(-100, 18));
titleFactory.setColor(Color.BLACK);
titleFactory.setHorizontalAlignment(ElementAlignment.CENTER);
titleFactory.setVerticalAlignment(ElementAlignment.TOP);
titleFactory.setText(title);
titleFactory.setFontName(getProportionalFont());
titleFactory.setFontSize(18);
titleFactory.setEmbedFont(Boolean.TRUE);
header.addElement(titleFactory.createElement());
//header.addElement(TextFieldElementFactory.createStringElement("dateRange", new Rectangle2D.Float(0, 26, -100, 9), Color.BLACK, ElementAlignment.CENTER, font, "-", "dateRange"));
TextFieldElementFactory datefactory = new TextFieldElementFactory();
datefactory.setAbsolutePosition(new Point2D.Float(0, 26));
datefactory.setMinimumSize(new Dimension(-100, 9));
datefactory.setColor(Color.BLACK);
datefactory.setHorizontalAlignment(ElementAlignment.CENTER);
datefactory.setVerticalAlignment(ElementAlignment.TOP);
datefactory.setFieldname("dateRange");
datefactory.setNullString("-");
datefactory.setFontName(getProportionalFont());
datefactory.setFontSize(9);
datefactory.setEmbedFont(Boolean.TRUE);
header.addElement(datefactory.createElement());
report.setReportHeader(header);
}
public static void populateReportHeaderTitleAndDate(JFreeReport report, String title, Date date) {
Resource rb = Resource.get();
bootJFreeReport();
// export date to the report
report.setProperty("date", date);
// create the expression
TextFormatExpression text = new TextFormatExpression();
text.setName("reportDate");
text.setPattern(rb.getString("Pattern.Date"));
text.setField(0, "date");
report.addExpression(text);
ReportHeader header = new ReportHeader();
header.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(45));
header.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#E0E9F1"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 40), false, true));
header.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#000000"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 40), true, false));
LabelElementFactory titleFactory = new LabelElementFactory();
titleFactory.setAbsolutePosition(new Point2D.Float(0, 7));
titleFactory.setMinimumSize(new Dimension(-100, 18));
titleFactory.setColor(Color.BLACK);
titleFactory.setHorizontalAlignment(ElementAlignment.CENTER);
titleFactory.setVerticalAlignment(ElementAlignment.TOP);
titleFactory.setText(title);
titleFactory.setFontName(getProportionalFont());
titleFactory.setFontSize(18);
titleFactory.setEmbedFont(Boolean.TRUE);
header.addElement(titleFactory.createElement());
TextFieldElementFactory datefactory = new TextFieldElementFactory();
datefactory.setAbsolutePosition(new Point2D.Float(0, 26));
datefactory.setMinimumSize(new Dimension(-100, 9));
datefactory.setColor(Color.BLACK);
datefactory.setHorizontalAlignment(ElementAlignment.CENTER);
datefactory.setVerticalAlignment(ElementAlignment.TOP);
datefactory.setFieldname("reportDate");
datefactory.setNullString("-");
datefactory.setFontName(getProportionalFont());
datefactory.setFontSize(9);
datefactory.setEmbedFont(Boolean.TRUE);
header.addElement(datefactory.createElement());
report.setReportHeader(header);
}
public static ReportFooter createGenericReportFooter() {
bootJFreeReport();
ReportFooter footer = new ReportFooter();
footer.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(15));
footer.getStyle().setStyleProperty(ElementStyleSheet.FONT, getProportionalFont());
footer.getStyle().setStyleProperty(ElementStyleSheet.FONTSIZE, new Integer(9));
footer.getStyle().setStyleProperty(ElementStyleSheet.BOLD, Boolean.TRUE);
footer.getStyle().setStyleProperty(ElementStyleSheet.EMBEDDED_FONT, Boolean.TRUE);
footer.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#E0E9F1"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 13), false, true));
footer.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#000000"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 13), true, false));
return footer;
}
public static void createGenericGroupFooter(Group group) {
bootJFreeReport();
GroupFooter footer = group.getFooter();
footer.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(15));
footer.getStyle().setStyleProperty(ElementStyleSheet.FONT, getProportionalFont());
footer.getStyle().setStyleProperty(ElementStyleSheet.FONTSIZE, new Integer(9));
footer.getStyle().setStyleProperty(ElementStyleSheet.BOLD, Boolean.TRUE);
footer.getStyle().setStyleProperty(ElementStyleSheet.EMBEDDED_FONT, Boolean.TRUE);
footer.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#E0E9F1"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 13), false, true));
footer.addElement(StaticShapeElementFactory.createRectangleShapeElement("background", Color.decode("#000000"), new BasicStroke(0), new Rectangle2D.Float(0, 0, -100, 13), true, false));
}
public static void createGenericGroupHeader(Group group) {
bootJFreeReport();
GroupHeader header = group.getHeader();
header.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(25));
header.getStyle().setStyleProperty(ElementStyleSheet.FONT, getProportionalFont());
header.getStyle().setStyleProperty(ElementStyleSheet.FONTSIZE, new Integer(12));
header.getStyle().setStyleProperty(ElementStyleSheet.BOLD, Boolean.TRUE);
header.getStyle().setStyleProperty(ElementStyleSheet.EMBEDDED_FONT, Boolean.TRUE);
header.addElement(StaticShapeElementFactory.createHorizontalLine("bottom", Color.BLACK, new BasicStroke(1.0f), 22f));
}
/**
* Creates a new {@link org.jfree.report.TextElement} containing a label.
*
* @param name the name of the new element.
* @param bounds the bounds of the new element.
* @param paint the text color of this text element.
* @param alignment the horizontal alignment.
* @param valign the vertical alignment.
* @param font the font for this element.
* @param labeltext the text to display.
* @return a report element for displaying a label (static text).
*
* @throws NullPointerException if bounds, name, format or field are
* <code>null</code>.
* @throws IllegalArgumentException if the given alignment is invalid.
*/
public static TextElement createLabelElement(final String name, final Rectangle2D bounds, final Color paint, final ElementAlignment alignment, final ElementAlignment valign, final Font font, final String labeltext) {
final LabelElementFactory factory = new LabelElementFactory();
factory.setX(new Float(bounds.getX()));
factory.setY(new Float(bounds.getY()));
factory.setMinimumWidth(new Float(bounds.getWidth()));
factory.setMinimumHeight(new Float(bounds.getHeight()));
factory.setName(name);
factory.setColor(paint);
factory.setHorizontalAlignment(alignment);
factory.setVerticalAlignment(valign);
if (font != null) {
factory.setFontName(font.getFamily());
factory.setFontSize(font.getSize());
factory.setBold(font.isBold());
factory.setItalic(font.isItalic());
factory.setEmbedFont(true);
}
factory.setText(labeltext);
return (TextElement) factory.createElement();
}
/**
* Creates a new TextElement containing a numeric filter structure.
*
* @param name the name of the new element.
* @param bounds the bounds of the new element.
* @param color the text color of this text element.
* @param alignment the horizontal text alignment.
* @param valign the vertical alignment.
* @param font the font for this element.
* @param nullString the text used when the value of this element is null.
* @param field the field in the datamodel to retrieve values from.
* @param format the NumberFormat used in this number element.
* @return a report element for displaying <code>Number</code> objects.
*
* @throws NullPointerException if bounds, name or function are null
* @throws IllegalArgumentException if the given alignment is invalid
*/
public static TextElement createNumberElement(final String name, final Rectangle2D bounds, final Color color, final ElementAlignment alignment, final ElementAlignment valign, final Font font, final String nullString, final NumberFormat format, final String field) {
final NumberFieldElementFactory factory = new NumberFieldElementFactory();
factory.setX(new Float(bounds.getX()));
factory.setY(new Float(bounds.getY()));
factory.setMinimumWidth(new Float(bounds.getWidth()));
factory.setMinimumHeight(new Float(bounds.getHeight()));
factory.setName(name);
factory.setColor(color);
factory.setHorizontalAlignment(alignment);
factory.setVerticalAlignment(valign);
if (font != null) {
factory.setFontName(font.getFamily());
factory.setFontSize(font.getSize());
factory.setBold(font.isBold());
factory.setItalic(font.isItalic());
factory.setEmbedFont(true);
}
factory.setNullString(nullString);
factory.setFormat(format);
factory.setFieldname(field);
return (TextElement) factory.createElement();
}
/**
* Creates a new TextElement containing a date filter structure.
*
* @param name the name of the new element
* @param bounds the bounds of the new element
* @param paint the text color of this text element
* @param alignment the horizontal text alignment.
* @param valign the vertical text alignment
* @param font the font for this element
* @param nullString the text used when the value of this element is null
* @param format the SimpleDateFormat used to format the date
* @param field the fieldname to retrieve values from
* @return a report element for displaying a java.util.Date value.
*
* @throws NullPointerException if bounds, name, format or field are null
* @throws IllegalArgumentException if the given alignment is invalid
*/
public static TextElement createDateElement(final String name, final Rectangle2D bounds, final Color paint, final ElementAlignment alignment, final ElementAlignment valign, final Font font, final String nullString, final DateFormat format, final String field) {
final DateFieldElementFactory factory = new DateFieldElementFactory();
factory.setX(new Float(bounds.getX()));
factory.setY(new Float(bounds.getY()));
factory.setMinimumWidth(new Float(bounds.getWidth()));
factory.setMinimumHeight(new Float(bounds.getHeight()));
factory.setName(name);
factory.setColor(paint);
factory.setHorizontalAlignment(alignment);
factory.setVerticalAlignment(valign);
if (font != null) {
factory.setFontName(font.getFamily());
factory.setFontSize(font.getSize());
factory.setBold(font.isBold());
factory.setItalic(font.isItalic());
factory.setEmbedFont(true);
}
factory.setNullString(nullString);
factory.setFormat(format);
factory.setFieldname(field);
return (TextElement) factory.createElement();
}
/**
* Creates a new TextElement without any additional filtering.
*
* @param name the name of the new element
* @param bounds the bounds of the new element
* @param paint the text color of this text element
* @param alignment the horizontal text alignment.
* @param valign the vertical alignment.
* @param font the font for this element
* @param nullString the text used when the value of this element is null
* @param field the field in the datamodel to retrieve values from
* @return a report element for displaying <code>String</code> objects.
*
* @throws NullPointerException if bounds, name or function are null
* @throws IllegalArgumentException if the given alignment is invalid
*/
public static TextElement createStringElement(final String name, final Rectangle2D bounds, final Color paint, final ElementAlignment alignment, final ElementAlignment valign, final Font font, final String nullString, final String field) {
final TextFieldElementFactory factory = new TextFieldElementFactory();
factory.setX(new Float(bounds.getX()));
factory.setY(new Float(bounds.getY()));
factory.setMinimumWidth(new Float(bounds.getWidth()));
factory.setMinimumHeight(new Float(bounds.getHeight()));
factory.setName(name);
factory.setColor(paint);
factory.setHorizontalAlignment(alignment);
factory.setVerticalAlignment(valign);
if (font != null) {
factory.setFontName(font.getFamily());
factory.setFontSize(font.getSize());
factory.setBold(font.isBold());
factory.setItalic(font.isItalic());
factory.setEmbedFont(true);
}
factory.setFieldname(field);
factory.setNullString(nullString);
return (TextElement) factory.createElement();
}
}
|