net.sf.jasperreports.engine.fill.JRVerticalFiller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2022 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.fill;
import org.apache.commons.javaflow.api.continuable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRGroup;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.type.FooterPositionEnum;
import net.sf.jasperreports.engine.type.IncrementTypeEnum;
import net.sf.jasperreports.engine.type.ResetTypeEnum;
import net.sf.jasperreports.engine.type.RunDirectionEnum;
/**
* @author Teodor Danciu ([email protected])
*/
public class JRVerticalFiller extends JRBaseFiller
{
private static final Log log = LogFactory.getLog(JRVerticalFiller.class);
protected boolean hasDetailOnPage;
/**
*
*/
protected JRVerticalFiller(
JasperReportsContext jasperReportsContext,
JasperReport jasperReport
) throws JRException
{
this(jasperReportsContext, jasperReport, null);
}
/**
*
*/
public JRVerticalFiller(
JasperReportsContext jasperReportsContext,
JasperReport jasperReport,
BandReportFillerParent parent
) throws JRException
{
this(jasperReportsContext, SimpleJasperReportSource.from(jasperReport), parent);
}
public JRVerticalFiller(
JasperReportsContext jasperReportsContext,
JasperReportSource reportSource,
BandReportFillerParent parent
) throws JRException
{
super(jasperReportsContext, reportSource, parent);
setPageHeight(pageHeight);
}
public boolean hasDetailOnPage()
{
return hasDetailOnPage;
}
@Override
protected void setPageHeight(int pageHeight)
{
this.pageHeight = pageHeight;
columnFooterOffsetY = pageHeight - bottomMargin - pageFooter.getHeight() - columnFooter.getHeight();
lastPageColumnFooterOffsetY = pageHeight - bottomMargin - lastPageFooter.getHeight() - columnFooter.getHeight();
if (log.isDebugEnabled())
{
log.debug("Filler " + fillerId + " - pageHeight: " + pageHeight
+ ", columnFooterOffsetY: " + columnFooterOffsetY
+ ", lastPageColumnFooterOffsetY: " + lastPageColumnFooterOffsetY);
}
}
@Override
@continuable
protected synchronized void fillReport() throws JRException
{
setLastPageFooter(false);
if (next())
{
fillReportStart();
while (next())
{
fillReportContent();
}
fillReportEnd();
}
else
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": no data");
}
switch (getWhenNoDataType())
{
case ALL_SECTIONS_NO_DETAIL :
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": all sections");
}
scriptlet.callBeforeReportInit();
calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
scriptlet.callAfterReportInit();
printPage = newPage();
printPageContentsWidth = 0;
addPage(printPage);
setFirstColumn();
offsetY = topMargin;
isFirstPageBand = true;
isFirstColumnBand = true;
isCrtRecordOnPage = false;
isCrtRecordOnColumn = false;
fillBackground();
fillTitle();
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
fillGroupHeaders(true);
fillGroupFooters(true);
fillSummary();
break;
}
case BLANK_PAGE :
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": blank page");
}
printPage = newPage();
addPage(printPage);
break;
}
case NO_DATA_SECTION:
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": all sections");
}
scriptlet.callBeforeReportInit();
calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
scriptlet.callAfterReportInit();
printPage = newPage();
addPage(printPage);
setFirstColumn();
offsetY = topMargin;
isFirstPageBand = true;
isFirstColumnBand = true;
isCrtRecordOnPage = false;
isCrtRecordOnColumn = false;
fillBackground();
fillNoData();
break;
}
case NO_PAGES :
default :
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": no pages");
}
}
}
}
recordUsedPageHeight(offsetY + bottomMargin);
if (ignorePagination)
{
jasperPrint.setPageHeight(usedPageHeight);
}
if (isSubreport())
{
addPageToParent(true);
}
else
{
addLastPageBookmarks();
}
if (bookmarkHelper != null)
{
jasperPrint.setBookmarks(bookmarkHelper.getRootBookmarks());
}
}
/**
*
*/
@continuable
private void fillReportStart() throws JRException
{
scriptlet.callBeforeReportInit();
calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
scriptlet.callAfterReportInit();
printPage = newPage();
printPageContentsWidth = 0;
addPage(printPage);
setFirstColumn();
offsetY = topMargin;
isFirstPageBand = true;
isFirstColumnBand = true;
isCrtRecordOnPage = false;
isCrtRecordOnColumn = false;
fillBackground();
fillTitle();
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
fillGroupHeaders(true);
fillDetail();
}
/**
*
*/
@continuable
private void fillReportContent() throws JRException
{
calculator.estimateGroupRuptures();
fillGroupFooters(false);
resolveGroupBoundElements(JRExpression.EVALUATION_OLD, false);
scriptlet.callBeforeGroupInit();
calculator.initializeVariables(ResetTypeEnum.GROUP, IncrementTypeEnum.GROUP);
scriptlet.callAfterGroupInit();
fillGroupHeaders(false);
fillDetail();
}
/**
*
*/
@continuable
private void fillReportEnd() throws JRException
{
fillGroupFooters(true);
fillSummary();
}
/**
*
*/
@continuable
private void fillTitle() throws JRException
{
if (log.isDebugEnabled() && !title.isEmpty())
{
log.debug("Fill " + fillerId + ": title at " + offsetY);
}
title.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (title.isToPrint())
{
while (
title.getBreakHeight() > pageHeight - bottomMargin - offsetY
)
{
addPage(false);
}
title.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = title.fill(pageHeight - bottomMargin - offsetY);
if (title.willOverflow() && title.isSplitPrevented() && !title.isSplitTypePreventInhibited())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
title.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
while (title.willOverflow())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand = title.fill(pageHeight - bottomMargin - offsetY);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
resolveBandBoundElements(title, JRExpression.EVALUATION_DEFAULT);
if (isTitleNewPage)
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
}
}
}
/**
*
*/
@continuable
private void fillPageHeader(byte evaluation) throws JRException
{
if (log.isDebugEnabled() && !pageHeader.isEmpty())
{
log.debug("Fill " + fillerId + ": page header at " + offsetY);
}
setNewPageColumnInBands();
pageHeader.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (pageHeader.isToPrint())
{
int reattempts = getMasterColumnCount();
if (isCreatingNewPage)
{
--reattempts;
}
boolean filled = fillBandNoOverflow(pageHeader, evaluation);
for (int i = 0; !filled && i < reattempts; ++i)
{
resolveGroupBoundElements(evaluation, false);
resolveColumnBoundElements(evaluation);
resolvePageBoundElements(evaluation);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
filled = fillBandNoOverflow(pageHeader, evaluation);
}
if (!filled)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_PAGE_HEADER_OVERFLOW_INFINITE_LOOP,
(Object[])null);
}
}
columnHeaderOffsetY = offsetY;
hasDetailOnPage = false;
isNewPage = true;
}
private boolean fillBandNoOverflow(JRFillBand band, byte evaluation) throws JRException
{
int availableHeight = columnFooterOffsetY - offsetY;
boolean overflow = availableHeight < band.getHeight();
if (!overflow)
{
band.evaluate(evaluation);
JRPrintBand printBand = band.fill(availableHeight);
overflow = band.willOverflow();
if (overflow)
{
band.rewind();
}
else
{
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
isCrtRecordOnColumn = isCrtRecordOnPage;
resolveBandBoundElements(band, evaluation);
}
}
return !overflow;
}
/**
*
*/
@continuable
private void fillColumnHeader(byte evaluation) throws JRException
{
if (log.isDebugEnabled() && !columnHeader.isEmpty())
{
log.debug("Fill " + fillerId + ": column header at " + offsetY);
}
setNewPageColumnInBands();
isFirstColumnBand = true;
columnHeader.evaluatePrintWhenExpression(evaluation);
if (columnHeader.isToPrint())
{
int reattempts = getMasterColumnCount();
if (isCreatingNewPage)
{
--reattempts;
}
setOffsetX();
boolean filled = fillBandNoOverflow(columnHeader, evaluation);
for (int i = 0; !filled && i < reattempts; ++i)
{
while (columnIndex < columnCount - 1)
{
resolveGroupBoundElements(evaluation, false);
resolveColumnBoundElements(evaluation);
scriptlet.callBeforeColumnInit();
calculator.initializeVariables(ResetTypeEnum.COLUMN, IncrementTypeEnum.COLUMN);
scriptlet.callAfterColumnInit();
columnIndex += 1;
setOffsetX();
offsetY = columnHeaderOffsetY;
isCrtRecordOnColumn = false;
setColumnNumberVar();
}
fillPageFooter(evaluation);
resolveGroupBoundElements(evaluation, false);
resolveColumnBoundElements(evaluation);
resolvePageBoundElements(evaluation);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(evaluation);
filled = fillBandNoOverflow(columnHeader, evaluation);
}
if (!filled)
{
throw new JRRuntimeException(EXCEPTION_MESSAGE_KEY_COLUMN_HEADER_OVERFLOW_INFINITE_LOOP, (Object[]) null);
}
}
isNewColumn = true;
}
/**
*
*/
@continuable
private void fillGroupHeaders(boolean isFillAll) throws JRException
{
if (groups != null && groups.length > 0)
{
for (int i = 0; i < groups.length; i++)
{
JRFillGroup group = groups[i];
if (isFillAll || group.hasChanged())
{
fillGroupHeader(group);
}
}
}
}
/**
*
*/
@continuable
private void fillGroupHeader(JRFillGroup group) throws JRException
{
JRFillSection groupHeaderSection = (JRFillSection)group.getGroupHeaderSection();
if (log.isDebugEnabled() && !groupHeaderSection.isEmpty())
{
log.debug("Fill " + fillerId + ": " + group.getName() + " header at " + offsetY);
}
//byte evalPrevPage = (group.isTopLevelChange()?JRExpression.EVALUATION_OLD:JRExpression.EVALUATION_DEFAULT);
if ( (group.isStartNewPage() || group.isResetPageNumber()) && !isNewPage )
{
fillPageBreak(
group.isResetPageNumber(),
isCrtRecordOnPage ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
JRExpression.EVALUATION_DEFAULT,
true
);
}
else if ( group.isStartNewColumn() && !isNewColumn )
{
fillColumnBreak(
isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
JRExpression.EVALUATION_DEFAULT
);
}
boolean isFirstHeaderBandToPrint = true;
boolean isGroupReset = false;
JRFillBand[] groupHeaderBands = groupHeaderSection.getFillBands();
for (int i = 0; i < groupHeaderBands.length; i++)
{
JRFillBand groupHeaderBand = groupHeaderBands[i];
groupHeaderBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (groupHeaderBand.isToPrint())
{
while (
groupHeaderBand.getBreakHeight() > columnFooterOffsetY - offsetY ||
(isFirstHeaderBandToPrint && group.getMinHeightToStartNewPage() > columnFooterOffsetY - offsetY)
)
{
fillColumnBreak(
isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
JRExpression.EVALUATION_DEFAULT
);
}
}
if (!isGroupReset && (isFirstHeaderBandToPrint || i == groupHeaderBands.length - 1))
{
// perform this group reset before the first header band prints,
// or before the last header band, regardless if it prints or not
setNewGroupInBands(group);
group.setFooterPrinted(false);
group.resetDetailsCount();
isGroupReset = true;
}
ElementRange elementRange = null;
if (
(group.isKeepTogether() && !isNewColumn)
|| group.getMinDetailsToStartFromTop() > 0
)
{
elementRange = group.getKeepTogetherElementRange();
if (elementRange == null)
{
// we need to set a keep together element range for the group
// even if its header does not print,
// but only if the column is not already new
elementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
group.setKeepTogetherElementRange(elementRange);
// setting a non-null element range here would cause the group header band to be
// refilled below and thus kept together, in case a split occurs in it;
// the non-null element range will be also moved onto the new page/column in the process,
// but it will contain no elements as the already mentioned non-splitting behavior of the group header band
// would not add any element to it;
// so the keep together element range set here is more like flag to signal the group header itself
// should be prevented from splitting in the fillColumnBand call below
}
}
if (groupHeaderBand.isToPrint())
{
fillColumnBand(groupHeaderBand, JRExpression.EVALUATION_DEFAULT, false);
ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
// in case a column/page break occurred during the filling of the band above,
// the provided element range is discarded/ignored,
// but that should not be a problem because the discarded element range was already dealt with during the break,
// because it was a keep together element range
ElementRangeUtil.expandOrIgnore(elementRange, newElementRange);
isFirstPageBand = false;
isFirstColumnBand = false;
isFirstHeaderBandToPrint = false;
}
}
group.setHeaderPrinted(true);
}
/**
*
*/
@continuable
private void fillGroupHeadersReprint(byte evaluation, boolean isPageBreak) throws JRException
{
if (groups != null && groups.length > 0)
{
for (int i = 0; i < groups.length; i++)
{
JRFillGroup group = groups[i];
if (
group.getKeepTogetherElementRange() != null
&& (group.isKeepTogether() || !group.hasMinDetails())
)
{
// we reprint headers only for groups that are "outer" to the one which
// triggered a potential "keep together" move
break;
}
if (
(group.isReprintHeaderOnEachColumn() || (group.isReprintHeaderOnEachPage() && isPageBreak))
&& (!group.hasChanged() || (group.hasChanged() && group.isHeaderPrinted()))
)
{
fillGroupHeaderReprint(groups[i], evaluation);
}
}
}
}
/**
*
*/
@continuable
private void fillGroupHeaderReprint(JRFillGroup group, byte evaluation) throws JRException
{
JRFillSection groupHeaderSection = (JRFillSection)group.getGroupHeaderSection();
JRFillBand[] groupHeaderBands = groupHeaderSection.getFillBands();
for (int i = 0; i < groupHeaderBands.length; i++)
{
JRFillBand groupHeaderBand = groupHeaderBands[i];
groupHeaderBand.evaluatePrintWhenExpression(evaluation);
if (groupHeaderBand.isToPrint())
{
while (groupHeaderBand.getBreakHeight() > columnFooterOffsetY - offsetY)
{
fillColumnBreak(evaluation, evaluation); // using same evaluation for both side of the break is ok here
}
fillColumnBand(groupHeaderBand, evaluation, false);
//isFirstPageBand = false;
if (columnCount > 1)
{
isFirstColumnBand = false;
}
}
}
}
/**
*
*/
@continuable
private void fillDetail() throws JRException
{
if (log.isDebugEnabled() && !detailSection.isEmpty())
{
log.debug("Fill " + fillerId + ": detail at " + offsetY);
}
if (!detailSection.areAllPrintWhenExpressionsNull())
{
calculator.estimateVariables();
}
JRFillBand[] detailBands = detailSection.getFillBands();
for (int i = 0; i < detailBands.length; i++)
{
JRFillBand detailBand = detailBands[i];
detailBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_ESTIMATED);
if (detailBand.isToPrint())
{
while (
detailBand.getBreakHeight() > columnFooterOffsetY - offsetY
)
{
fillColumnBreak(
isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD,
JRExpression.EVALUATION_DEFAULT
);
}
break;
}
}
scriptlet.callBeforeDetailEval();
calculator.calculateVariables(true);
scriptlet.callAfterDetailEval();
detailElementRange = null;
boolean keepDetailElementRangeForOrphanFooter = true;
boolean atLeastOneDetailBandPrinted = false;
for (int i = 0; i < detailBands.length; i++)
{
JRFillBand detailBand = detailBands[i];
detailBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (detailBand.isToPrint())
{
while (
detailBand.getBreakHeight() > columnFooterOffsetY - offsetY
)
{
fillColumnBreak(
isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD,
JRExpression.EVALUATION_DEFAULT
);
}
if (
keepDetailElementRangeForOrphanFooter
&& detailElementRange == null
)
{
detailElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
}
fillColumnBand(detailBand, JRExpression.EVALUATION_DEFAULT, !atLeastOneDetailBandPrinted); //recalculate variables on refill if this is the first detail band
if (detailElementRange == null)
{
// page/column break occurred so we give up keeping the detail element range altogether;
// even if the detail moved onto new page/column completely (did not start at the bottom as it was
// non-splitting or did not fit within break height), we still need to give up on keeping
// the current detail element range because only the next detail on the page/column would make
// sense to move for orphan footers;
// if there will be no second detail there, we simply can't move the only detail, so we still have to give up here
keepDetailElementRangeForOrphanFooter = false;
}
else
{
// there was no overflow, otherwise this range would have been reset to null during page/column break
ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
ElementRangeUtil.expandOrIgnore(detailElementRange, newElementRange);
}
atLeastOneDetailBandPrinted = true;
isFirstPageBand = false;
isFirstColumnBand = false;
}
}
if (atLeastOneDetailBandPrinted)
{
if (groups != null)
{
for (JRFillGroup group : groups)
{
group.incrementDetailsCount();
}
}
}
hasDetailOnPage = atLeastOneDetailBandPrinted;
isNewPage = false;
isNewColumn = false;
}
/**
*
*/
@continuable
private void fillGroupFooters(boolean isFillAll) throws JRException
{
if (groups != null && groups.length > 0)
{
byte evaluation = (isFillAll)?JRExpression.EVALUATION_DEFAULT:JRExpression.EVALUATION_OLD;
preventOrphanFootersMinLevel = null;
for (int i = groups.length - 1; i >= 0; i--)
{
JRFillGroup group = groups[i];
if (
(isFillAll || group.hasChanged())
&& group.isPreventOrphanFooter()
)
{
// we need to decide up-front if during the current group footers printing,
// there are any potential orphans to take care of
preventOrphanFootersMinLevel = i;
break;
}
}
for (int i = groups.length - 1; i >= 0; i--)
{
JRFillGroup group = groups[i];
crtGroupFootersLevel = i;
if (
preventOrphanFootersMinLevel != null
&& crtGroupFootersLevel < preventOrphanFootersMinLevel
)
{
// reset the element ranges when we get to the group footers
// that are outer to the ones for which we need to prevent orphans;
// these ranges act like flags to signal we need to deal with orphans
orphanGroupFooterDetailElementRange = null;
orphanGroupFooterElementRange = null;
detailElementRange = null; // put this line here just to have the same trio everywhere; could not find a case when this line really matters
}
if (isFillAll || group.hasChanged())
{
fillGroupFooter(group, evaluation);
// regardless of whether the fillGroupFooter was printed or not,
// we just need to mark the end of the group
group.setKeepTogetherElementRange(null);
}
}
// resetting orphan footer element ranges because all group footers have been rendered
orphanGroupFooterDetailElementRange = null;
orphanGroupFooterElementRange = null;
detailElementRange = null; // put this line here just to have the same trio everywhere; could not find a case when this line really matters
// we need to take care of groupFooterPositionElementRange here because all groups footers have been
// rendered and we need to consume remaining space before next groups start;
//
// but we don't process the last groupFooterPositionElementRange when the report ends (isFillAll true),
// because it will be dealt with during summary rendering, depending on whether a last page footer exists or not
if (
!isFillAll
&& groupFooterPositionElementRange != null
)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
groupFooterPositionElementRange = null;
// update the offsetY to signal there is no more space left at the bottom after forcing the footer
offsetY = columnFooterOffsetY;
}
}
}
/**
*
*/
@continuable
private void fillGroupFooter(JRFillGroup group, byte evaluation) throws JRException
{
JRFillSection groupFooterSection = (JRFillSection)group.getGroupFooterSection();
if (log.isDebugEnabled() && !groupFooterSection.isEmpty())
{
log.debug("Fill " + fillerId + ": " + group.getName() + " footer at " + offsetY);
}
JRFillBand[] groupFooterBands = groupFooterSection.getFillBands();
for (int i = 0; i < groupFooterBands.length; i++)
{
JRFillBand groupFooterBand = groupFooterBands[i];
groupFooterBand.evaluatePrintWhenExpression(evaluation);
if (groupFooterBand.isToPrint())
{
if (
preventOrphanFootersMinLevel != null
&& crtGroupFootersLevel >= preventOrphanFootersMinLevel
&& orphanGroupFooterDetailElementRange == null
)
{
// the detail element range can't be null here, unless there is no detail printing;
// keeping the detail element range in this separate variable signals we are currently
// dealing with orphan group footers
orphanGroupFooterDetailElementRange = detailElementRange;
}
if (
groupFooterBand.getBreakHeight() > columnFooterOffsetY - offsetY
)
{
fillColumnBreak(evaluation, evaluation); // using same evaluation for both side of the break is ok here
}
if (
groupFooterPositionElementRange == null
&& group.getFooterPositionValue() != FooterPositionEnum.NORMAL
)
{
groupFooterPositionElementRange =
new SimpleGroupFooterElementRange(
new SimpleElementRange(getCurrentPage(), columnIndex, offsetY),
group.getFooterPositionValue()
);
}
if (groupFooterPositionElementRange != null)
{
// keep the current group footer position because it will be needed
// in case the band breaks and the group footer element range needs to
// be recreated on the new page
groupFooterPositionElementRange.setCurrentFooterPosition(group.getFooterPositionValue());
}
if (orphanGroupFooterDetailElementRange != null)
{
ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
if (orphanGroupFooterElementRange == null)
{
orphanGroupFooterElementRange = newElementRange;
}
else
{
ElementRangeUtil.expandOrIgnore(orphanGroupFooterElementRange, newElementRange);
}
}
fillColumnBand(groupFooterBand, evaluation, false);
ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
if (groupFooterPositionElementRange != null)
{
ElementRangeUtil.expandOrIgnore(groupFooterPositionElementRange.getElementRange(), newElementRange);
switch (group.getFooterPositionValue())
{
case STACK_AT_BOTTOM :
{
groupFooterPositionElementRange.setMasterFooterPosition(FooterPositionEnum.STACK_AT_BOTTOM);
break;
}
case FORCE_AT_BOTTOM :
{
groupFooterPositionElementRange.setMasterFooterPosition(FooterPositionEnum.FORCE_AT_BOTTOM);
break;
}
case COLLATE_AT_BOTTOM :
{
break;
}
case NORMAL :
default :
{
// only StackAtBottom and CollateAtBottom can get here
if (groupFooterPositionElementRange.getMasterFooterPosition() == FooterPositionEnum.COLLATE_AT_BOTTOM)
{
groupFooterPositionElementRange = null;
}
break;
}
}
}
isFirstPageBand = false;
isFirstColumnBand = false;
}
}
// we need to perform ForceAtBottom here because only the group footer as a whole should be forced to bottom,
// not the individual bands in this footer section;
// also, when forcing a group footer to bottom, we consider the normal/current columnFooterOffsetY, because it is impossible
// to tell at this point if this would be the last page or not (last page footer)
if (
groupFooterPositionElementRange != null
&& groupFooterPositionElementRange.getMasterFooterPosition() == FooterPositionEnum.FORCE_AT_BOTTOM
)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
groupFooterPositionElementRange = null;
// update the offsetY to signal there is no more space left at the bottom after forcing the footer
offsetY = columnFooterOffsetY;
}
isNewPage = false;
isNewColumn = false;
group.setHeaderPrinted(false);
group.setFooterPrinted(true);
}
/**
*
*/
private void fillColumnFooter(byte evaluation) throws JRException
{
if (log.isDebugEnabled() && !columnFooter.isEmpty())
{
log.debug("Fill " + fillerId + ": column footer at " + offsetY);
}
setOffsetX();
/*
if (!isSubreport)
{
offsetY = columnFooterOffsetY;
}
*/
if (isSubreport() && !isSubreportRunToBottom() && columnIndex == 0)
{
columnFooterOffsetY = offsetY;
}
int oldOffsetY = offsetY;
if (!isFloatColumnFooter && !ignorePagination)
{
offsetY = columnFooterOffsetY;
}
// we first let the column footer Y offset calculations to occur normally above,
// before attempting to deal with existing groupFooterPositionElementRange
if (groupFooterPositionElementRange != null)
{
// all types of footer position can get here (StackAtBottom, CollapseAtBottom and ForceAtBottom);
// ForceAtBottom group footer element ranges could reach this point in case multi-band group footer gets
// split across a column/page break; remaining bands in such group footer would be dealt at the end
// of the group footer filling method (see fillGroupFooter() method above)
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
groupFooterPositionElementRange = null;
// we do not need to set the offsetY because it has already been set properly earlier in this method;
}
columnFooter.evaluatePrintWhenExpression(evaluation);
if (columnFooter.isToPrint())
{
if (isFloatColumnFooter && !ignorePagination)
{
floatColumnFooterElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
}
fillFixedBand(columnFooter, evaluation);
if (floatColumnFooterElementRange != null)
{
floatColumnFooterElementRange.expand(offsetY);
}
}
if (isFloatColumnFooter && !ignorePagination)
{
offsetY += columnFooterOffsetY - oldOffsetY;
}
}
/**
*
*/
private void fillPageFooter(byte evaluation) throws JRException
{
JRFillBand crtPageFooter = getCurrentPageFooter();
if (log.isDebugEnabled() && !crtPageFooter.isEmpty())
{
log.debug("Fill " + fillerId + ": " + (isLastPageFooter ? "last " : "") + "page footer at " + offsetY);
}
offsetX = leftMargin;
if ((!isSubreport() || isSubreportRunToBottom()) && !ignorePagination)
{
offsetY = pageHeight - crtPageFooter.getHeight() - bottomMargin;
}
crtPageFooter.evaluatePrintWhenExpression(evaluation);
if (crtPageFooter.isToPrint())
{
fillFixedBand(crtPageFooter, evaluation);
}
}
/**
*
*/
@continuable
private void fillSummary() throws JRException
{
if (log.isDebugEnabled() && !summary.isEmpty())
{
log.debug("Fill " + fillerId + ": summary at " + offsetY);
}
offsetX = leftMargin;
if (lastPageFooter == missingFillBand)
{
if (
!isSummaryNewPage
&& columnIndex == 0
&& summary.getBreakHeight() <= columnFooterOffsetY - offsetY
)
{
fillSummaryNoLastFooterSamePage();
}
else
{
fillSummaryNoLastFooterNewPage();
}
}
else
{
if (isSummaryWithPageHeaderAndFooter)
{
fillSummaryWithLastFooterAndPageBands();
}
else
{
fillSummaryWithLastFooterNoPageBands();
}
}
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
resolveReportBoundElements();
if (isMasterReport())
{
resolveMasterBoundElements();
}
}
/**
*
*/
@continuable
private void fillSummaryNoLastFooterSamePage() throws JRException
{
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
// deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
if (groupFooterPositionElementRange != null)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
offsetY = columnFooterOffsetY;
// reset the element range here although it will not be checked anymore as the report ends
groupFooterPositionElementRange = null;
}
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
if (isSummaryWithPageHeaderAndFooter)
{
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0)
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
//DONE
}
else
{
//SummaryReport.14 test
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
if (summary.willOverflow())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
if (isSummaryWithPageHeaderAndFooter)
{
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
//DONE
}
else
{
resolveBandBoundElements(summary, JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
}
else
{
//SummaryReport.15 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
/**
*
*/
@continuable
private void fillSummaryNoLastFooterNewPage() throws JRException
{
//SummaryReport.13 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
if (isSummaryWithPageHeaderAndFooter)
{
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
if (isSummaryWithPageHeaderAndFooter)
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
if (isSummaryWithPageHeaderAndFooter)
{
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0)
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
}
//DONE
}
/**
*
*/
@continuable
private void fillSummaryWithLastFooterAndPageBands() throws JRException
{
if (
!isSummaryNewPage
&& columnIndex == 0
&& summary.getBreakHeight() <= columnFooterOffsetY - offsetY
)
{
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
// deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
if (groupFooterPositionElementRange != null)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
offsetY = columnFooterOffsetY;
// reset the element range here although it will not be checked anymore as the report ends
groupFooterPositionElementRange = null;
}
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
else
{
//SummaryReport.8 test
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
if (
!summary.willOverflow()
&& offsetY <= lastPageColumnFooterOffsetY
)
{
setLastPageFooter(true);
}
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
}
/* */
fillSummaryOverflow();
//DONE
}
else
{
//SummaryReport.9 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
setLastPageFooter(true);
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
else if (columnIndex == 0 && offsetY <= lastPageColumnFooterOffsetY)
{
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
//SummaryReport.10 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - pageFooter.getHeight());
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
//DONE
}
else
{
//SummaryReport.11 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
setLastPageFooter(true);
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
else
{
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
//SummaryReport.12 test
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - pageFooter.getHeight());
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
else
{
//SummaryReport.16 test
}
/* */
fillSummaryOverflow();
//DONE
}
}
/**
*
*/
@continuable
private void fillSummaryWithLastFooterNoPageBands() throws JRException
{
if (
!isSummaryNewPage
&& columnIndex == 0
&& summary.getBreakHeight() <= lastPageColumnFooterOffsetY - offsetY
)
{
setLastPageFooter(true);
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
// deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
if (groupFooterPositionElementRange != null)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
offsetY = columnFooterOffsetY;
// reset the element range here although it will not be checked anymore as the report ends
groupFooterPositionElementRange = null;
}
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
else
{
//SummaryReport.1 test
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
/* */
fillSummaryOverflow();
//DONE
}
else
{
//SummaryReport.2 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
else if (
!isSummaryNewPage
&& columnIndex == 0
&& summary.getBreakHeight() <= columnFooterOffsetY - offsetY
)
{
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
// deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
if (groupFooterPositionElementRange != null)
{
ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
offsetY = columnFooterOffsetY;
// reset the element range here although it will not be checked anymore as the report ends
groupFooterPositionElementRange = null;
}
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
if (offsetY <= lastPageColumnFooterOffsetY)
{
setLastPageFooter(true);
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
else
{
fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
setLastPageFooter(true);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
lastPageColumnFooterOffsetY - offsetY
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
}
else
{
//SummaryReport.3 test
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
setLastPageFooter(true);
if (summary.willOverflow())
{
printBand = summary.fill(lastPageColumnFooterOffsetY - offsetY);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
/* */
fillSummaryOverflow();
//DONE
}
else
{
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
// it will be either the one in fillPageBreak or the following
if (offsetY > lastPageColumnFooterOffsetY)
{
//SummaryReport.5 test
fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
}
else
{
//SummaryReport.4 test
}
setLastPageFooter(true);
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
//DONE
}
}
else if (columnIndex == 0 && offsetY <= lastPageColumnFooterOffsetY)
{
//SummaryReport.6 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
setLastPageFooter(true);
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
}
//DONE
}
else
{
//SummaryReport.7 test
// do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
//fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
setLastPageFooter(true);
if (isSummaryNewPage)
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
/* */
fillSummaryOverflow();
}
//DONE
}
else
{
summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (summary.isToPrint())
{
summary.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
summary.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
else
{
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
/* */
fillSummaryOverflow();
}
else
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
//DONE
}
}
}
/**
*
*/
@continuable
private void fillSummaryOverflow() throws JRException
{
while (summary.willOverflow())
{
if (isSummaryWithPageHeaderAndFooter)
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
if (isSummaryWithPageHeaderAndFooter)
{
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
resolveBandBoundElements(summary, JRExpression.EVALUATION_DEFAULT);
if (isSummaryWithPageHeaderAndFooter)
{
if (offsetY > pageHeight - bottomMargin - lastPageFooter.getHeight())
{
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
fillPageHeader(JRExpression.EVALUATION_DEFAULT);
}
if (lastPageFooter != missingFillBand)
{
setLastPageFooter(true);
}
fillPageFooter(JRExpression.EVALUATION_DEFAULT);
}
}
/**
*
*/
private void fillBackground() throws JRException
{
if (log.isDebugEnabled() && !background.isEmpty())
{
log.debug("Fill " + fillerId + ": background at " + offsetY);
}
//offsetX = leftMargin;
//if (!isSubreport)
//{
// offsetY = pageHeight - pageFooter.getHeight() - bottomMargin;
//}
if (background.getHeight() <= pageHeight - bottomMargin - offsetY)
{
background.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (background.isToPrint())
{
background.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = background.fill(pageHeight - bottomMargin - offsetY);
fillBand(printBand);
//offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
//FIXMENOW does not have resolveBandBoundElements
}
}
}
/**
*
*/
@continuable
private void addPage(boolean isResetPageNumber) throws JRException
{
if (isSubreport())
{
addPageToParent(false);
}
if (printPage != null)
{
recordUsedPageHeight(offsetY + bottomMargin);
}
printPage = newPage();
printPageContentsWidth = 0;
JRFillVariable pageNumberVar = calculator.getPageNumber();
if (isResetPageNumber)
{
pageNumberVar.setValue(1);
}
else
{
pageNumberVar.setValue(
((Number)pageNumberVar.getValue()).intValue() + 1
);
}
pageNumberVar.setOldValue(pageNumberVar.getValue());
addPage(printPage);
setFirstColumn();
offsetY = topMargin;
isFirstPageBand = true;
isFirstColumnBand = true;
isCrtRecordOnPage = false;
isCrtRecordOnColumn = false;
fillBackground();
}
private void setFirstColumn()
{
columnIndex = 0;
offsetX = leftMargin;
setColumnNumberVar();
}
private void setColumnNumberVar()
{
JRFillVariable columnNumber = calculator.getColumnNumber();
columnNumber.setValue(columnIndex + 1);
columnNumber.setOldValue(columnNumber.getValue());
}
/**
*
*/
@continuable
private void fillPageBreak(
boolean isResetPageNumber,
byte evalPrevPage,
byte evalNextPage,
boolean isReprintGroupHeaders
) throws JRException
{
if (isCreatingNewPage)
{
throw
new JRException(
EXCEPTION_MESSAGE_KEY_INFINITE_LOOP_CREATING_NEW_PAGE,
(Object[])null
);
}
if (groups != null)
{
for (JRFillGroup group : groups)
{
if (group.getKeepTogetherElementRange() != null)
{
group.getKeepTogetherElementRange().expand(offsetY);
}
}
}
FooterPositionEnum groupFooterPositionForOverflow = null;
if (groupFooterPositionElementRange != null)
{
groupFooterPositionForOverflow = groupFooterPositionElementRange.getCurrentFooterPosition();
// we are during group footers filling, otherwise this element range would have been null;
// adding the content of the group footer band that is currently breaking
groupFooterPositionElementRange.getElementRange().expand(offsetY);
}
if (orphanGroupFooterElementRange != null)
{
// we are during a group footer filling and footers already started to print,
// so the current expansion applies to the group footer element range, not the detail element range
orphanGroupFooterElementRange.expand(offsetY);
}
else if (orphanGroupFooterDetailElementRange != null)
{
// we are during a group footer filling, but footers did not yet start to print,
// so the current expansion applies to the detail element range
orphanGroupFooterDetailElementRange.expand(offsetY);
}
isCreatingNewPage = true;
fillColumnFooter(evalPrevPage);
fillPageFooter(evalPrevPage);
resolveGroupBoundElements(evalPrevPage, false);
resolveColumnBoundElements(evalPrevPage);
resolvePageBoundElements(evalPrevPage);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
JRFillGroup keepTogetherGroup = getKeepTogetherGroup();
ElementRange elementRangeToMove = null;
ElementRange elementRangeToMove2 = null; // we don't have more than two possible element ranges to move; at least for now
if (keepTogetherGroup != null)
{
elementRangeToMove = keepTogetherGroup.getKeepTogetherElementRange();
}
else if (orphanGroupFooterDetailElementRange != null)
{
elementRangeToMove = orphanGroupFooterDetailElementRange;
elementRangeToMove2 = orphanGroupFooterElementRange;
}
if (floatColumnFooterElementRange != null && elementRangeToMove != null)
{
ElementRangeUtil.moveContent(floatColumnFooterElementRange, elementRangeToMove.getTopY());
}
// remove second range first, otherwise element indexes would become out of range
ElementRangeContents elementsToMove2 = null;
if (elementRangeToMove2 != null)
{
elementsToMove2 = ElementRangeUtil.removeContent(elementRangeToMove2, delayedActions);
}
ElementRangeContents elementsToMove = null;
if (elementRangeToMove != null)
{
elementsToMove = ElementRangeUtil.removeContent(elementRangeToMove, delayedActions);
}
addPage(isResetPageNumber);
fillPageHeader(evalNextPage);
fillColumnHeader(evalNextPage);
if (isReprintGroupHeaders)
{
fillGroupHeadersReprint(evalNextPage, true);
ElementRange keepTogetherElementRange = keepTogetherGroup == null ? null : keepTogetherGroup.getKeepTogetherElementRange();
if (
keepTogetherElementRange != null
&& offsetY > keepTogetherElementRange.getTopY()
)
{
throw new JRException(EXCEPTION_MESSAGE_KEY_KEEP_TOGETHER_CONTENT_DOES_NOT_FIT, (Object[]) null);
}
}
// reseting all movable element ranges
orphanGroupFooterDetailElementRange = null;
orphanGroupFooterElementRange = null;
detailElementRange = null;
if (keepTogetherGroup != null)
{
keepTogetherGroup.setKeepTogetherElementRange(null);
}
if (elementRangeToMove != null)
{
ElementRangeUtil.addContent(
printPage,
currentPageIndex(),
elementsToMove,
//regardless whether there was page break or column break, the X offset needs to account for columnIndex difference
(columnIndex - elementRangeToMove.getColumnIndex()) * (columnSpacing + columnWidth),
offsetY - elementRangeToMove.getTopY(),
delayedActions
);
offsetY = offsetY + elementRangeToMove.getBottomY() - elementRangeToMove.getTopY();
if (elementRangeToMove2 != null)
{
ElementRangeUtil.addContent(
printPage,
currentPageIndex(),
elementsToMove2,
//regardless whether there was page break or column break, the X offset needs to account for columnIndex difference
(columnIndex - elementRangeToMove2.getColumnIndex()) * (columnSpacing + columnWidth),
offsetY - elementRangeToMove2.getTopY(),
delayedActions
);
offsetY = offsetY + elementRangeToMove2.getBottomY() - elementRangeToMove2.getTopY();
}
isFirstPageBand = false;
isFirstColumnBand = false;
}
else if (
groupFooterPositionForOverflow != null
&& groupFooterPositionForOverflow != FooterPositionEnum.NORMAL
)
{
// here we are during a group footer filling that broke over onto a new page;
// recreating the group footer element range for the overflow content of the band
groupFooterPositionElementRange =
new SimpleGroupFooterElementRange(
new SimpleElementRange(getCurrentPage(), columnIndex, offsetY),
groupFooterPositionForOverflow
);
}
isCreatingNewPage = false;
}
/**
*
*/
@continuable
private void fillColumnBreak(
byte evalPrevPage,
byte evalNextPage
) throws JRException
{
if (columnIndex == columnCount - 1)
{
fillPageBreak(false, evalPrevPage, evalNextPage, true);
}
else
{
if (groups != null)
{
for (JRFillGroup group : groups)
{
if (group.getKeepTogetherElementRange() != null)
{
group.getKeepTogetherElementRange().expand(offsetY);
}
}
}
FooterPositionEnum groupFooterPositionForOverflow = null;
if (groupFooterPositionElementRange != null)
{
groupFooterPositionForOverflow = groupFooterPositionElementRange.getCurrentFooterPosition();
// we are during group footers filling, otherwise this element range would have been null;
// adding the content of the group footer band that is currently breaking
groupFooterPositionElementRange.getElementRange().expand(offsetY);
}
if (orphanGroupFooterElementRange != null)
{
// we are during a group footer filling and footers already started to print,
// so the current expansion applies to the group footer element range, not the detail element range
orphanGroupFooterElementRange.expand(offsetY);
}
else if (orphanGroupFooterDetailElementRange != null)
{
// we are during a group footer filling, but footers did not yet start to print,
// so the current expansion applies to the detail element range
orphanGroupFooterDetailElementRange.expand(offsetY);
}
fillColumnFooter(evalPrevPage);
resolveGroupBoundElements(evalPrevPage, false);
resolveColumnBoundElements(evalPrevPage);
scriptlet.callBeforeColumnInit();
calculator.initializeVariables(ResetTypeEnum.COLUMN, IncrementTypeEnum.COLUMN);
scriptlet.callAfterColumnInit();
JRFillGroup keepTogetherGroup = getKeepTogetherGroup();
ElementRange elementRangeToMove = null;
ElementRange elementRangeToMove2 = null; // we don't have more than two possible element ranges to move; at least for now
if (keepTogetherGroup != null)
{
elementRangeToMove = keepTogetherGroup.getKeepTogetherElementRange();
}
else if (orphanGroupFooterDetailElementRange != null)
{
elementRangeToMove = orphanGroupFooterDetailElementRange;
elementRangeToMove2 = orphanGroupFooterElementRange;
}
if (floatColumnFooterElementRange != null && elementRangeToMove != null)
{
ElementRangeUtil.moveContent(floatColumnFooterElementRange, elementRangeToMove.getTopY());
}
// remove second range first, otherwise element indexes would become out of range
ElementRangeContents elementsToMove2 = null;
if (elementRangeToMove2 != null)
{
elementsToMove2 = ElementRangeUtil.removeContent(elementRangeToMove2, delayedActions);
}
ElementRangeContents elementsToMove = null;
if (elementRangeToMove != null)
{
elementsToMove = ElementRangeUtil.removeContent(elementRangeToMove, null);
}
columnIndex += 1;
setOffsetX();
offsetY = columnHeaderOffsetY;
isCrtRecordOnColumn = false;
setColumnNumberVar();
fillColumnHeader(evalNextPage);
//if (isReprintGroupHeaders)
{
fillGroupHeadersReprint(evalNextPage, false);
ElementRange keepTogetherElementRange = keepTogetherGroup == null ? null : keepTogetherGroup.getKeepTogetherElementRange();
if (
keepTogetherElementRange != null
&& offsetY > keepTogetherElementRange.getTopY()
)
{
throw new JRException(EXCEPTION_MESSAGE_KEY_KEEP_TOGETHER_CONTENT_DOES_NOT_FIT, (Object[]) null);
}
}
// reseting all movable element ranges
orphanGroupFooterDetailElementRange = null;
orphanGroupFooterElementRange = null;
detailElementRange = null;
if (keepTogetherGroup != null)
{
keepTogetherGroup.setKeepTogetherElementRange(null);
}
if (elementRangeToMove != null)
{
ElementRangeUtil.addContent(
printPage,
currentPageIndex(),
elementsToMove,
//regardless whether there was page break or column break, the X offset needs to account for columnIndex difference
(columnIndex - elementRangeToMove.getColumnIndex()) * (columnSpacing + columnWidth),
offsetY - elementRangeToMove.getTopY(),
delayedActions
);
offsetY = offsetY + elementRangeToMove.getBottomY() - elementRangeToMove.getTopY();
if (elementRangeToMove2 != null)
{
ElementRangeUtil.addContent(
printPage,
currentPageIndex(),
elementsToMove2,
//regardless whether there was page break or column break, the X offset needs to account for columnIndex difference
(columnIndex - elementRangeToMove2.getColumnIndex()) * (columnSpacing + columnWidth),
offsetY - elementRangeToMove2.getTopY(),
delayedActions
);
offsetY = offsetY + elementRangeToMove2.getBottomY() - elementRangeToMove2.getTopY();
}
isFirstPageBand = false;
isFirstColumnBand = false;
}
else if (
groupFooterPositionForOverflow != null
&& groupFooterPositionForOverflow != FooterPositionEnum.NORMAL
)
{
// here we are during a group footer filling that broke over onto a new column;
// recreating the group footer element range for the overflow content of the band
groupFooterPositionElementRange =
new SimpleGroupFooterElementRange(
new SimpleElementRange(getCurrentPage(), columnIndex, offsetY),
groupFooterPositionForOverflow
);
}
}
}
/**
*
*/
@continuable
protected void fillColumnBand(JRFillBand band, byte evaluation, boolean recalculateVariables) throws JRException
{
band.evaluate(evaluation);
JRPrintBand printBand = band.fill(columnFooterOffsetY - offsetY);
if (band.willOverflow())
{
boolean toRefill = band.isSplitPrevented() && !band.isSplitTypePreventInhibited();
if (!toRefill)
{
if (groups != null)
{
// this works even for group headers and footers, not only detail,
// because outer groups keep together is honored, while for the
// inner keep together groups, the element range would be null
// in-between parent group breaks
for (JRFillGroup group : groups)
{
if (
group.getKeepTogetherElementRange() != null
&& (group.isKeepTogether() || !group.hasMinDetails())
)
{
toRefill = true;
break;
}
}
}
}
if (!toRefill)
{
if (orphanGroupFooterDetailElementRange != null)
{
toRefill = true;
}
}
if (toRefill)
{
fillColumnBreak(
evaluation == JRExpression.EVALUATION_DEFAULT
? (isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD)
: evaluation,
evaluation
);
if (recalculateVariables)
{
@SuppressWarnings("deprecation")
boolean isLegacyBandEvaluationEnabled = getFillContext().isLegacyBandEvaluationEnabled();
if (!isLegacyBandEvaluationEnabled)
{
mainDataset.revertVariablesToOldValues();
calculator.recalculateVariables();
}
}
printBand = band.refill(evaluation, columnFooterOffsetY - offsetY);
}
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
isCrtRecordOnColumn = isCrtRecordOnPage;
while (band.willOverflow())
{
// this overflow here is special in the sense that it is the overflow of a detail band or group header or footer,
// which are the only bands that are involved with movable element ranges such as keep together, footer position or orphan footer;
// it is also special in the sense that it is an overflow after the band actually generated some content on the current page/column
// and is not an early overflow like the one occurring when the band does not fit with its declared height or is non-splitting band;
// having said that, it is OK to be more specific about the type of overflow here and only deal with non-white-space overflows of the band,
// as they are the only ones which actually need to introduce a page/column break and continue rendering their remaining elements;
// white space band overflows do not render anything on the next page/column and don't even preserve their remaining white space (historical behavior);
// avoiding a page/column break here in case of white space overflows helps with preserving the detail element range, which would
// thus be moved onto the new page/column as a non-breaking detail, if orphan footers follow;
// a page/column break here would cause the existing detail element range to be discarded (lost on subsequent element range expand),
// and thus it would not be moved in case orphan footer follows,
// even if nothing gets rendered by this detail on the next page/column
if (band.willOverflowWithElements())
{
fillColumnBreak(
evaluation == JRExpression.EVALUATION_DEFAULT
? (isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD)
: evaluation,
evaluation
);
}
// we continue filling band overflow normally, because even in case of white space band overflow, nothing gets actually rendered
// and the offsetY remains unchanged;
// but we need to do this because the isOverflow flag would eventually be set to false and thus the current band rendering would end,
// bringing the band into a state ready for the next filling
printBand = band.fill(columnFooterOffsetY - offsetY);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
isCrtRecordOnColumn = isCrtRecordOnPage;
}
resolveBandBoundElements(band, evaluation);
}
/**
*
*/
protected void fillFixedBand(JRFillBand band, byte evaluation) throws JRException
{
band.evaluate(evaluation);
JRPrintBand printBand = band.fill();
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
isCrtRecordOnColumn = isCrtRecordOnPage;
resolveBandBoundElements(band, evaluation);
}
/**
*
*/
private void setNewPageColumnInBands()
{
title.setNewPageColumn(true);
pageHeader.setNewPageColumn(true);
columnHeader.setNewPageColumn(true);
detailSection.setNewPageColumn(true);
columnFooter.setNewPageColumn(true);
pageFooter.setNewPageColumn(true);
lastPageFooter.setNewPageColumn(true);
summary.setNewPageColumn(true);
noData.setNewPageColumn(true);
if (groups != null && groups.length > 0)
{
for(int i = 0; i < groups.length; i++)
{
((JRFillSection)groups[i].getGroupHeaderSection()).setNewPageColumn(true);
((JRFillSection)groups[i].getGroupFooterSection()).setNewPageColumn(true);
}
}
}
/**
*
*/
private void setNewGroupInBands(JRGroup group)
{
title.setNewGroup(group, true);
pageHeader.setNewGroup(group, true);
columnHeader.setNewGroup(group, true);
detailSection.setNewGroup(group, true);
columnFooter.setNewGroup(group, true);
pageFooter.setNewGroup(group, true);
lastPageFooter.setNewGroup(group, true);
summary.setNewGroup(group, true);
noData.setNewGroup(group, true);
if (groups != null && groups.length > 0)
{
for(int i = 0; i < groups.length; i++)
{
((JRFillSection)groups[i].getGroupHeaderSection()).setNewGroup(group, true);
((JRFillSection)groups[i].getGroupFooterSection()).setNewGroup(group, true);
}
}
}
/**
*
*/
private JRFillBand getCurrentPageFooter()
{
return isLastPageFooter ? lastPageFooter : pageFooter;
}
/**
*
*/
private void setLastPageFooter(boolean isLastPageFooter)
{
this.isLastPageFooter = isLastPageFooter;
if (isLastPageFooter)
{
columnFooterOffsetY = lastPageColumnFooterOffsetY;
}
}
/**
*
*/
@continuable
private void fillNoData() throws JRException
{
if (log.isDebugEnabled() && !noData.isEmpty())
{
log.debug("Fill " + fillerId + ": noData at " + offsetY);
}
noData.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
if (noData.isToPrint())
{
while (noData.getBreakHeight() > pageHeight - bottomMargin - offsetY)
{
addPage(false);
}
noData.evaluate(JRExpression.EVALUATION_DEFAULT);
JRPrintBand printBand = noData.fill(pageHeight - bottomMargin - offsetY);
if (noData.willOverflow() && noData.isSplitPrevented() && !noData.isSplitTypePreventInhibited())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand =
noData.refill(
JRExpression.EVALUATION_DEFAULT,
pageHeight - bottomMargin - offsetY
);
}
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
while (noData.willOverflow())
{
resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
scriptlet.callBeforePageInit();
calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
scriptlet.callAfterPageInit();
addPage(false);
printBand = noData.fill(pageHeight - bottomMargin - offsetY);
fillBand(printBand);
offsetY += printBand.getHeight();
isCrtRecordOnPage = true;
isCrtRecordOnColumn = true;
}
resolveBandBoundElements(noData, JRExpression.EVALUATION_DEFAULT);
}
}
/**
*
*/
private void setOffsetX()
{
if (columnDirection == RunDirectionEnum.RTL)
{
offsetX = pageWidth - rightMargin - columnWidth - columnIndex * (columnSpacing + columnWidth);
}
else
{
offsetX = leftMargin + columnIndex * (columnSpacing + columnWidth);
}
}
}