/*
* 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;
}
}