📄 reportpane.java
字号:
/**
* ========================================
* JFreeReport : a free Java report library
* ========================================
*
* Project Info: http://www.jfree.org/jfreereport/index.html
* Project Lead: Thomas Morgner;
*
* (C) Copyright 2000-2003, by Simba Management Limited and Contributors.
*
* 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.
*
* ---------------
* ReportPane.java
* ---------------
* (C)opyright 2000-2003, by Simba Management Limited.
*
* Original Author: David Gilbert (for Simba Management Limited);
* Contributor(s): Thomas Morgner;
*
* $Id: ReportPane.java,v 1.49.2.2 2003/08/24 14:18:11 taqua Exp $
*
* Changes (from 8-Feb-2002)
* -------------------------
* 08-Feb-2002 : Updated code to work with latest version of the JCommon class library (DG);
* 18-Feb-2002 : Multiple changes with introduction of XML format for report definition (DG);
* 18-Apr-2002 : Caching painted graphics for performance reasons if the cached graphic is not
* greater than 1500 pixels. Provides propertyChangeEvents for zoom and paginating.
* 10-May-2002 : Updated code to work with last changes in report processing.
* 20-May-2002 : Adjusted to catch ReportProcessingException on processPage.
* 26-May-2002 : Changed Repagination bahaviour. Implemented the Pageable-interface
* 08-Jun-2002 : Documentation
* 22-Aug-2002 : BugFix: Errors while processing the report did not trigger a PropertyChangeEvent
* 01-Sep-2002 : BugFix: ZoomFactorProperty did not trigger a PropertyChangeEvent
*/
package com.jrefinery.report.preview;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.UIManager;
import com.jrefinery.report.JFreeReport;
import com.jrefinery.report.ReportProcessingException;
import com.jrefinery.report.function.FunctionInitializeException;
import com.jrefinery.report.states.ReportState;
import com.jrefinery.report.targets.pageable.OutputTarget;
import com.jrefinery.report.targets.pageable.OutputTargetException;
import com.jrefinery.report.targets.pageable.PageableReportProcessor;
import com.jrefinery.report.targets.pageable.ReportStateList;
import com.jrefinery.report.targets.pageable.output.DummyOutputTarget;
import com.jrefinery.report.targets.pageable.output.G2OutputTarget;
import com.jrefinery.report.targets.base.event.RepaginationListener;
import com.jrefinery.report.targets.base.event.RepaginationState;
import com.jrefinery.report.util.Log;
import com.jrefinery.report.util.PageFormatFactory;
/**
* A panel used to display one page of a report. Works in tandem with a ReportPreviewFrame
* to display a report.
* <p>
* The panel uses several properties to inform its listeners of state changes.
*
* @author David Gilbert
* @author Thomas Morgner
*/
public class ReportPane extends JComponent
implements Printable, Pageable, RepaginationListener
{
/** Literal text for the 'paginated' property. */
public static final String PAGINATED_PROPERTY = "paginated";
/** Literal text for the 'NumberOfPages' property. */
public static final String NUMBER_OF_PAGES_PROPERTY = "NumberOfPages";
/** Literal text for the 'pagenumber' property. */
public static final String PAGENUMBER_PROPERTY = "pagenumber";
/** Literal text for the 'zoomfactor' property. */
public static final String ZOOMFACTOR_PROPERTY = "zoomfactor";
/** Literal text for the 'error' property. */
public static final String ERROR_PROPERTY = "error";
/** Literal text for the 'borderPainted' property. */
public static final String BORDER_PROPERTY = "borderPainted";
/** The size of the paper border. */
private static final float PAPERBORDER_PIXEL = 6f;
/**
* The page cache contains one complete page.
* For performance reasons, I buffer the rendered image and
* discard it when the page is changed or zooming.
*/
private BufferedImage graphCache;
/** The current page number. */
private int pageNumber;
/** The current zoom-factor. */
private float zoomFactor;
/** The number of pages required for the report given the current page format. */
private int pageCount;
/** Storage for end-of-page state information. */
private ReportStateList pageStateList;
/** A flag to indicate whether the border is painted or not. */
private boolean borderPainted;
/** The last error that occurred while printing or painting the report. */
private Exception error;
/** The report. */
private JFreeReport report;
/**
* A simple class performing the locking for huge paginating runs.
*/
private static class PaginateLock
{
/** The 'paginate' state. */
private boolean paginateState;
/**
* Returns the 'paginate' state.
*
* @return the 'paginate' state.
*/
public boolean isPaginating()
{
return paginateState;
}
/**
* Sets the 'paginate' state.
*
* @param p the flag.
*/
public void setPaginating(final boolean p)
{
paginateState = p;
}
}
/** The local paginate lock instance. */
private PaginateLock paginateLock = new PaginateLock();
/** The report processor. */
private PageableReportProcessor processor;
/** The repagination listeners. */
private ArrayList repaginationListeners;
private Object[] repaginationListenersCache;
/**
* Creates a report pane to display the specified report.
*
* @param report the report to display within the pane.
*
* @throws ReportProcessingException if there was a problem processing the report.
*/
public ReportPane(final JFreeReport report) throws ReportProcessingException
{
if (report == null)
{
throw new NullPointerException("Report is null.");
}
this.repaginationListeners = new ArrayList();
this.report = report;
setDoubleBuffered(true);
try
{
processor = new PageableReportProcessor(report);
}
catch (FunctionInitializeException fe)
{
throw new ReportProcessingException("Unable to create the PageableReportProcessor", fe);
}
processor.addRepaginationListener(this);
borderPainted = false;
pageNumber = 1;
setZoomFactor(1.0f);
}
/**
* Returns true, if the report processor should handle the
* Thread.interrupted polling.
*
* @return whether the processing is abortable.
*/
public boolean isHandleInterruptedState()
{
return processor.isHandleInterruptedState();
}
/**
* Defines, whether the report processor should take care of the
* current threads interrupted state. If set to true, the report
* processing may be aborted.
*
* @param handleInterruptedState the new flag value.
*/
public void setHandleInterruptedState(final boolean handleInterruptedState)
{
processor.setHandleInterruptedState(handleInterruptedState);
}
/**
* Returns the current pageStates as a list. The page state list is
* a private property of this class, dont use it elsewhere.
*
* @return the report state list.
*/
protected ReportStateList getPageStateList()
{
synchronized (paginateLock)
{
return pageStateList;
}
}
/**
* Sets the current page state list after the report has been repaginated.
* Fires the paginating PropertyChangeEvent after the report is paginated.
*
* @param list the report state list.
*/
protected void setPageStateList(final ReportStateList list)
{
synchronized (paginateLock)
{
final ReportStateList oldList = pageStateList;
if (oldList != null)
{
oldList.clear();
}
this.pageStateList = list;
firePropertyChange(PAGINATED_PROPERTY, oldList == null, list == null);
}
}
/**
* Returns the page format.
*
* @return The current page format;
*/
public PageFormat getPageFormat()
{
return report.getDefaultPageFormat();
}
/**
* Returns the pageFormat for this Pageable Object. Currently no different pageformats
* are supported within a single report, so this returns alway the same as getPageFormat()
*
* @param page the page number.
*
* @return the page format.
*/
public PageFormat getPageFormat(final int page)
{
return getPageFormat();
}
/**
* Returns a self-reference (this), as this object implements its own Printable-Interface.
*
* @param page the page number.
*
* @return this object (as an instance of Printable).
*/
public Printable getPrintable(final int page)
{
return this;
}
/**
* Returns true, if this report has a pagestate list.
*
* @return true if the report has been paginated.
*/
protected boolean isPaginated()
{
return (pageStateList != null);
}
/**
* Sets the page format.
*
* @param pageFormat The new page format;
*
*/
public void setPageFormat(final PageFormat pageFormat)
{
if (pageFormat == null)
{
throw new NullPointerException("PageFormat must not be null");
}
if (PageFormatFactory.isEqual(pageFormat, this.report.getDefaultPageFormat()))
{
// do nothing if the pageformat is equal, no pagination needed
return;
}
this.report.setDefaultPageFormat(pageFormat);
setPageStateList(null);
graphCache = null;
final int w = (int) ((pageFormat.getWidth() + PAPERBORDER_PIXEL) * zoomFactor);
final int h = (int) ((pageFormat.getHeight() + PAPERBORDER_PIXEL) * zoomFactor);
super.setSize(w, h);
}
/**
* Returns the currently displayed page.
*
* @return the current page shown.
*/
public int getPageNumber()
{
return this.pageNumber;
}
/**
* Gets the number of pages in the report. If the report is not yet paginated,
* the pagination is done.
*
* @return the page count for the current page settings.
*/
public int getNumberOfPages()
{
if (isPaginating())
{
// we are currently in the process of repagination, dont try to
// repaginate ...
return pageCount;
}
if (isPaginated() == false)
{
try
{
repaginate();
}
catch (Exception e)
{
this.pageCount = 0;
}
}
return this.pageCount;
}
/**
* defines the page count for the current page settings. This is set after the report
* has been repaginated.
*
* @param pc the new pagecount.
*/
private void setCurrentPageCount(final int pc)
{
final int oldpc = pageCount;
pageCount = pc;
firePropertyChange(NUMBER_OF_PAGES_PROPERTY, oldpc, pc);
}
/**
* checkes whether a black border is painted around the printable page area.
*
* @return a flag indicating whether to paint the border.
*/
public boolean isBorderPainted()
{
return borderPainted;
}
/**
* Defines whether a black border is painted around the printable page area.
*
* @param b a flag indicating whether to paint the border.
*/
public void setBorderPainted(final boolean b)
{
final boolean oldval = isBorderPainted();
borderPainted = b;
revalidate();
firePropertyChange(BORDER_PROPERTY, oldval, b);
}
/**
* Sets the page number to be displayed.
* If the page number is negaitive it is corrected to 0. A page 0 is never printed.
*
* @param page The new page number;
*/
public void setPageNumber(int page)
{
if (page > getNumberOfPages())
{
return;
}
if (page < 1)
{
page = 0;
}
if (page <= getNumberOfPages())
{
final int oldpage = pageNumber;
pageNumber = page;
graphCache = null;
this.repaint();
firePropertyChange(PAGENUMBER_PROPERTY, oldpage, page);
}
}
/**
* Sets the zoom factor for the pane.
* @param factor The new factor;
*
*/
public void setZoomFactor(final float factor)
{
final double oldzoom = zoomFactor;
zoomFactor = factor;
graphCache = null;
final PageFormat pageFormat = getPageFormat();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -