/*
* 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) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.layout.model;
import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.filter.types.AutoLayoutBoxType;
import org.pentaho.reporting.engine.classic.core.filter.types.bands.MasterReportType;
import org.pentaho.reporting.engine.classic.core.layout.model.context.BoxDefinition;
import org.pentaho.reporting.engine.classic.core.layout.style.SimpleStyleSheet;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
/**
* The logical page is the root-structure of the generated content. This object is a slotted container.
*
* @author Thomas Morgner
*/
public final class LogicalPageBox extends BlockRenderBox {
// All breaks along the major-axis.
private PageBreakPositionList allVerticalBreaks;
private long pageOffset;
private long pageEnd;
private long processedTableOffset;
private WatermarkAreaBox watermarkArea;
private PageAreaBox headerArea;
private PageAreaBox footerArea;
private PageAreaBox repeatFooterArea;
private DefaultPageGrid pageGrid;
private InstanceID contentAreaId;
private String pageName;
private WatermarkAreaBox savedWatermarkArea;
private PageAreaBox savedHeaderArea;
private PageAreaBox savedFooterArea;
private PageAreaBox savedRepeatFooterArea;
public LogicalPageBox( final ReportDefinition report, final StyleSheet style, final BoxDefinition box ) {
super( style, report.getObjectID(), box, AutoLayoutBoxType.INSTANCE, report.getAttributes(), null );
this.headerArea = new PageAreaBox();
this.headerArea.setName( "Logical-Page-Header-Area" );
this.headerArea.setLogicalPage( this );
this.repeatFooterArea = new PageAreaBox();
this.repeatFooterArea.setName( "Logical-Repeat-Footer-Area" );
this.repeatFooterArea.setLogicalPage( this );
this.footerArea = new PageAreaBox();
this.footerArea.setName( "Logical-Page-Footer-Area" );
this.footerArea.setLogicalPage( this );
this.watermarkArea = new WatermarkAreaBox();
this.watermarkArea.setName( "Logical-Page-Watermark-Area" );
this.watermarkArea.setLogicalPage( this );
final BlockRenderBox contentArea =
new BlockRenderBox( SimpleStyleSheet.EMPTY_STYLE, new InstanceID(), BoxDefinition.EMPTY,
new MasterReportType(), report.getAttributes(), null );
contentArea.setName( "Logical-Page-Content-Area" );
addChild( contentArea );
contentAreaId = contentArea.getInstanceId();
this.pageGrid = new DefaultPageGrid( report.getPageDefinition() );
this.allVerticalBreaks = new PageBreakPositionList();
}
public BlockRenderBox getContentArea() {
// this should be very inexpensive, as there is only one child, which already is the box in question.
final BlockRenderBox blockRenderBox = (BlockRenderBox) findNodeById( contentAreaId );
if ( blockRenderBox == null ) {
throw new IllegalStateException( "Cloning or deriving must have failed: No content area." );
}
return blockRenderBox;
}
public BlockRenderBox getHeaderArea() {
return headerArea;
}
public BlockRenderBox getRepeatFooterArea() {
return repeatFooterArea;
}
public BlockRenderBox getFooterArea() {
return footerArea;
}
public WatermarkAreaBox getWatermarkArea() {
return watermarkArea;
}
public LogicalPageBox getLogicalPage() {
return this;
}
public long getPageWidth() {
return pageGrid.getMaximumPageWidth();
}
public PageGrid getPageGrid() {
return pageGrid;
}
public long getPageOffset() {
return pageOffset;
}
public void setPageOffset( final long pageOffset ) {
this.pageOffset = pageOffset;
}
public long getPageEnd() {
return pageEnd;
}
public void setPageEnd( final long pageEnd ) {
this.pageEnd = pageEnd;
}
public long[] getPhysicalBreaks( final int axis ) {
if ( axis == RenderNode.HORIZONTAL_AXIS ) {
return pageGrid.getHorizontalBreaks();
}
return pageGrid.getVerticalBreaks();
}
public long getPageHeight() {
return pageGrid.getMaximumPageHeight();
}
/**
* Derive creates a disconnected node that shares all the properties of the original node. The derived node will no
* longer have any parent, silbling, child or any other relationships with other nodes.
*
* @return
*/
public LogicalPageBox deriveFrozen( final boolean deepDerive ) {
final LogicalPageBox box = (LogicalPageBox) super.deriveFrozen( deepDerive );
box.headerArea = (PageAreaBox) headerArea.deriveFrozen( deepDerive );
box.headerArea.setLogicalPage( box );
box.footerArea = (PageAreaBox) footerArea.deriveFrozen( deepDerive );
box.footerArea.setLogicalPage( box );
box.repeatFooterArea = (PageAreaBox) repeatFooterArea.deriveFrozen( deepDerive );
box.repeatFooterArea.setLogicalPage( box );
box.watermarkArea = (WatermarkAreaBox) watermarkArea.deriveFrozen( deepDerive );
box.watermarkArea.setLogicalPage( box );
return box;
}
/**
* Derive creates a disconnected node that shares all the properties of the original node. The derived node will no
* longer have any parent, silbling, child or any other relationships with other nodes.
*
* @return
*/
public LogicalPageBox derive( final boolean deepDerive ) {
final LogicalPageBox box = (LogicalPageBox) super.derive( deepDerive );
box.headerArea = (PageAreaBox) headerArea.derive( deepDerive );
box.headerArea.setLogicalPage( box );
box.footerArea = (PageAreaBox) footerArea.derive( deepDerive );
box.footerArea.setLogicalPage( box );
box.repeatFooterArea = (PageAreaBox) repeatFooterArea.derive( deepDerive );
box.repeatFooterArea.setLogicalPage( box );
box.watermarkArea = (WatermarkAreaBox) watermarkArea.derive( deepDerive );
box.watermarkArea.setLogicalPage( box );
if ( box.savedFooterArea != null ) {
box.savedFooterArea = (PageAreaBox) savedFooterArea.derive( deepDerive );
box.savedFooterArea.setLogicalPage( box );
}
if ( box.savedRepeatFooterArea != null ) {
box.savedRepeatFooterArea = (PageAreaBox) savedRepeatFooterArea.derive( deepDerive );
box.savedRepeatFooterArea.setLogicalPage( box );
}
if ( box.savedHeaderArea != null ) {
box.savedHeaderArea = (PageAreaBox) savedHeaderArea.derive( deepDerive );
box.savedHeaderArea.setLogicalPage( box );
}
if ( box.savedWatermarkArea != null ) {
box.savedWatermarkArea = (WatermarkAreaBox) savedWatermarkArea.derive( deepDerive );
box.savedWatermarkArea.setLogicalPage( box );
}
return box;
}
/**
* Clones this node. Be aware that cloning can get you into deep trouble, as the relations this node has may no longer
* be valid.
*
* @return
*/
public LogicalPageBox clone() {
try {
final LogicalPageBox o = (LogicalPageBox) super.clone();
o.pageGrid = (DefaultPageGrid) pageGrid.clone();
o.allVerticalBreaks = allVerticalBreaks;
return o;
} catch ( CloneNotSupportedException e ) {
throw new IllegalStateException( "Cloning *must* be supported." );
}
}
public void setAllVerticalBreaks( final PageBreakPositionList allVerticalBreaks ) {
if ( allVerticalBreaks == null ) {
throw new NullPointerException();
}
// create a new list-controller but share the backend with the old list.
this.allVerticalBreaks = new PageBreakPositionList( this.allVerticalBreaks );
this.allVerticalBreaks.copyFrom( allVerticalBreaks );
}
public PageBreakPositionList getAllVerticalBreaks() {
return allVerticalBreaks;
}
public long computePageEnd() {
final long pageOffset = getPageOffset();
final PageBreakPositionList allVerticalBreaks = getAllVerticalBreaks();
final long lastMasterBreak = allVerticalBreaks.getLastMasterBreak();
if ( pageOffset == lastMasterBreak ) {
return getHeight();
}
return allVerticalBreaks.findNextMajorBreakPosition( pageOffset + 1 );
}
public String getPageName() {
return pageName;
}
public void setPageName( final String pageName ) {
this.pageName = pageName;
}
public int getNodeType() {
return LayoutNodeTypes.TYPE_BOX_LOGICALPAGE;
}
public void storeSaveInformation() {
savedFooterArea = ( (PageAreaBox) getFooterArea().derive( true ) );
savedRepeatFooterArea = ( (PageAreaBox) getRepeatFooterArea().derive( true ) );
savedHeaderArea = ( (PageAreaBox) getHeaderArea().derive( true ) );
savedWatermarkArea = ( (WatermarkAreaBox) getWatermarkArea().derive( true ) );
}
public void rollbackSaveInformation() {
headerArea = ( (PageAreaBox) savedHeaderArea.derive( true ) );
footerArea = ( (PageAreaBox) savedFooterArea.derive( true ) );
repeatFooterArea = ( (PageAreaBox) savedRepeatFooterArea.derive( true ) );
watermarkArea = ( (WatermarkAreaBox) savedWatermarkArea.derive( true ) );
}
public long getProcessedTableOffset() {
return processedTableOffset;
}
public void setProcessedTableOffset( final long processedTableOffset ) {
this.processedTableOffset = processedTableOffset;
}
}