460 lines
14 KiB
Java
460 lines
14 KiB
Java
package net.sf.jasperreports.engine.fill;
|
|
|
|
import java.awt.Color;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import net.sf.jasperreports.crosstabs.JRCellContents;
|
|
import net.sf.jasperreports.engine.JRBox;
|
|
import net.sf.jasperreports.engine.JRBoxContainer;
|
|
import net.sf.jasperreports.engine.JRDefaultStyleProvider;
|
|
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.JRLineBox;
|
|
import net.sf.jasperreports.engine.JRPrintElement;
|
|
import net.sf.jasperreports.engine.JRPrintFrame;
|
|
import net.sf.jasperreports.engine.JRStyle;
|
|
import net.sf.jasperreports.engine.JRStyleContainer;
|
|
import net.sf.jasperreports.engine.JRStyleSetter;
|
|
import net.sf.jasperreports.engine.util.LineBoxWrapper;
|
|
import org.apache.commons.collections.ReferenceMap;
|
|
|
|
public class JRFillCellContents extends JRFillElementContainer implements JRCellContents, JRFillCloneable, JRStyleSetter {
|
|
private final Map transformedContentsCache;
|
|
|
|
private final Map boxContentsCache;
|
|
|
|
private final JRClonePool clonePool;
|
|
|
|
private JRFillCellContents original;
|
|
|
|
private final JRCellContents parentCell;
|
|
|
|
private JRLineBox lineBox;
|
|
|
|
private int height;
|
|
|
|
private int width;
|
|
|
|
private int x;
|
|
|
|
private int y;
|
|
|
|
private int verticalSpan;
|
|
|
|
private byte verticalPositionType = 1;
|
|
|
|
private Map templateFrames;
|
|
|
|
private JRDefaultStyleProvider defaultStyleProvider;
|
|
|
|
private JRStyle initStyle;
|
|
|
|
public JRFillCellContents(JRBaseFiller filler, JRCellContents cell, JRFillObjectFactory factory) {
|
|
super(filler, (JRElementGroup)cell, factory);
|
|
this.defaultStyleProvider = factory.getDefaultStyleProvider();
|
|
this.parentCell = cell;
|
|
this.lineBox = cell.getLineBox();
|
|
this.width = cell.getWidth();
|
|
this.height = cell.getHeight();
|
|
factory.registerDelayedStyleSetter(this, (JRStyleContainer)this.parentCell);
|
|
initElements();
|
|
initConditionalStyles();
|
|
initTemplatesMap();
|
|
this.transformedContentsCache = (Map)new ReferenceMap();
|
|
this.boxContentsCache = new HashMap();
|
|
this.clonePool = new JRClonePool(this, true, true);
|
|
}
|
|
|
|
private void initTemplatesMap() {
|
|
this.templateFrames = new HashMap();
|
|
}
|
|
|
|
protected JRFillCellContents(JRFillCellContents cellContents, JRFillCloneFactory factory) {
|
|
super(cellContents, factory);
|
|
this.defaultStyleProvider = cellContents.defaultStyleProvider;
|
|
this.parentCell = cellContents.parentCell;
|
|
this.lineBox = cellContents.lineBox;
|
|
this.width = cellContents.width;
|
|
this.height = cellContents.height;
|
|
this.initStyle = cellContents.initStyle;
|
|
initElements();
|
|
initConditionalStyles();
|
|
this.templateFrames = cellContents.templateFrames;
|
|
this.transformedContentsCache = (Map)new ReferenceMap();
|
|
this.boxContentsCache = new HashMap();
|
|
this.clonePool = new JRClonePool(this, true, true);
|
|
this.verticalPositionType = cellContents.verticalPositionType;
|
|
}
|
|
|
|
public Color getBackcolor() {
|
|
return this.parentCell.getBackcolor();
|
|
}
|
|
|
|
public JRBox getBox() {
|
|
return (JRBox)new LineBoxWrapper(getLineBox());
|
|
}
|
|
|
|
public JRLineBox getLineBox() {
|
|
return this.lineBox;
|
|
}
|
|
|
|
protected void setBox(JRLineBox box) {
|
|
this.lineBox = box;
|
|
initTemplatesMap();
|
|
}
|
|
|
|
public int getHeight() {
|
|
return this.height;
|
|
}
|
|
|
|
public int getWidth() {
|
|
return this.width;
|
|
}
|
|
|
|
protected void setHeight(int height) {
|
|
this.height = height;
|
|
}
|
|
|
|
protected void setWidth(int width) {
|
|
this.width = width;
|
|
}
|
|
|
|
public JRFillCellContents getBoxContents(boolean left, boolean right, boolean top) {
|
|
if (this.lineBox == null)
|
|
return this;
|
|
boolean copyLeft = (left && this.lineBox.getLeftPen().getLineWidth().floatValue() <= 0.0F && this.lineBox.getRightPen().getLineWidth().floatValue() > 0.0F);
|
|
boolean copyRight = (right && this.lineBox.getRightPen().getLineWidth().floatValue() <= 0.0F && this.lineBox.getLeftPen().getLineWidth().floatValue() > 0.0F);
|
|
boolean copyTop = (top && this.lineBox.getTopPen().getLineWidth().floatValue() <= 0.0F && this.lineBox.getBottomPen().getLineWidth().floatValue() > 0.0F);
|
|
if (!copyLeft && !copyRight && !copyTop)
|
|
return this;
|
|
Object key = new BoxContents(copyLeft, copyRight, copyTop);
|
|
JRFillCellContents boxContents = (JRFillCellContents)this.boxContentsCache.get(key);
|
|
if (boxContents == null) {
|
|
boxContents = (JRFillCellContents)createClone();
|
|
JRLineBox newBox = this.lineBox.clone((JRBoxContainer)this.parentCell);
|
|
if (copyLeft)
|
|
newBox.copyLeftPen(this.lineBox.getRightPen());
|
|
if (copyRight)
|
|
newBox.copyRightPen(this.lineBox.getLeftPen());
|
|
if (copyTop)
|
|
newBox.copyTopPen(this.lineBox.getBottomPen());
|
|
boxContents.setBox(newBox);
|
|
this.boxContentsCache.put(key, boxContents);
|
|
}
|
|
return boxContents;
|
|
}
|
|
|
|
public JRFillCellContents getTransformedContents(int newWidth, int newHeight, byte xPosition, byte yPosition) throws JRException {
|
|
if (getHeight() == newHeight && getWidth() == newWidth)
|
|
return this;
|
|
if (newHeight < getHeight() || newWidth < getWidth())
|
|
throw new JRException("Cannot shrink cell contents.");
|
|
Object key = new StretchedContents(newWidth, newHeight, xPosition, yPosition);
|
|
JRFillCellContents transformedCell = (JRFillCellContents)this.transformedContentsCache.get(key);
|
|
if (transformedCell == null) {
|
|
transformedCell = (JRFillCellContents)createClone();
|
|
transformedCell.transform(newWidth, newHeight, xPosition, yPosition);
|
|
transformedCell.setElementsBandBottomY();
|
|
this.transformedContentsCache.put(key, transformedCell);
|
|
}
|
|
return transformedCell;
|
|
}
|
|
|
|
private void transform(int newWidth, int newHeight, byte xPosition, byte yPosition) {
|
|
transformElements(newWidth, newHeight, xPosition, yPosition);
|
|
this.width = newWidth;
|
|
this.height = newHeight;
|
|
}
|
|
|
|
private void transformElements(int newWidth, int newHeight, byte xPosition, byte yPosition) {
|
|
if ((this.height == newHeight || yPosition == 1) && (this.width == newWidth || xPosition == 1))
|
|
return;
|
|
double scaleX = -1.0D;
|
|
int offsetX = 0;
|
|
switch (xPosition) {
|
|
case 2:
|
|
offsetX = (newWidth - this.width) / 2;
|
|
break;
|
|
case 3:
|
|
offsetX = newWidth - this.width;
|
|
break;
|
|
case 4:
|
|
scaleX = newWidth / this.width;
|
|
break;
|
|
}
|
|
double scaleY = -1.0D;
|
|
int offsetY = 0;
|
|
switch (yPosition) {
|
|
case 2:
|
|
offsetY = (newHeight - this.height) / 2;
|
|
break;
|
|
case 3:
|
|
offsetY = newHeight - this.height;
|
|
break;
|
|
case 4:
|
|
scaleY = newHeight / this.height;
|
|
break;
|
|
}
|
|
transformElements(getElements(), scaleX, offsetX, scaleY, offsetY);
|
|
}
|
|
|
|
private static void transformElements(JRElement[] elements, double scaleX, int offsetX, double scaleY, int offsetY) {
|
|
if (elements != null)
|
|
for (int i = 0; i < elements.length; i++) {
|
|
JRFillElement element = (JRFillElement)elements[i];
|
|
if (scaleX != -1.0D) {
|
|
element.setX((int)(element.getX() * scaleX));
|
|
element.setWidth((int)(element.getWidth() * scaleX));
|
|
}
|
|
if (offsetX != 0)
|
|
element.setX(element.getX() + offsetX);
|
|
if (scaleY != -1.0D) {
|
|
element.setY((int)(element.getY() * scaleY));
|
|
element.setHeight((int)(element.getHeight() * scaleY));
|
|
}
|
|
if (offsetY != 0)
|
|
element.setY(element.getY() + offsetY);
|
|
if (element instanceof JRFrame) {
|
|
JRElement[] frameElements = ((JRFrame)element).getElements();
|
|
transformElements(frameElements, scaleX, offsetX, scaleY, offsetY);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void prepare(int availableStretchHeight) throws JRException {
|
|
initFill();
|
|
resetElements();
|
|
prepareElements(availableStretchHeight, true);
|
|
}
|
|
|
|
protected JRPrintFrame fill() throws JRException {
|
|
stretchElements();
|
|
moveBandBottomElements();
|
|
removeBlankElements();
|
|
JRTemplatePrintFrame printCell = new JRTemplatePrintFrame(getTemplateFrame());
|
|
printCell.setX(this.x);
|
|
printCell.setY(this.y);
|
|
printCell.setWidth(this.width);
|
|
fillElements(printCell);
|
|
verticallyPositionElements(printCell);
|
|
printCell.setHeight(getPrintHeight());
|
|
return printCell;
|
|
}
|
|
|
|
private JRTemplateFrame getTemplateFrame() {
|
|
JRStyle style = getStyle();
|
|
JRTemplateFrame template = (JRTemplateFrame)this.templateFrames.get(style);
|
|
if (template == null) {
|
|
template = new JRTemplateFrame(null, this.filler.getJasperPrint().getDefaultStyleProvider(), this);
|
|
this.templateFrames.put(style, template);
|
|
}
|
|
return template;
|
|
}
|
|
|
|
protected void verticallyPositionElements(JRTemplatePrintFrame printCell) {
|
|
int positionOffset;
|
|
switch (this.verticalPositionType) {
|
|
case 2:
|
|
positionOffset = (getStretchHeight() - getContainerHeight()) / 2;
|
|
break;
|
|
case 3:
|
|
positionOffset = getStretchHeight() - getContainerHeight();
|
|
break;
|
|
default:
|
|
positionOffset = 0;
|
|
break;
|
|
}
|
|
if (positionOffset != 0) {
|
|
List printElements = printCell.getElements();
|
|
int positionY = getStretchHeight() - positionOffset;
|
|
boolean outside = false;
|
|
for (Iterator it = printElements.iterator(); !outside && it.hasNext(); ) {
|
|
JRPrintElement element = it.next();
|
|
outside = (element.getY() > positionY);
|
|
}
|
|
if (!outside)
|
|
for (Iterator iterator = printElements.iterator(); iterator.hasNext(); ) {
|
|
JRPrintElement element = iterator.next();
|
|
element.setY(element.getY() + positionOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected int getPrintHeight() {
|
|
return getStretchHeight() + getTopPadding() + getBottomPadding();
|
|
}
|
|
|
|
protected void stretchTo(int stretchHeight) {
|
|
setStretchHeight(stretchHeight - getTopPadding() - getBottomPadding());
|
|
}
|
|
|
|
protected static class BoxContents {
|
|
final boolean left;
|
|
|
|
final boolean right;
|
|
|
|
final boolean top;
|
|
|
|
final int hashCode;
|
|
|
|
public BoxContents(boolean left, boolean right, boolean top) {
|
|
this.left = left;
|
|
this.right = right;
|
|
this.top = top;
|
|
int hash = left ? 1231 : 1237;
|
|
hash = 31 * hash + (right ? 1231 : 1237);
|
|
hash = 31 * hash + (top ? 1231 : 1237);
|
|
this.hashCode = hash;
|
|
}
|
|
|
|
public boolean equals(Object obj) {
|
|
if (obj == this)
|
|
return true;
|
|
BoxContents b = (BoxContents)obj;
|
|
return (b.left == this.left && b.right == this.right && b.top == this.top);
|
|
}
|
|
|
|
public int hashCode() {
|
|
return this.hashCode;
|
|
}
|
|
}
|
|
|
|
protected static class StretchedContents {
|
|
final int newHeight;
|
|
|
|
final int newWidth;
|
|
|
|
final int hashCode;
|
|
|
|
final byte xPosition;
|
|
|
|
final byte yPosition;
|
|
|
|
StretchedContents(int newWidth, int newHeight, byte xPosition, byte yPosition) {
|
|
this.newHeight = newHeight;
|
|
this.newWidth = newWidth;
|
|
this.xPosition = xPosition;
|
|
this.yPosition = yPosition;
|
|
int hash = newHeight;
|
|
hash = 31 * hash + newWidth;
|
|
hash = 31 * hash + xPosition;
|
|
hash = 31 * hash + yPosition;
|
|
this.hashCode = hash;
|
|
}
|
|
|
|
public boolean equals(Object o) {
|
|
if (o == this)
|
|
return true;
|
|
StretchedContents s = (StretchedContents)o;
|
|
return (s.newHeight == this.newHeight && s.newWidth == this.newWidth && s.xPosition == this.xPosition && s.yPosition == this.yPosition);
|
|
}
|
|
|
|
public int hashCode() {
|
|
return this.hashCode;
|
|
}
|
|
}
|
|
|
|
protected int getContainerHeight() {
|
|
return getHeight() - getTopPadding() - getBottomPadding();
|
|
}
|
|
|
|
protected int getTopPadding() {
|
|
return (this.lineBox == null) ? 0 : this.lineBox.getTopPadding().intValue();
|
|
}
|
|
|
|
protected int getBottomPadding() {
|
|
return (this.lineBox == null) ? 0 : this.lineBox.getBottomPadding().intValue();
|
|
}
|
|
|
|
public JRFillCloneable createClone() {
|
|
JRFillCloneFactory factory = new JRFillCloneFactory();
|
|
return createClone(factory);
|
|
}
|
|
|
|
public JRFillCloneable createClone(JRFillCloneFactory factory) {
|
|
return new JRFillCellContents(this, factory);
|
|
}
|
|
|
|
public JRFillCellContents getWorkingClone() {
|
|
JRFillCellContents clone = (JRFillCellContents)this.clonePool.getClone();
|
|
clone.original = this;
|
|
return clone;
|
|
}
|
|
|
|
public void releaseWorkingClone() {
|
|
this.original.clonePool.releaseClone(this);
|
|
}
|
|
|
|
public void setX(int x) {
|
|
this.x = x;
|
|
}
|
|
|
|
public void setY(int y) {
|
|
this.y = y;
|
|
}
|
|
|
|
public int getVerticalSpan() {
|
|
return this.verticalSpan;
|
|
}
|
|
|
|
public void setVerticalSpan(int span) {
|
|
this.verticalSpan = span;
|
|
}
|
|
|
|
public void setVerticalPositionType(byte positionType) {
|
|
this.verticalPositionType = positionType;
|
|
}
|
|
|
|
protected void evaluate(byte evaluation) throws JRException {
|
|
evaluateConditionalStyles(evaluation);
|
|
super.evaluate(evaluation);
|
|
}
|
|
|
|
public JRDefaultStyleProvider getDefaultStyleProvider() {
|
|
return this.defaultStyleProvider;
|
|
}
|
|
|
|
public JRStyle getStyle() {
|
|
JRStyle crtStyle = this.initStyle;
|
|
boolean isUsingDefaultStyle = false;
|
|
if (crtStyle == null) {
|
|
crtStyle = this.filler.getDefaultStyle();
|
|
isUsingDefaultStyle = true;
|
|
}
|
|
JRStyle evalStyle = getEvaluatedConditionalStyle(crtStyle);
|
|
if (isUsingDefaultStyle && evalStyle == crtStyle)
|
|
evalStyle = null;
|
|
return evalStyle;
|
|
}
|
|
|
|
protected void initConditionalStyles() {
|
|
super.initConditionalStyles();
|
|
collectConditionalStyle(this.initStyle);
|
|
}
|
|
|
|
public Byte getMode() {
|
|
return this.parentCell.getMode();
|
|
}
|
|
|
|
public String getStyleNameReference() {
|
|
return null;
|
|
}
|
|
|
|
public void setStyle(JRStyle style) {
|
|
this.initStyle = style;
|
|
collectConditionalStyle(style);
|
|
}
|
|
|
|
public void setStyleNameReference(String name) {
|
|
throw new UnsupportedOperationException("Style name references not allowed at fill time");
|
|
}
|
|
|
|
public Color getDefaultLineColor() {
|
|
return this.parentCell.getDefaultLineColor();
|
|
}
|
|
}
|