blob: b69e59feb727fa4ac97186ee7f4e6381c7988f68 [file] [log] [blame]
/*
* $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
package org.apache.fop.fo.flow;
// FOP
import org.apache.fop.fo.*;
import org.apache.fop.fo.properties.*;
import org.apache.fop.datatypes.*;
import org.apache.fop.layout.*;
import org.apache.fop.apps.FOPException;
// Java
import java.util.Vector;
import java.util.Enumeration;
public class TableBody extends FObj {
public static class Maker extends FObj.Maker {
public FObj make(FObj parent,
PropertyList propertyList) throws FOPException {
return new TableBody(parent, propertyList);
}
}
public static FObj.Maker maker() {
return new TableBody.Maker();
}
int spaceBefore;
int spaceAfter;
ColorType backgroundColor;
String id;
Vector columns;
RowSpanMgr rowSpanMgr; // manage information about spanning rows
AreaContainer areaContainer;
public TableBody(FObj parent, PropertyList propertyList) {
super(parent, propertyList);
this.name = "fo:table-body";
}
public void setColumns(Vector columns) {
this.columns = columns;
}
public void setYPosition(int value) {
areaContainer.setYPosition(value);
}
public int getYPosition() {
return areaContainer.getCurrentYPosition();
}
public int getHeight() {
return areaContainer.getHeight() + spaceBefore + spaceAfter;
}
public Status layout(Area area) throws FOPException {
if (this.marker == BREAK_AFTER) {
return new Status(Status.OK);
}
if (this.marker == START) {
// Common Accessibility Properties
AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
// Common Aural Properties
AuralProps mAurProps = propMgr.getAuralProps();
// Common Border, Padding, and Background Properties
BorderAndPadding bap = propMgr.getBorderAndPadding();
BackgroundProps bProps = propMgr.getBackgroundProps();
// Common Relative Position Properties
RelativePositionProps mRelProps = propMgr.getRelativePositionProps();
// this.properties.get("id");
this.spaceBefore =
this.properties.get("space-before.optimum").getLength().mvalue();
this.spaceAfter =
this.properties.get("space-after.optimum").getLength().mvalue();
this.backgroundColor =
this.properties.get("background-color").getColorType();
this.id = this.properties.get("id").getString();
area.getIDReferences().createID(id);
if (area instanceof BlockArea) {
area.end();
}
if (rowSpanMgr == null) {
rowSpanMgr = new RowSpanMgr(columns.size());
}
// if (this.isInListBody) {
// startIndent += bodyIndent + distanceBetweenStarts;
// }
this.marker = 0;
}
if ((spaceBefore != 0) && (this.marker == 0)) {
area.increaseHeight(spaceBefore);
}
if (marker == 0) {
// configure id
area.getIDReferences().configureID(id, area);
}
int spaceLeft = area.spaceLeft();
/*
* Note: the parent FO must be a Table. The parent Area is the Block
* type area created by the Table, which is also a reference area.
* The content "width" (IPD) of the TableBody is the same as that
* of the containing table area, and its relative position is 0,0.
* Strictly speaking (CR), this FO should generate no areas!
*/
this.areaContainer =
new AreaContainer(propMgr.getFontState(area.getFontInfo()), 0,
area.getContentHeight(),
area.getContentWidth(), // IPD
area.spaceLeft(), Position.RELATIVE);
areaContainer.foCreator = this; // G Seshadri
areaContainer.setPage(area.getPage());
areaContainer.setBackgroundColor(backgroundColor);
areaContainer.setBorderAndPadding(propMgr.getBorderAndPadding());
areaContainer.start();
areaContainer.setAbsoluteHeight(area.getAbsoluteHeight());
areaContainer.setIDReferences(area.getIDReferences());
Vector keepWith = new Vector();
int numChildren = this.children.size();
TableRow lastRow = null;
boolean endKeepGroup = true;
for (int i = this.marker; i < numChildren; i++) {
Object child = children.elementAt(i);
if (!(child instanceof TableRow)) {
throw new FOPException("Currently only Table Rows are supported in table body, header and footer");
}
TableRow row = (TableRow)child;
row.setRowSpanMgr(rowSpanMgr);
row.setColumns(columns);
row.doSetup(areaContainer);
if (row.getKeepWithPrevious().getType()
!= KeepValue.KEEP_WITH_AUTO && lastRow != null
&& keepWith.indexOf(lastRow)
== -1) {
keepWith.addElement(lastRow);
} else {
if (endKeepGroup && keepWith.size() > 0) {
keepWith = new Vector();
}
}
Status status;
if ((status = row.layout(areaContainer)).isIncomplete()) {
// BUG!!! don't distinguish between break-before and after!
if (status.isPageBreak()) {
this.marker = i;
area.addChild(areaContainer);
// areaContainer.end();
area.increaseHeight(areaContainer.getHeight());
area.setAbsoluteHeight(areaContainer.getAbsoluteHeight());
if (i == numChildren - 1) {
this.marker = BREAK_AFTER;
if (spaceAfter != 0) {
area.increaseHeight(spaceAfter);
}
}
return status;
}
if ((keepWith.size() > 0)
&& (!rowSpanMgr.ignoreKeeps())) {
// && status.getCode() == Status.AREA_FULL_NONE
// FIXME!!! Handle rows spans!!!
row.removeLayout(areaContainer);
for (Enumeration e = keepWith.elements();
e.hasMoreElements(); ) {
TableRow tr = (TableRow)e.nextElement();
tr.removeLayout(areaContainer);
i--;
}
if (i == 0) {
resetMarker();
// Fix for infinite loop bug if keeps are too big for page
rowSpanMgr.setIgnoreKeeps(true);
return new Status(Status.AREA_FULL_NONE);
}
}
this.marker = i;
if ((i != 0) && (status.getCode() == Status.AREA_FULL_NONE)) {
status = new Status(Status.AREA_FULL_SOME);
}
if (!((i == 0) && (areaContainer.getContentHeight() <= 0))) {
area.addChild(areaContainer);
// areaContainer.end();
area.increaseHeight(areaContainer.getHeight());
area.setAbsoluteHeight(areaContainer.getAbsoluteHeight());
}
// Fix for infinite loop bug if spanned rows are too big for page
rowSpanMgr.setIgnoreKeeps(true);
return status;
} else if (status.getCode() == Status.KEEP_WITH_NEXT
|| rowSpanMgr.hasUnfinishedSpans()) {
keepWith.addElement(row);
endKeepGroup = false;
} else {
endKeepGroup = true;
}
lastRow = row;
area.setMaxHeight(area.getMaxHeight() - spaceLeft
+ this.areaContainer.getMaxHeight());
spaceLeft = area.spaceLeft();
}
area.addChild(areaContainer);
areaContainer.end();
area.increaseHeight(areaContainer.getHeight());
area.setAbsoluteHeight(areaContainer.getAbsoluteHeight());
if (spaceAfter != 0) {
area.increaseHeight(spaceAfter);
area.setMaxHeight(area.getMaxHeight() - spaceAfter);
}
if (area instanceof BlockArea) {
area.start();
}
return new Status(Status.OK);
}
public void removeLayout(Area area) {
if (areaContainer != null) {
area.removeChild(areaContainer);
}
if (spaceBefore != 0) {
area.increaseHeight(-spaceBefore);
}
if (spaceAfter != 0) {
area.increaseHeight(-spaceAfter);
}
this.resetMarker();
this.removeID(area.getIDReferences());
}
}