From: Karen Lease Date: Wed, 4 Jul 2001 21:16:02 +0000 (+0000) Subject: Implements spanning table rows X-Git-Tag: PRE_CODEFORMATTING~47 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c6c5c26561b0392d41eca49cbebf7b556c72e04f;p=xmlgraphics-fop.git Implements spanning table rows git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194332 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/org/apache/fop/fo/flow/TableBody.java b/src/org/apache/fop/fo/flow/TableBody.java index 2c40b66a4..69b95db25 100644 --- a/src/org/apache/fop/fo/flow/TableBody.java +++ b/src/org/apache/fop/fo/flow/TableBody.java @@ -37,6 +37,7 @@ public class TableBody extends FObj { String id; Vector columns; + RowSpanMgr rowSpanMgr; // manage information about spanning rows AreaContainer areaContainer; @@ -82,6 +83,10 @@ public class TableBody extends FObj { area.end(); } + if (rowSpanMgr == null) { + rowSpanMgr = new RowSpanMgr(columns.size()); + } + //if (this.isInListBody) { //startIndent += bodyIndent + distanceBetweenStarts; //} @@ -131,6 +136,7 @@ public class TableBody extends FObj { } TableRow row = (TableRow) child; + row.setRowSpanMgr(rowSpanMgr); row.setColumns(columns); row.doSetup(areaContainer); if (row.getKeepWithPrevious().getType() != @@ -145,6 +151,7 @@ public class TableBody extends FObj { 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); @@ -162,6 +169,7 @@ public class TableBody extends FObj { return status; } if (keepWith.size() > 0) { // && status.getCode() == Status.AREA_FULL_NONE + // FIXME!!! Handle rows spans!!! row.removeLayout(areaContainer); for (Enumeration e = keepWith.elements(); e.hasMoreElements();) { @@ -179,34 +187,6 @@ public class TableBody extends FObj { (status.getCode() == Status.AREA_FULL_NONE)) { status = new Status(Status.AREA_FULL_SOME); } - // if (i < widows && numChildren >= widows) { - // resetMarker(); - // return new Status(Status.AREA_FULL_NONE); - // } - // if (numChildren <= orphans) { - // resetMarker(); - // return new Status(Status.AREA_FULL_NONE); - // } - // if (numChildren - i < orphans && numChildren >= orphans) { - // for (int count = i; - // count > numChildren - orphans - 1; count--) { - // row = (TableRow) children.elementAt(count); - // row.removeLayout(areaContainer); - // i--; - // } - // if (i < widows && numChildren >= widows) { - // resetMarker(); - // return new Status(Status.AREA_FULL_NONE); - // } - // this.marker = i; - // area.addChild(areaContainer); - // //areaContainer.end(); - - // area.increaseHeight(areaContainer.getHeight()); - // area.setAbsoluteHeight( - // areaContainer.getAbsoluteHeight()); - // return new Status(Status.AREA_FULL_SOME); - // } if (!((i == 0) && (areaContainer.getContentHeight() <= 0))) { area.addChild(areaContainer); @@ -217,7 +197,8 @@ public class TableBody extends FObj { areaContainer.getAbsoluteHeight()); } return status; - } else if (status.getCode() == Status.KEEP_WITH_NEXT) { + } else if (status.getCode() == Status.KEEP_WITH_NEXT || + rowSpanMgr.hasUnfinishedSpans()) { keepWith.addElement(row); endKeepGroup = false; } else { diff --git a/src/org/apache/fop/fo/flow/TableCell.java b/src/org/apache/fop/fo/flow/TableCell.java index 9be25f7ca..8b24159db 100644 --- a/src/org/apache/fop/fo/flow/TableCell.java +++ b/src/org/apache/fop/fo/flow/TableCell.java @@ -33,6 +33,7 @@ public class TableCell extends FObj { String id; int numColumnsSpanned; int numRowsSpanned; + int iColNumber = -1; // uninitialized /** Offset of content rectangle in inline-progression-direction, * relative to table. @@ -49,13 +50,14 @@ public class TableCell extends FObj { /* ivan demakov */ protected int borderHeight = 0; + protected int cellHeight = 0; protected int height = 0; protected int top; // Ypos of cell ??? protected int verticalAlign ; protected boolean bRelativeAlign = false; - boolean setup = false; + // boolean setup = false; boolean bSepBorders = true; /** Border separation value in the block-progression dimension. @@ -68,6 +70,7 @@ public class TableCell extends FObj { public TableCell(FObj parent, PropertyList propertyList) { super(parent, propertyList); this.name = "fo:table-cell"; + doSetup(); // init some basic property values } // Set position relative to table (set by body?) @@ -81,6 +84,11 @@ public class TableCell extends FObj { this.width = width; } + public int getColumnNumber() + { + return iColNumber; + } + public int getNumColumnsSpanned() { return numColumnsSpanned; @@ -91,22 +99,22 @@ public class TableCell extends FObj { return numRowsSpanned; } - public void doSetup(Area area) throws FOPException + public void doSetup()// throws FOPException { + this.iColNumber = properties.get("column-number").getNumber().intValue(); + if (iColNumber < 0) { iColNumber = 0; } this.numColumnsSpanned = this.properties.get("number-columns-spanned").getNumber().intValue(); + if (numColumnsSpanned < 1) { numColumnsSpanned = 1; } this.numRowsSpanned = this.properties.get("number-rows-spanned").getNumber().intValue(); + if (numRowsSpanned < 1) { numRowsSpanned = 1; } - /** - 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(); + bSepBorders = (this.properties.get("border-collapse").getEnum() == BorderCollapse.SEPARATE); // Vertical cell alignment @@ -118,6 +126,7 @@ public class TableCell extends FObj { } else bRelativeAlign = false; // Align on a per-cell basis + this.cellHeight = this.properties.get("height").getLength().mvalue(); } @@ -128,9 +137,9 @@ public class TableCell extends FObj { } if (this.marker == START) { - if (!setup) { - doSetup(area); - } +// if (!setup) { +// doSetup(area); +// } // Calculate cell borders calcBorders(propMgr.getBorderAndPadding()); @@ -151,14 +160,14 @@ public class TableCell extends FObj { area.getIDReferences().configureID(id,area); } - int spaceLeft = area.spaceLeft(); + int spaceLeft = area.spaceLeft() - m_borderSeparation/2 + borderHeight/2 ; // The Area position defines the content rectangle! Borders // and padding are outside of this rectangle. this.cellArea = new AreaContainer(propMgr.getFontState(area.getFontInfo()), startOffset, beforeOffset, - width, area.spaceLeft()- m_borderSeparation/2 + borderHeight/2, + width, spaceLeft, Position.RELATIVE); cellArea.foCreator=this; // G Seshadri @@ -194,6 +203,7 @@ public class TableCell extends FObj { return new Status(Status.AREA_FULL_SOME); } } + area.setMaxHeight(area.getMaxHeight() - spaceLeft + this.cellArea.getMaxHeight()); } @@ -218,7 +228,8 @@ public class TableCell extends FObj { // TableRow calls this. Anyone else? public int getHeight() { // return cellArea.getHeight() + spaceBefore + spaceAfter; - return cellArea.getHeight() + m_borderSeparation - borderHeight / 2; + if (cellHeight > 0) return cellHeight; + return cellArea.getHeight() + m_borderSeparation - borderHeight/2; } /** Called by TableRow to set final size of cell content rectangles and @@ -290,6 +301,10 @@ public class TableCell extends FObj { this.beforeOffset = m_borderSeparation/2 + bp.getBorderTopWidth(false) + bp.getPaddingTop(false); // bp.getBorderBeforeWidth(false) + bp.getPaddingBefore(false); + if (this.cellHeight > 0) { + this.cellHeight += this.beforeOffset + m_borderSeparation/2 + + bp.getBorderBottomWidth(false) + bp.getPaddingBottom(false); + } } else { //System.err.println("Collapse borders"); @@ -332,6 +347,9 @@ public class TableCell extends FObj { this.beforeOffset = borderBefore/2 + bp.getPaddingTop(false); this.borderHeight = borderBefore + borderAfter; + if (this.cellHeight > 0) { + this.cellHeight += this.beforeOffset + borderAfter/2 + bp.getPaddingBottom(false); + } } } } diff --git a/src/org/apache/fop/fo/flow/TableRow.java b/src/org/apache/fop/fo/flow/TableRow.java index da12002e0..4a885b56b 100644 --- a/src/org/apache/fop/fo/flow/TableRow.java +++ b/src/org/apache/fop/fo/flow/TableRow.java @@ -16,526 +16,497 @@ import org.apache.fop.apps.FOPException; // Java import java.util.Vector; +import java.util.Enumeration; public class TableRow extends FObj { - public static class Maker extends FObj.Maker { - public FObj make(FObj parent, - PropertyList propertyList) throws FOPException { - return new TableRow(parent, propertyList); - } - } - - public static FObj.Maker maker() { - return new TableRow.Maker(); - } - - boolean setup = false; + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, + PropertyList propertyList) throws FOPException { + return new TableRow(parent, propertyList); + } + } - int spaceBefore; - int spaceAfter; - int breakBefore; - int breakAfter; - ColorType backgroundColor; - String id; + public static FObj.Maker maker() { + return new TableRow.Maker(); + } - KeepValue keepWithNext; - KeepValue keepWithPrevious; + boolean setup = false; - int widthOfCellsSoFar = 0; - int largestCellHeight = 0; + int breakAfter; + ColorType backgroundColor; + String id; - Vector columns; + KeepValue keepWithNext; + KeepValue keepWithPrevious; + KeepValue keepTogether; - AreaContainer areaContainer; + int widthOfCellsSoFar = 0; + int largestCellHeight = 0; - // added by Dresdner Bank, Germany - DisplaySpace spacer = null; - boolean hasAddedSpacer = false; - DisplaySpace spacerAfter = null; - boolean areaAdded = false; + Vector columns; - /** - * The list of cell states for this row. This is the location of - * where I will be storing the state of each cell so that I can - * spread a cell over multiple pages if I have to. This is part - * of fixing the TableRow larger than a single page bug. - * Hani Elabed, 11/22/2000. - */ - public Vector cells = null; - - /** - * CellState
- * - * Copyright @ 2000 Circuit Court Automation Program. - * state of Wisconsin. - * All Rights Reserved. - *

- * This class is a container class for encapsulating a the - * state of a cell - * - * - * - * - * - * - * - *
Name: CellState
Purpose: a helpful container class
Description: This class is a container class for - * encapsulating the state of a - * cell belonging to a TableRow class - *
- * - * @author Hani Elabed - * @version 0.14.0, 11/22/2000 - * @since JDK1.1 - */ - public final class CellState { - /** the cell location or index starting at 0.*/ - private int location; - - /** true if the layout of the cell was complete, false otherwise.*/ - private boolean layoutCompleted; - - /** the width of the cell so far.*/ - private int widthOfCellSoFar; - - private int column = 0; - - /** - * simple no args constructor. - */ - public CellState() { - this(0, false, 0); - } - - /** - * three argument fill everything constructor. - * @param int the location(index) of the cell. - * @param boolean flag of wether the cell was completely laid out or not. - * @param int the horizontal offset(width so far) of the cell. - */ - public CellState(int aLocation, boolean completed, int aWidth) { - - location = aLocation; - layoutCompleted = completed; - widthOfCellSoFar = aWidth; - } - - /** - * returns the index of the cell starting at 0. - * @return int the location of the cell. - */ - public final int getLocation() { - return location; - } - - /** - * sets the location of the cell. - * @param int, the location of the cell. - */ - public final void setLocation(int aLocation) { - location = aLocation; - } - - - /** - * returns true if the cell was completely laid out. - * @return false if cell was partially laid out. - */ - public final boolean isLayoutComplete() { - return layoutCompleted; - } - - /** - * sets the layoutCompleted flag. - * @param boolean, the layout Complete state of the cell. - */ - public final void setLayoutComplete(boolean completed) { - layoutCompleted = completed; - } - - - /** - * returns the horizontal offset of the cell. - * @return int the horizontal offset of the cell, also known as width - * of the cell so far. - */ - public final int getWidthOfCellSoFar() { - return widthOfCellSoFar; - } - - /** - * sets the width of the Cell So Far, i.e the cell's offset. - * @param int, the horizontal offset of the cell. - */ - public final void setWidthOfCellSoFar(int aWidth) { - widthOfCellSoFar = aWidth; - } - - public int getColumn() { - return column; - } - - public void setColumn(int col) { - column = col; - } - } + AreaContainer areaContainer; + boolean areaAdded = false; - public TableRow(FObj parent, PropertyList propertyList) { - super(parent, propertyList); - this.name = "fo:table-row"; - } - - public void setColumns(Vector columns) { - this.columns = columns; - } - - public KeepValue getKeepWithPrevious() { - return keepWithPrevious; - } - - public void doSetup(Area area) throws FOPException { + private RowSpanMgr rowSpanMgr = null; + private CellArray cellArray = null; - this.spaceBefore = this.properties.get( - "space-before.optimum").getLength().mvalue(); - this.spaceAfter = this.properties.get( - "space-after.optimum").getLength().mvalue(); - this.breakBefore = this.properties.get("break-before").getEnum(); - this.breakAfter = this.properties.get("break-after").getEnum(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); + private static class CellArray { + public static final byte EMPTY=0; + public static final byte CELLSTART=1; + public static final byte CELLSPAN=2; - this.keepWithNext = getKeepValue("keep-with-next.within-column"); - this.keepWithPrevious = getKeepValue("keep-with-previous.within-column"); + private TableCell[] cells; + private byte[] states; - this.id = this.properties.get("id").getString(); - setup = true; + public CellArray(RowSpanMgr rsi, int numColumns) { + // Initialize the cell array by marking any cell positions + // occupied by spans from previous rows + cells = new TableCell[numColumns]; + states = new byte[numColumns]; + for (int i=0; i = input value. + */ + int getNextFreeCell(int colNum) { + for (int i=colNum-1; i 0 && colNum<=cells.length) { + return states[colNum-1]; + } + else return -1; // probably should throw exception + } + + /** + * Return cell in colNum (1 based) + */ + TableCell getCell(int colNum) { + if (colNum > 0 && colNum<=cells.length) { + return cells[colNum-1]; + } + else return null; // probably should throw exception + } + + /** + * Store cell starting at cellColNum (1 based) and spanning numCols + * If any of the columns is already occupied, return false, else true + */ + boolean storeCell(TableCell cell, int colNum, int numCols) { + boolean rslt=true; + int index=colNum-1; + for (int count=0; index columns.size()) { - MessageHandler.errorln("WARNING: Number of cell columns under table-row not equal to number of table-columns"); - return new Status(Status.OK); - } - for (int count = 0; - count < numCols && count < columns.size(); - count++) { - width += ((TableColumn) columns.elementAt(colCount)). - getColumnWidth(); - colCount++; - } - - cell.setWidth(width); - widthOfCellsSoFar += width; - - } - if(colCount < columns.size()) { - MessageHandler.errorln("WARNING: Number of cell columns under table-row not equal to number of table-columns"); - return new Status(Status.OK); - } - } - - int numChildren = this.children.size(); - // if (numChildren != columns.size()) { - // MessageHandler.errorln("WARNING: Number of children under table-row not equal to number of table-columns"); - // return new Status(Status.OK); - // } - - // added by Eric Schaeffer - largestCellHeight = 0; - - // added by Hani Elabed 11/27/2000 - boolean someCellDidNotLayoutCompletely = false; - - // If it takes multiple calls to completely layout the row, we need to process - // all of the children (cells) not just those from the marker so that the borders - // will be drawn properly. - for (int i = 0; i < numChildren; i++) { - TableCell cell = (TableCell) children.elementAt(i); - - // added by Hani Elabed 11/22/2000 - CellState cellState = (CellState) cells.elementAt(i); - - //--- this is modified to preserve the state of start - //--- offset of the cell. - //--- change by Hani Elabed 11/22/2000 - cell.setStartOffset(cellState.getWidthOfCellSoFar()); - - // Each column in the row should start with the same height available - // True: we now don't set the row height until all cells in it are - // (at least partially) composed, so this is not necssary. - // -Karen Lease, 01 may 2001 -// if ( i > 0 ) -// { -// areaContainer.increaseHeight(areaContainer.spaceLeft() - areaContainer.getMaxHeight() - spaceLeft + origMaxHeight); -// areaContainer.setMaxHeight(spaceLeft); -// } - - Status status; - if ((status = cell.layout(areaContainer)).isIncomplete()) { - this.marker = i; - if (status.getCode() == Status.AREA_FULL_SOME) { - // this whole block added by - // Hani Elabed 11/27/2000 - - cellState.setLayoutComplete(false); - someCellDidNotLayoutCompletely = true; - } else { - /* None of the cell content was laid out. - * In this case, we stop doing this row and - * reset the marker to start it in the next - * column or page. Note that the row height hasn't been - * set and the row area hasn't yet - * been added to its parent at this point! - */ - - // added on 11/28/2000, by Dresdner Bank, Germany - if (spacer != null) { - area.increaseHeight(-spaceBefore); - // area.removeChild(spacer); - // spacer = null; - } -// hasAddedSpacer = false; -// if(spacerAfter != null) -// area.removeChild(spacerAfter); -// spacerAfter = null; - - // removing something that was added by succession - // of cell.layout() - // just to keep my sanity here, Hani - // area.increaseHeight(areaContainer.getHeight()); - // area.removeChild(areaContainer); - this.resetMarker(); - this.removeID(area.getIDReferences()); - - // hani elabed 11/27/2000 - // cellState.setLayoutComplete(false); - - return status; - } - } else // layout was complete for a particular cell - { // Hani Elabed - cellState.setLayoutComplete(true); - } - - int h = cell.getHeight(); - if (h > largestCellHeight) { - largestCellHeight = h; - } - } - - // This is in case a float was composed in the cells - area.setMaxHeight(area.getMaxHeight() - spaceLeft + - this.areaContainer.getMaxHeight()); - - for (int i = 0; i < numChildren; i++) { - TableCell cell = (TableCell) children.elementAt(i); - cell.setRowHeight(largestCellHeight); - } - - // added by Dresdner Bank, Germany - if (!hasAddedSpacer && spacer != null) { - area.addChild(spacer); - hasAddedSpacer = true; - } - - area.addChild(areaContainer); - areaContainer.setHeight(largestCellHeight); - areaAdded = true; - areaContainer.end(); - - /* The method addDisplaySpace increases both the content - * height of the parent area (table body, head or footer) and - * also its "absolute height". So we don't need to do this - * explicitly. - * - * Note: it doesn't look from the CR as though we should take - * into account borders and padding on rows, only background. - * The exception is perhaps if the borders are "collapsed", but - * they should still be rendered only on cells and not on the - * rows themselves. (Karen Lease - 01may2001) - */ - area.addDisplaySpace(largestCellHeight + - areaContainer.getPaddingTop() + - areaContainer.getBorderTopWidth() + - areaContainer.getPaddingBottom() + - areaContainer.getBorderBottomWidth()); - - - if (!someCellDidNotLayoutCompletely && spaceAfter != 0) { - spacerAfter = new DisplaySpace(spaceAfter); - area.addChild(spacerAfter); - area.increaseHeight(spaceAfter); - } - - - // replaced by Hani Elabed 11/27/2000 - //return new Status(Status.OK); - - if (someCellDidNotLayoutCompletely) { - return new Status(Status.AREA_FULL_SOME); - } else { - if (breakAfter == BreakAfter.PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK); - } - - if (breakAfter == BreakAfter.ODD_PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK_ODD); - } - - if (breakAfter == BreakAfter.EVEN_PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK_EVEN); - } - - if (breakAfter == BreakAfter.COLUMN) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_COLUMN_BREAK); - } - if (keepWithNext.getType() != KeepValue.KEEP_WITH_AUTO) { - return new Status(Status.KEEP_WITH_NEXT); - } - return new Status(Status.OK); - } - + } + + this.marker = 0; + int breakStatus = propMgr.checkBreakBefore(); + if (breakStatus != Status.OK) + return new Status(breakStatus); + } + + // if (marker == 0 && configID) { + if (marker == 0) { // KDL: need to do this if thrown or if split? + // configure id + area.getIDReferences().configureID(id, area); + } + + int spaceLeft = area.spaceLeft(); + + this.areaContainer = + new AreaContainer(propMgr.getFontState(area.getFontInfo()), + 0,0, + area.getContentWidth(), + spaceLeft, + Position.RELATIVE); + areaContainer.foCreator=this; // G Seshadri + areaContainer.setPage(area.getPage()); + + areaContainer.setBackgroundColor(backgroundColor); + areaContainer.start(); + + areaContainer.setAbsoluteHeight(area.getAbsoluteHeight()); + areaContainer.setIDReferences(area.getIDReferences()); + + largestCellHeight = 0; + + // Flag indicaing whether any cell didn't fit in available space + boolean someCellDidNotLayoutCompletely = false; + + /* If it takes multiple calls to completely layout the row, + * we need to process all of the children (cells) + * not just those from the marker so that the borders + * will be drawn properly. + */ + int offset=0; // Offset of each cell from table start edge + int iColIndex = 0; // 1-based column index + Enumeration eCols = columns.elements(); + /* Ideas: set offset on each column when they are initialized + * no need to calculate for each row. + * Pass column object to cell to get offset and width and border + * info if borders are "collapsed". + */ + + while (eCols.hasMoreElements()) { + TableCell cell; + ++iColIndex; + TableColumn tcol = (TableColumn)eCols.nextElement(); + int colWidth = tcol.getColumnWidth(); + if (cellArray.getCellType(iColIndex) == CellArray.CELLSTART) { + cell = cellArray.getCell(iColIndex); + } else { + /* If this cell is spanned from a previous row, + * and this is the last row, get the remaining height + * and use it to increase maxCellHeight if necessary + */ + if (rowSpanMgr.isInLastRow(iColIndex)) { + int h = rowSpanMgr.getRemainingHeight(iColIndex); + if (h > largestCellHeight) + largestCellHeight = h; } - - public int getAreaHeight() { - return areaContainer.getHeight(); + offset += colWidth; + continue; + } + // cell.setTableColumn(tcol); + cell.setStartOffset(offset); + offset += colWidth; + + + int rowSpan = cell.getNumRowsSpanned(); + Status status; + if ((status = cell.layout(areaContainer)).isIncomplete()) { + if ((keepTogether.getType() == KeepValue.KEEP_WITH_ALWAYS) || + (status.getCode() == Status.AREA_FULL_NONE) || + rowSpan > 1) { + // We will put this row into the next column/page + // Note: the only time this shouldn't be honored is + // if this row is at the top of the column area. + // Remove spanning cells from RowSpanMgr? + this.resetMarker(); + this.removeID(area.getIDReferences()); + return new Status(Status.AREA_FULL_NONE); } - - public void removeLayout(Area area) { - if (spacer != null) { - if(hasAddedSpacer) { - area.removeChild(spacer); - } else { - area.increaseHeight(-spaceBefore); - } - } - if(spacerAfter != null) - area.removeChild(spacerAfter); - //area.increaseHeight(areaContainer.getHeight()); - if(areaAdded) - area.removeChild(areaContainer); - areaAdded = false; - this.resetMarker(); - this.removeID(area.getIDReferences()); + else if (status.getCode() == Status.AREA_FULL_SOME) { + /* Row is not keep-together, cell isn't spanning + * and part of it fits. We can break the cell and + * the row. + */ + someCellDidNotLayoutCompletely = true; } - - public void resetMarker() - { - super.resetMarker(); - spacer = null; - spacerAfter = null; - hasAddedSpacer = false; - cells = null; + } //else { + // layout was complete for a particular cell + int h = cell.getHeight(); // allocation height of cell + if (rowSpan > 1) { // pass cell fo or area??? + rowSpanMgr.addRowSpan(cell, iColIndex, + cell.getNumColumnsSpanned(), h, rowSpan); + } + else if (h > largestCellHeight) { + largestCellHeight = h; } + // } + } // end of loop over all columns/cells + + // This is in case a float was composed in the cells + area.setMaxHeight(area.getMaxHeight() - spaceLeft + + this.areaContainer.getMaxHeight()); + + // Only do this for "STARTCELL", ending spans are handled separately + // What about empty cells? Yes, we should set their height too! + for (int iCol = 1; iCol <= columns.size(); iCol++) { + if (cellArray.getCellType(iCol) == CellArray.CELLSTART) { + cellArray.getCell(iCol).setRowHeight(largestCellHeight); + } + } + + // Adjust spanning row information + // ??? what if some cells are broken??? + rowSpanMgr.finishRow(largestCellHeight); + + area.addChild(areaContainer); + areaContainer.setHeight(largestCellHeight); + areaAdded = true; + areaContainer.end(); + + /* The method addDisplaySpace increases both the content + * height of the parent area (table body, head or footer) and + * also its "absolute height". So we don't need to do this + * explicitly. + * + * Note: it doesn't look from the CR as though we should take + * into account borders and padding on rows, only background. + * The exception is perhaps if the borders are "collapsed", but + * they should still be rendered only on cells and not on the + * rows themselves. (Karen Lease - 01may2001) + */ + area.addDisplaySpace(largestCellHeight + + areaContainer.getPaddingTop() + + areaContainer.getBorderTopWidth() + + areaContainer.getPaddingBottom() + + areaContainer.getBorderBottomWidth()); + + + // replaced by Hani Elabed 11/27/2000 + //return new Status(Status.OK); + + if (someCellDidNotLayoutCompletely) { + return new Status(Status.AREA_FULL_SOME); + } else { + if (rowSpanMgr.hasUnfinishedSpans()) { + // Ignore break after if row span! + return new Status(Status.KEEP_WITH_NEXT); + } + if (breakAfter == BreakAfter.PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK); + } + + if (breakAfter == BreakAfter.ODD_PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK_ODD); + } + + if (breakAfter == BreakAfter.EVEN_PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK_EVEN); + } + + if (breakAfter == BreakAfter.COLUMN) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_COLUMN_BREAK); + } + if (keepWithNext.getType() != KeepValue.KEEP_WITH_AUTO) { + return new Status(Status.KEEP_WITH_NEXT); + } + return new Status(Status.OK); + } + + } + + public int getAreaHeight() { + return areaContainer.getHeight(); + } + + public void removeLayout(Area area) { + if(areaAdded) + area.removeChild(areaContainer); + areaAdded = false; + this.resetMarker(); + this.removeID(area.getIDReferences()); + } + + public void resetMarker() + { + super.resetMarker(); + // Just reset all the states to not laid out and fix up row spans + } + + /** + * Called by parent FO to initialize information about + * cells started in previous rows which span into this row. + * The layout operation modifies rowSpanMgr + */ + public void setRowSpanMgr(RowSpanMgr rowSpanMgr) { + this.rowSpanMgr = rowSpanMgr; + } + + /** + * Before starting layout for the first time, initialize information + * about spanning rows, empty cells and spanning columns. + */ + private void initCellArray() { + cellArray = new CellArray(rowSpanMgr, columns.size()); + int colNum = 1; + Enumeration eCells = children.elements(); + while (eCells.hasMoreElements()) { + colNum = cellArray.getNextFreeCell(colNum); + // If off the end, the rest of the cells had better be + // explicitly positioned!!! (returns -1) + + TableCell cell = (TableCell) eCells.nextElement(); + int numCols = cell.getNumColumnsSpanned(); + int numRows = cell.getNumRowsSpanned(); + int cellColNum = cell.getColumnNumber(); + + if (cellColNum == 0) { + // Not explicitly specified, so put in next available colummn + // cell.setColumnNumber(colNum); + // If cellColNum "off the end", this cell is in limbo! + if (colNum < 1) { + // ERROR!!! + continue; + } + else cellColNum = colNum; + } + else if (cellColNum > columns.size()) { + // Explicit specification out of range! + // Skip it and print an ERROR MESSAGE + continue; + } + // see if it fits and doesn't overwrite anything + if (cellColNum + numCols - 1 > columns.size()) { + // MESSAGE: TOO MANY COLUMNS SPANNED! + numCols = columns.size() - cellColNum + 1; + } + // Check for overwriting other cells (returns false) + if (cellArray.storeCell(cell, cellColNum, numCols) == false) { + // Print out some kind of warning message. + } + if (cellColNum > colNum) { + // Cells are initialized as empty already + colNum = cellColNum; + } + else if (cellColNum < colNum) { + // MESSAGE ? cells out of order? + colNum = cellColNum; // CR "to the letter"! + } + int cellWidth = getCellWidth(cellColNum, numCols); + cell.setWidth(cellWidth); + colNum += numCols; // next cell in this column + } + } + + // ATTENTION if startCol + numCols > number of columns in table! + private int getCellWidth(int startCol, int numCols) { + int width = 0; + for (int count = 0; count < numCols; count++) { + width += ((TableColumn) columns.elementAt(startCol+count-1)).getColumnWidth(); + } + return width; + } }