first commit
This commit is contained in:
@@ -0,0 +1,434 @@
|
||||
package net.sf.jasperreports.engine.fill;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.sf.jasperreports.engine.JRConditionalStyle;
|
||||
import net.sf.jasperreports.engine.JRElement;
|
||||
import net.sf.jasperreports.engine.JRElementGroup;
|
||||
import net.sf.jasperreports.engine.JRException;
|
||||
import net.sf.jasperreports.engine.JRFrame;
|
||||
import net.sf.jasperreports.engine.JROrigin;
|
||||
import net.sf.jasperreports.engine.JRPrintElement;
|
||||
import net.sf.jasperreports.engine.JRPrintElementContainer;
|
||||
import net.sf.jasperreports.engine.JRReportFont;
|
||||
import net.sf.jasperreports.engine.JRStyle;
|
||||
import net.sf.jasperreports.engine.base.JRBaseStyle;
|
||||
import net.sf.jasperreports.engine.util.JRStyleResolver;
|
||||
|
||||
public abstract class JRFillElementContainer extends JRFillElementGroup {
|
||||
protected JRBaseFiller filler;
|
||||
|
||||
private JRFillElement[] ySortedElements = null;
|
||||
|
||||
private JRFillElement[] stretchElements = null;
|
||||
|
||||
private JRFillElement[] bandBottomElements = null;
|
||||
|
||||
private JRFillElement[] removableElements = null;
|
||||
|
||||
private boolean willOverflow = false;
|
||||
|
||||
protected boolean isOverflow = false;
|
||||
|
||||
private int stretchHeight = 0;
|
||||
|
||||
private int firstY = 0;
|
||||
|
||||
protected JRFillElement firstYElement = null;
|
||||
|
||||
protected final JRFillExpressionEvaluator expressionEvaluator;
|
||||
|
||||
protected JRFillElement[] deepElements;
|
||||
|
||||
protected Set stylesToEvaluate = new HashSet();
|
||||
|
||||
protected Map evaluatedStyles = new HashMap();
|
||||
|
||||
protected boolean hasPrintWhenOverflowElement;
|
||||
|
||||
protected JRFillElementContainer(JRBaseFiller filler, JRElementGroup container, JRFillObjectFactory factory) {
|
||||
super(container, factory);
|
||||
this.expressionEvaluator = factory.getExpressionEvaluator();
|
||||
initDeepElements();
|
||||
this.filler = filler;
|
||||
}
|
||||
|
||||
protected JRFillElementContainer(JRFillElementContainer container, JRFillCloneFactory factory) {
|
||||
super(container, factory);
|
||||
this.expressionEvaluator = container.expressionEvaluator;
|
||||
initDeepElements();
|
||||
this.filler = container.filler;
|
||||
}
|
||||
|
||||
private void initDeepElements() {
|
||||
if (this.elements == null) {
|
||||
this.deepElements = new JRFillElement[0];
|
||||
} else {
|
||||
List deepElementsList = new ArrayList(this.elements.length);
|
||||
collectDeepElements((JRElement[])this.elements, deepElementsList);
|
||||
this.deepElements = new JRFillElement[deepElementsList.size()];
|
||||
deepElementsList.toArray((Object[])this.deepElements);
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectDeepElements(JRElement[] elements, List deepElementsList) {
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
JRElement element = elements[i];
|
||||
deepElementsList.add(element);
|
||||
if (element instanceof JRFillFrame) {
|
||||
JRFrame frame = (JRFrame)element;
|
||||
collectDeepElements(frame.getElements(), deepElementsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final void initElements() {
|
||||
this.hasPrintWhenOverflowElement = false;
|
||||
if (this.elements != null && this.elements.length > 0) {
|
||||
List sortedElemsList = new ArrayList();
|
||||
List stretchElemsList = new ArrayList();
|
||||
List bandBottomElemsList = new ArrayList();
|
||||
List removableElemsList = new ArrayList();
|
||||
for (int i = 0; i < this.elements.length; i++) {
|
||||
JRFillElement element = this.elements[i];
|
||||
sortedElemsList.add(element);
|
||||
if (element.getPositionType() == 3)
|
||||
bandBottomElemsList.add(element);
|
||||
if (element.getStretchType() != 0)
|
||||
stretchElemsList.add(element);
|
||||
if (element.isRemoveLineWhenBlank())
|
||||
removableElemsList.add(element);
|
||||
if (element.isPrintWhenDetailOverflows())
|
||||
this.hasPrintWhenOverflowElement = true;
|
||||
}
|
||||
Collections.sort(sortedElemsList, new JRYComparator());
|
||||
this.ySortedElements = new JRFillElement[this.elements.length];
|
||||
sortedElemsList.toArray(this.ySortedElements);
|
||||
this.stretchElements = new JRFillElement[stretchElemsList.size()];
|
||||
stretchElemsList.toArray(this.stretchElements);
|
||||
this.bandBottomElements = new JRFillElement[bandBottomElemsList.size()];
|
||||
bandBottomElemsList.toArray(this.bandBottomElements);
|
||||
this.removableElements = new JRFillElement[removableElemsList.size()];
|
||||
removableElemsList.toArray(this.removableElements);
|
||||
}
|
||||
setDependentElements();
|
||||
setElementsBandBottomY();
|
||||
}
|
||||
|
||||
protected final void setElementsBandBottomY() {
|
||||
if (this.elements != null && this.elements.length > 0)
|
||||
for (int i = 0; i < this.elements.length; i++)
|
||||
this.elements[i].setBandBottomY(getContainerHeight() - this.elements[i].getY() - this.elements[i].getHeight());
|
||||
}
|
||||
|
||||
private void setDependentElements() {
|
||||
if (this.ySortedElements != null && this.ySortedElements.length > 0)
|
||||
for (int i = 0; i < this.ySortedElements.length - 1; i++) {
|
||||
JRFillElement iElem = this.ySortedElements[i];
|
||||
boolean isBreakElem = iElem instanceof JRFillBreak;
|
||||
for (int j = i + 1; j < this.ySortedElements.length; j++) {
|
||||
JRFillElement jElem = this.ySortedElements[j];
|
||||
int left = Math.min(iElem.getX(), jElem.getX());
|
||||
int right = Math.max(iElem.getX() + iElem.getWidth(), jElem.getX() + jElem.getWidth());
|
||||
if (((isBreakElem && jElem.getPositionType() == 2) || jElem.getPositionType() == 1) && iElem.getY() + iElem.getHeight() <= jElem.getY() && iElem.getWidth() + jElem.getWidth() > right - left)
|
||||
iElem.addDependantElement(jElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void evaluate(byte evaluation) throws JRException {
|
||||
JRElement[] allElements = getElements();
|
||||
if (allElements != null && allElements.length > 0)
|
||||
for (int i = 0; i < allElements.length; i++) {
|
||||
JRFillElement element = (JRFillElement)allElements[i];
|
||||
element.setCurrentEvaluation(evaluation);
|
||||
element.evaluate(evaluation);
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetElements() {
|
||||
if (this.ySortedElements != null && this.ySortedElements.length > 0)
|
||||
for (int i = 0; i < this.ySortedElements.length; i++) {
|
||||
JRFillElement element = this.ySortedElements[i];
|
||||
element.reset();
|
||||
if (!this.isOverflow)
|
||||
element.setAlreadyPrinted(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean willOverflow() {
|
||||
return this.willOverflow;
|
||||
}
|
||||
|
||||
protected void initFill() {
|
||||
this.isOverflow = this.willOverflow;
|
||||
this.firstY = 0;
|
||||
this.firstYElement = null;
|
||||
}
|
||||
|
||||
protected void prepareElements(int availableStretchHeight, boolean isOverflowAllowed) throws JRException {
|
||||
boolean tmpWillOverflow = false;
|
||||
int maxBandStretch = 0;
|
||||
int bandStretch = 0;
|
||||
this.firstY = this.isOverflow ? getContainerHeight() : 0;
|
||||
this.firstYElement = null;
|
||||
boolean isFirstYFound = false;
|
||||
if (this.ySortedElements != null && this.ySortedElements.length > 0)
|
||||
for (int i = 0; i < this.ySortedElements.length; i++) {
|
||||
JRFillElement element = this.ySortedElements[i];
|
||||
tmpWillOverflow = (element.prepare(availableStretchHeight + getElementFirstY(element), this.isOverflow) || tmpWillOverflow);
|
||||
element.moveDependantElements();
|
||||
if (element.isToPrint()) {
|
||||
if (this.isOverflow) {
|
||||
if (element.isReprinted()) {
|
||||
this.firstY = 0;
|
||||
} else if (!isFirstYFound) {
|
||||
this.firstY = element.getY();
|
||||
}
|
||||
isFirstYFound = true;
|
||||
}
|
||||
this.firstYElement = element;
|
||||
bandStretch = element.getRelativeY() + element.getStretchHeight() - getContainerHeight() + element.getBandBottomY();
|
||||
if (bandStretch > maxBandStretch)
|
||||
maxBandStretch = bandStretch;
|
||||
}
|
||||
}
|
||||
if (maxBandStretch > availableStretchHeight + this.firstY)
|
||||
tmpWillOverflow = true;
|
||||
if (tmpWillOverflow) {
|
||||
this.stretchHeight = getContainerHeight() + availableStretchHeight;
|
||||
} else {
|
||||
this.stretchHeight = getContainerHeight() + maxBandStretch;
|
||||
}
|
||||
this.willOverflow = (tmpWillOverflow && isOverflowAllowed);
|
||||
}
|
||||
|
||||
private int getElementFirstY(JRFillElement element) {
|
||||
int elemFirstY;
|
||||
if (!this.isOverflow || this.hasPrintWhenOverflowElement) {
|
||||
elemFirstY = 0;
|
||||
} else if (element.getY() >= this.firstY) {
|
||||
elemFirstY = this.firstY;
|
||||
} else {
|
||||
elemFirstY = element.getY();
|
||||
}
|
||||
return elemFirstY;
|
||||
}
|
||||
|
||||
protected void setStretchHeight(int stretchHeight) {
|
||||
if (stretchHeight > this.stretchHeight)
|
||||
this.stretchHeight = stretchHeight;
|
||||
}
|
||||
|
||||
protected void stretchElements() {
|
||||
if (this.stretchElements != null && this.stretchElements.length > 0)
|
||||
for (int i = 0; i < this.stretchElements.length; i++) {
|
||||
JRFillElement element = this.stretchElements[i];
|
||||
element.stretchElement(this.stretchHeight - getContainerHeight());
|
||||
element.moveDependantElements();
|
||||
}
|
||||
if (this.ySortedElements != null && this.ySortedElements.length > 0)
|
||||
for (int i = 0; i < this.ySortedElements.length; i++) {
|
||||
JRFillElement element = this.ySortedElements[i];
|
||||
element.stretchHeightFinal();
|
||||
}
|
||||
}
|
||||
|
||||
protected int getStretchHeight() {
|
||||
return this.stretchHeight;
|
||||
}
|
||||
|
||||
protected void moveBandBottomElements() {
|
||||
if (this.bandBottomElements != null && this.bandBottomElements.length > 0)
|
||||
for (int i = 0; i < this.bandBottomElements.length; i++) {
|
||||
JRFillElement element = this.bandBottomElements[i];
|
||||
element.setRelativeY(element.getY() + this.stretchHeight - getContainerHeight());
|
||||
element.setToPrint((element.isToPrint() && !this.willOverflow));
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeBlankElements() {
|
||||
JRFillElement[] arrayOfJRFillElement = this.removableElements;
|
||||
if (arrayOfJRFillElement != null && arrayOfJRFillElement.length > 0) {
|
||||
JRFillElement[] arrayOfJRFillElement1 = this.ySortedElements;
|
||||
for (int i = 0; i < arrayOfJRFillElement.length; i++) {
|
||||
int blankHeight;
|
||||
JRFillElement iElem = arrayOfJRFillElement[i];
|
||||
if (iElem.isToPrint()) {
|
||||
blankHeight = iElem.getHeight() - iElem.getStretchHeight();
|
||||
} else {
|
||||
blankHeight = iElem.getHeight();
|
||||
}
|
||||
if (blankHeight > 0 && iElem.getRelativeY() + iElem.getStretchHeight() <= this.stretchHeight && iElem.getRelativeY() >= this.firstY) {
|
||||
int blankY = iElem.getRelativeY() + iElem.getHeight() - blankHeight;
|
||||
boolean isToRemove = true;
|
||||
int j;
|
||||
for (j = 0; j < arrayOfJRFillElement1.length; j++) {
|
||||
JRFillElement jElem = arrayOfJRFillElement1[j];
|
||||
if (iElem != jElem && jElem.isToPrint()) {
|
||||
int top = Math.min(blankY, jElem.getRelativeY());
|
||||
int bottom = Math.max(blankY + blankHeight, jElem.getRelativeY() + jElem.getStretchHeight());
|
||||
if (blankHeight + jElem.getStretchHeight() > bottom - top) {
|
||||
isToRemove = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isToRemove) {
|
||||
for (j = 0; j < arrayOfJRFillElement1.length; j++) {
|
||||
JRFillElement jElem = arrayOfJRFillElement1[j];
|
||||
if (jElem.getRelativeY() >= blankY + blankHeight)
|
||||
jElem.setRelativeY(jElem.getRelativeY() - blankHeight);
|
||||
}
|
||||
this.stretchHeight -= blankHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void fillElements(JRPrintElementContainer printContainer) throws JRException {
|
||||
JRElement[] allElements = getElements();
|
||||
if (allElements != null && allElements.length > 0)
|
||||
for (int i = 0; i < allElements.length; i++) {
|
||||
JRFillElement element = (JRFillElement)allElements[i];
|
||||
element.setRelativeY(element.getRelativeY() - this.firstY);
|
||||
if (element.getRelativeY() + element.getStretchHeight() > this.stretchHeight)
|
||||
element.setToPrint(false);
|
||||
element.setAlreadyPrinted((element.isToPrint() || element.isAlreadyPrinted()));
|
||||
if (element.isToPrint()) {
|
||||
JRPrintElement printElement = element.fill();
|
||||
if (printElement != null) {
|
||||
printContainer.addElement(printElement);
|
||||
if (element instanceof JRFillSubreport) {
|
||||
JRFillSubreport subreport = (JRFillSubreport)element;
|
||||
List fonts = subreport.subreportFiller.getJasperPrint().getFontsList();
|
||||
for (int j = 0; j < fonts.size(); j++)
|
||||
this.filler.getJasperPrint().addFont(fonts.get(j), true);
|
||||
List styles = subreport.subreportFiller.getJasperPrint().getStylesList();
|
||||
for (int k = 0; k < styles.size(); k++)
|
||||
this.filler.addPrintStyle(styles.get(k));
|
||||
List origins = subreport.subreportFiller.getJasperPrint().getOriginsList();
|
||||
for (int m = 0; m < origins.size(); m++)
|
||||
this.filler.getJasperPrint().addOrigin(origins.get(m));
|
||||
Collection printElements = subreport.getPrintElements();
|
||||
addSubElements(printContainer, element, printElements);
|
||||
} else if (element instanceof JRFillCrosstab) {
|
||||
List printElements = ((JRFillCrosstab)element).getPrintElements();
|
||||
addSubElements(printContainer, element, printElements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printContainer.setHeight(this.stretchHeight - this.firstY);
|
||||
}
|
||||
|
||||
protected void addSubElements(JRPrintElementContainer printContainer, JRFillElement element, Collection printElements) {
|
||||
if (printElements != null && printElements.size() > 0)
|
||||
for (Iterator it = printElements.iterator(); it.hasNext(); ) {
|
||||
JRPrintElement printElement = it.next();
|
||||
printElement.setX(element.getX() + printElement.getX());
|
||||
printElement.setY(element.getRelativeY() + printElement.getY());
|
||||
printContainer.addElement(printElement);
|
||||
}
|
||||
}
|
||||
|
||||
protected void rewind() throws JRException {
|
||||
if (this.ySortedElements != null && this.ySortedElements.length > 0)
|
||||
for (int i = 0; i < this.ySortedElements.length; i++) {
|
||||
JRFillElement element = this.ySortedElements[i];
|
||||
element.rewind();
|
||||
element.setAlreadyPrinted(false);
|
||||
}
|
||||
this.willOverflow = false;
|
||||
}
|
||||
|
||||
protected int getFirstY() {
|
||||
return this.firstY;
|
||||
}
|
||||
|
||||
protected abstract int getContainerHeight();
|
||||
|
||||
protected void initConditionalStyles() {
|
||||
this.filler.addDefaultStyleListener(new JRBaseFiller.DefaultStyleListener() {
|
||||
private final JRFillElementContainer this$0;
|
||||
|
||||
public void defaultStyleSet(JRStyle style) {
|
||||
JRFillElementContainer.this.collectConditionalStyle(style);
|
||||
}
|
||||
});
|
||||
int i;
|
||||
for (i = 0; i < this.deepElements.length; i++) {
|
||||
JRStyle style = (this.deepElements[i]).initStyle;
|
||||
collectConditionalStyle(style);
|
||||
}
|
||||
if (this.deepElements.length > 0)
|
||||
for (i = 0; i < this.deepElements.length; i++)
|
||||
this.deepElements[i].setConditionalStylesContainer(this);
|
||||
}
|
||||
|
||||
protected void collectConditionalStyle(JRStyle style) {
|
||||
if (style != null)
|
||||
this.stylesToEvaluate.add(style);
|
||||
}
|
||||
|
||||
protected void evaluateConditionalStyles(byte evaluation) throws JRException {
|
||||
for (Iterator it = this.stylesToEvaluate.iterator(); it.hasNext();)
|
||||
evaluateConditionalStyle(it.next(), evaluation);
|
||||
}
|
||||
|
||||
protected JRStyle evaluateConditionalStyle(JRStyle initialStyle, byte evaluation) throws JRException {
|
||||
JRBaseStyle jRBaseStyle;
|
||||
JRStyle consolidatedStyle = initialStyle;
|
||||
StringBuffer code = new StringBuffer();
|
||||
List condStylesToApply = new ArrayList();
|
||||
boolean anyTrue = buildConsolidatedStyle(initialStyle, evaluation, code, condStylesToApply);
|
||||
if (anyTrue) {
|
||||
String consolidatedStyleName = initialStyle.getName() + code.toString();
|
||||
consolidatedStyle = (JRStyle)this.filler.getJasperPrint().getStylesMap().get(consolidatedStyleName);
|
||||
if (consolidatedStyle == null) {
|
||||
jRBaseStyle = new JRBaseStyle(consolidatedStyleName);
|
||||
for (int j = condStylesToApply.size() - 1; j >= 0; j--)
|
||||
JRStyleResolver.appendStyle((JRStyle)jRBaseStyle, condStylesToApply.get(j));
|
||||
this.filler.addPrintStyle((JRStyle)jRBaseStyle);
|
||||
}
|
||||
}
|
||||
this.evaluatedStyles.put(initialStyle, jRBaseStyle);
|
||||
return (JRStyle)jRBaseStyle;
|
||||
}
|
||||
|
||||
protected boolean buildConsolidatedStyle(JRStyle style, byte evaluation, StringBuffer code, List condStylesToApply) throws JRException {
|
||||
boolean anyTrue = false;
|
||||
JRConditionalStyle[] conditionalStyles = style.getConditionalStyles();
|
||||
if (conditionalStyles != null && conditionalStyles.length > 0)
|
||||
for (int j = 0; j < conditionalStyles.length; j++) {
|
||||
boolean condition;
|
||||
JRConditionalStyle conditionalStyle = conditionalStyles[j];
|
||||
Boolean expressionValue = (Boolean)this.expressionEvaluator.evaluate(conditionalStyle.getConditionExpression(), evaluation);
|
||||
if (expressionValue == null) {
|
||||
condition = false;
|
||||
} else {
|
||||
condition = expressionValue.booleanValue();
|
||||
}
|
||||
code.append(condition ? 49 : 48);
|
||||
anyTrue |= condition;
|
||||
if (condition)
|
||||
condStylesToApply.add(conditionalStyle);
|
||||
}
|
||||
condStylesToApply.add(style);
|
||||
if (style.getStyle() != null)
|
||||
anyTrue |= buildConsolidatedStyle(style.getStyle(), evaluation, code, condStylesToApply);
|
||||
return anyTrue;
|
||||
}
|
||||
|
||||
public JRStyle getEvaluatedConditionalStyle(JRStyle parentStyle) {
|
||||
return (JRStyle)this.evaluatedStyles.get(parentStyle);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user