git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@289865 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_90-alpha1
@@ -28,6 +28,7 @@ import org.apache.fop.fo.properties.BorderWidthPropertyMaker; | |||
import org.apache.fop.fo.properties.BoxPropShorthandParser; | |||
import org.apache.fop.fo.properties.CharacterProperty; | |||
import org.apache.fop.fo.properties.ColorTypeProperty; | |||
import org.apache.fop.fo.properties.ColumnNumberPropertyMaker; | |||
import org.apache.fop.fo.properties.CondLengthProperty; | |||
import org.apache.fop.fo.properties.CorrespondingPropertyMaker; | |||
import org.apache.fop.fo.properties.DimensionPropertyMaker; | |||
@@ -2386,9 +2387,7 @@ public class FOPropertyMapping implements Constants { | |||
addPropertyMaker("caption-side", m); | |||
// column-number | |||
m = new NumberProperty.Maker(PR_COLUMN_NUMBER); | |||
m.setInherited(false); | |||
m.setDefault("0"); | |||
m = new ColumnNumberPropertyMaker(PR_COLUMN_NUMBER); | |||
addPropertyMaker("column-number", m); | |||
// column-width |
@@ -18,6 +18,7 @@ | |||
package org.apache.fop.fo.flow; | |||
import java.util.BitSet; | |||
import java.util.List; | |||
import org.xml.sax.Locator; | |||
@@ -41,7 +42,7 @@ import org.apache.fop.fo.properties.LengthRangeProperty; | |||
/** | |||
* Class modelling the fo:table object. | |||
*/ | |||
public class Table extends FObj { | |||
public class Table extends TableFObj { | |||
// The value of properties relevant for fo:table. | |||
private CommonAccessibility commonAccessibility; | |||
private CommonAural commonAural; | |||
@@ -49,12 +50,8 @@ public class Table extends FObj { | |||
private CommonMarginBlock commonMarginBlock; | |||
private CommonRelativePosition commonRelativePosition; | |||
private LengthRangeProperty blockProgressionDimension; | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private int borderCollapse; | |||
private Numeric borderEndPrecedence; | |||
private LengthPairProperty borderSeparation; | |||
private Numeric borderStartPrecedence; | |||
private int breakAfter; | |||
private int breakBefore; | |||
private String id; | |||
@@ -75,6 +72,8 @@ public class Table extends FObj { | |||
/** collection of columns in this table */ | |||
protected List columns = null; | |||
private BitSet usedColumnIndices = new BitSet(); | |||
private int columnIndex = 1; | |||
private TableBody tableHeader = null; | |||
private TableBody tableFooter = null; | |||
@@ -106,12 +105,8 @@ public class Table extends FObj { | |||
commonMarginBlock = pList.getMarginBlockProps(); | |||
commonRelativePosition = pList.getRelativePositionProps(); | |||
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderCollapse = pList.get(PR_BORDER_COLLAPSE).getEnum(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderSeparation = pList.get(PR_BORDER_SEPARATION).getLengthPair(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
breakAfter = pList.get(PR_BREAK_AFTER).getEnum(); | |||
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum(); | |||
id = pList.get(PR_ID).getString(); | |||
@@ -126,6 +121,7 @@ public class Table extends FObj { | |||
tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); | |||
//width = pList.get(PR_WIDTH).getLength(); | |||
writingMode = pList.get(PR_WRITING_MODE).getEnum(); | |||
super.bind(pList); | |||
//Create default column in case no table-columns will be defined. | |||
defaultColumn = new TableColumn(this, true); | |||
@@ -213,7 +209,8 @@ public class Table extends FObj { | |||
missingChildElementError( | |||
"(marker*,table-column*,table-header?,table-footer?,table-body+)"); | |||
} | |||
//release reference | |||
usedColumnIndices = null; | |||
getFOEventHandler().endTable(this); | |||
} | |||
@@ -222,10 +219,7 @@ public class Table extends FObj { | |||
*/ | |||
protected void addChildNode(FONode child) throws FOPException { | |||
if (child.getName().equals("fo:table-column")) { | |||
if (columns == null) { | |||
columns = new java.util.ArrayList(); | |||
} | |||
columns.add(((TableColumn)child)); | |||
addColumnNode((TableColumn) child); | |||
} else if (child.getName().equals("fo:table-footer")) { | |||
tableFooter = (TableBody)child; | |||
} else if (child.getName().equals("fo:table-header")) { | |||
@@ -236,6 +230,48 @@ public class Table extends FObj { | |||
} | |||
} | |||
/** | |||
* Adds a column to the columns List, and updates the columnIndex | |||
* used for determining initial values for column-number | |||
* | |||
* @param col the column to add | |||
* @throws FOPException | |||
*/ | |||
private void addColumnNode(TableColumn col) throws FOPException { | |||
int colNumber = col.getColumnNumber(); | |||
int colRepeat = col.getNumberColumnsRepeated(); | |||
if (columns == null) { | |||
columns = new java.util.ArrayList(); | |||
} | |||
if( columns.size() < colNumber ) { | |||
//add nulls for non-occupied indices between | |||
//the last column up to and including the current one | |||
while( columns.size() < colNumber ) { | |||
columns.add(null); | |||
} | |||
} | |||
//replace the null-value with the actual column | |||
columns.set(colNumber - 1, col); | |||
if( colRepeat > 1 ) { | |||
//in case column is repeated: | |||
//for the time being, add the same column | |||
//(colRepeat - 1) times to the columns list | |||
//TODO: need to force the column-number | |||
//TODO: need to make sure START/END BorderInfo | |||
// are completely independent instances (clones?) | |||
// = necessary for border-collapse="collapse" | |||
// if collapsing is handled in FOTree | |||
for( int i = colRepeat - 1; --i >= 0; ) { | |||
columns.add(col); | |||
} | |||
} | |||
//flag column indices used by this column | |||
usedColumnIndices.set(colNumber - 1, colNumber - 1 + colRepeat); | |||
//set index for the next column to use | |||
while( usedColumnIndices.get(columnIndex - 1) ) { | |||
columnIndex++; | |||
} | |||
} | |||
/** @return true of table-layout="auto" */ | |||
public boolean isAutoLayout() { | |||
return (tableLayout != EN_FIXED); | |||
@@ -376,4 +412,33 @@ public class Table extends FObj { | |||
public int getNameId() { | |||
return FO_TABLE; | |||
} | |||
/** | |||
* Returns the current column index of the Table | |||
* | |||
* @return the next column number to use | |||
*/ | |||
public int getCurrentColumnIndex() { | |||
return columnIndex; | |||
} | |||
/** | |||
* Sets the current column index of the given Table | |||
* (used by TableColumn.bind() in case the column-number | |||
* was explicitly specified) | |||
* | |||
*/ | |||
protected void setCurrentColumnIndex(int newIndex) { | |||
columnIndex = newIndex; | |||
} | |||
/** | |||
* Checks if a certain column-number is already occupied | |||
* | |||
* @param colNr the column-number to check | |||
* @return true if column-number is already in use | |||
*/ | |||
protected boolean isColumnNumberUsed(int colNr) { | |||
return usedColumnIndices.get(colNr - 1); | |||
} | |||
} |
@@ -19,6 +19,7 @@ | |||
package org.apache.fop.fo.flow; | |||
// Java | |||
import java.util.BitSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
@@ -39,23 +40,24 @@ import org.apache.fop.fo.properties.CommonRelativePosition; | |||
/** | |||
* Class modelling the fo:table-body object. | |||
*/ | |||
public class TableBody extends FObj { | |||
public class TableBody extends TableFObj { | |||
// The value of properties relevant for fo:table-body. | |||
private CommonAccessibility commonAccessibility; | |||
private CommonAural commonAural; | |||
private CommonBorderPaddingBackground commonBorderPaddingBackground; | |||
private CommonRelativePosition commonRelativePosition; | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private Numeric borderEndPrecedence; | |||
private Numeric borderStartPrecedence; | |||
private int visibility; | |||
// End of property values | |||
private PropertyList savedPropertyList; | |||
protected boolean tableRowsFound = false; | |||
protected boolean tableCellsFound = false; | |||
protected boolean tableCellsFound = false; | |||
private int columnIndex = 1; | |||
protected List pendingSpans; | |||
protected BitSet usedColumnIndices = new BitSet(); | |||
private boolean firstRow = true; | |||
/** | |||
* @param parent FONode that is the parent of the object | |||
@@ -72,12 +74,8 @@ public class TableBody extends FObj { | |||
commonAural = pList.getAuralProps(); | |||
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); | |||
commonRelativePosition = pList.getRelativePositionProps(); | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
visibility = pList.get(PR_VISIBILITY).getEnum(); | |||
super.bind(pList); | |||
//Used by convertCellsToRows() | |||
savedPropertyList = pList; | |||
} | |||
@@ -86,6 +84,7 @@ public class TableBody extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
initPendingSpans(); | |||
getFOEventHandler().startBody(this); | |||
} | |||
@@ -107,7 +106,10 @@ public class TableBody extends FObj { | |||
if (tableCellsFound) { | |||
convertCellsToRows(); | |||
}*/ | |||
savedPropertyList = null; //Release reference | |||
//release references | |||
savedPropertyList = null; | |||
pendingSpans = null; | |||
usedColumnIndices = null; | |||
} | |||
/** | |||
@@ -142,6 +144,78 @@ public class TableBody extends FObj { | |||
invalidChildError(loc, nsURI, localName); | |||
} | |||
} | |||
/** | |||
* @see org.apache.fop.fo.FONode#addChildNode(FONode) | |||
*/ | |||
protected void addChildNode(FONode child) throws FOPException { | |||
if( child.getNameId() == FO_TABLE_CELL ) { | |||
addCellNode( (TableCell) child); | |||
} else { | |||
super.addChildNode(child); | |||
} | |||
} | |||
/** | |||
* Adds a cell to the list of child nodes, and updates the columnIndex | |||
* used for determining the initial value of column-number | |||
* | |||
* @param cell cell to add | |||
* @throws FOPException | |||
*/ | |||
private void addCellNode(TableCell cell) throws FOPException { | |||
//if firstRow flag is still true, the cell starts a row, | |||
//and there was a previous cell that didn't explicitly | |||
//end the previous row => set firstRow flag to false | |||
if( firstRow && cell.startsRow() && !lastCellEndedRow() ) { | |||
firstRow = false; | |||
} | |||
int rowSpan = cell.getNumberRowsSpanned(); | |||
int colSpan = cell.getNumberColumnsSpanned(); | |||
//if there were no explicit columns, pendingSpans | |||
//will not be properly initialized for the first row | |||
if( firstRow && ((Table) parent).columns == null ) { | |||
if( pendingSpans == null ) { | |||
pendingSpans = new java.util.ArrayList(); | |||
} | |||
for( int i = colSpan; --i >= 0; ) { | |||
pendingSpans.add(null); | |||
} | |||
} | |||
//if the current cell spans more than one row, | |||
//update pending span list for the next row | |||
if( rowSpan > 1 ) { | |||
for( int i = colSpan; --i >= 0; ) { | |||
pendingSpans.set(columnIndex - 1 + i, | |||
new PendingSpan(rowSpan)); | |||
} | |||
} | |||
//flag column indices used by this cell, | |||
//take into account that possibly not all column-numbers | |||
//are used by columns in the parent table (if any), | |||
//so a cell spanning three columns, might actually | |||
//take up more than three columnIndices... | |||
int startIndex = columnIndex - 1; | |||
int endIndex = startIndex + colSpan; | |||
if( ((Table) parent).columns != null ) { | |||
List cols = ((Table) parent).columns; | |||
int tmpIndex = endIndex; | |||
for( int i = startIndex; i <= tmpIndex; ++i ) { | |||
if( i < cols.size() && cols.get(i) == null ) { | |||
endIndex++; | |||
} | |||
} | |||
} | |||
usedColumnIndices.set(startIndex, endIndex); | |||
setNextColumnIndex(); | |||
super.addChildNode(cell); | |||
if( cell.endsRow() ) { | |||
if( firstRow ) { | |||
firstRow = false; | |||
} | |||
resetColumnIndex(); | |||
} | |||
} | |||
/** | |||
* If table-cells are used as direct children of a table-body|header|footer | |||
@@ -215,5 +289,110 @@ public class TableBody extends FObj { | |||
return (childNodes.size() > 0) | |||
&& (childNodes.get(childNodes.size() - 1) == obj); | |||
} | |||
/** | |||
* Initializes pending spans list; used for correctly | |||
* assigning initial value for column-number for the | |||
* cells of following rows | |||
* | |||
*/ | |||
protected void initPendingSpans() { | |||
if( ((Table) parent).columns != null ) { | |||
List tableCols = ((Table) parent).columns; | |||
pendingSpans = new java.util.ArrayList(tableCols.size()); | |||
for( int i = tableCols.size(); --i >= 0; ) { | |||
pendingSpans.add(null); | |||
} | |||
} | |||
} | |||
/** | |||
* Returns the current column index of the TableBody | |||
* | |||
* @return the next column number to use | |||
*/ | |||
public int getCurrentColumnIndex() { | |||
return columnIndex; | |||
} | |||
/** | |||
* Sets the current column index to a specific value | |||
* (used by TableCell.bind() in case the column-number | |||
* was explicitly specified) | |||
* | |||
*/ | |||
protected void setCurrentColumnIndex(int newIndex) { | |||
columnIndex = newIndex; | |||
} | |||
/** | |||
* Resets the current column index for the TableBody | |||
* | |||
*/ | |||
public void resetColumnIndex() { | |||
columnIndex = 1; | |||
usedColumnIndices.clear(); | |||
PendingSpan pSpan; | |||
for( int i = pendingSpans.size(); --i >= 0; ) { | |||
pSpan = (PendingSpan) pendingSpans.get(i); | |||
if( pSpan != null ) { | |||
pSpan.rowsLeft--; | |||
if( pSpan.rowsLeft == 0 ) { | |||
pendingSpans.set(i, null); | |||
} | |||
} | |||
usedColumnIndices.set(i, pendingSpans.get(i) != null); | |||
} | |||
if( !firstRow ) { | |||
setNextColumnIndex(); | |||
} | |||
} | |||
/** | |||
* Increases columnIndex to the next available value | |||
* | |||
*/ | |||
private void setNextColumnIndex() { | |||
while( usedColumnIndices.get(columnIndex - 1) ) { | |||
//increment columnIndex | |||
columnIndex++; | |||
//if the table has explicit columns, and | |||
//the updated index is not assigned to any | |||
//column, increment further until the next | |||
//index occupied by a column... | |||
if( ((Table) parent).columns != null ) { | |||
while( columnIndex <= ((Table) parent).columns.size() | |||
&& !((Table) parent).isColumnNumberUsed(columnIndex) ) { | |||
columnIndex++; | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Checks whether the previous cell had 'ends-row="true"' | |||
* | |||
* @return false only if there was a previous cell, which | |||
* had ends-row="false" (implicit or explicit) | |||
*/ | |||
public boolean lastCellEndedRow() { | |||
if( childNodes != null ) { | |||
FONode prevNode = (FONode) childNodes.get(childNodes.size() - 1); | |||
if( prevNode.getNameId() == FO_TABLE_CELL ) { | |||
return ((TableCell) prevNode).endsRow(); | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
* Checks whether a given column-number is already in use | |||
* for the current row (used by TableCell.bind()); | |||
* | |||
* @return true if column-number is already occupied | |||
*/ | |||
protected boolean isColumnNumberUsed(int colNr) { | |||
return usedColumnIndices.get(colNr - 1); | |||
} | |||
} | |||
@@ -38,16 +38,12 @@ import org.apache.fop.fo.properties.LengthRangeProperty; | |||
* Class modelling the fo:table-cell object. | |||
* @todo check need for all instance variables stored here | |||
*/ | |||
public class TableCell extends FObj { | |||
public class TableCell extends TableFObj { | |||
// The value of properties relevant for fo:table-cell. | |||
private CommonAccessibility commonAccessibility; | |||
private CommonAural commonAural; | |||
private CommonBorderPaddingBackground commonBorderPaddingBackground; | |||
private CommonRelativePosition commonRelativePosition; | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private Numeric borderEndPrecedence; | |||
private Numeric borderStartPrecedence; | |||
private LengthRangeProperty blockProgressionDimension; | |||
private int borderCollapse; //inherited from fo:table | |||
private LengthPairProperty borderSeparation; //inherited from fo:table | |||
@@ -118,10 +114,6 @@ public class TableCell extends FObj { | |||
commonAural = pList.getAuralProps(); | |||
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); | |||
commonRelativePosition = pList.getRelativePositionProps(); | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); | |||
borderCollapse = pList.get(PR_BORDER_COLLAPSE).getEnum(); | |||
borderSeparation = pList.get(PR_BORDER_SEPARATION).getLengthPair(); | |||
@@ -137,6 +129,24 @@ public class TableCell extends FObj { | |||
numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric(); | |||
startsRow = pList.get(PR_STARTS_ROW).getEnum(); | |||
width = pList.get(PR_WIDTH).getLength(); | |||
super.bind(pList); | |||
//check if any of the column-numbers occupied by this cell | |||
//are already in use in the current row... | |||
for( int i = getColumnNumber(); | |||
++i <= getColumnNumber() + getNumberColumnsSpanned(); ) { | |||
if( ((TableFObj) parent).isColumnNumberUsed(i - 1) ) { | |||
throw new FOPException("cell overlaps in column " + (i - 1), | |||
locator); | |||
} | |||
} | |||
//if column-number was explicitly specified, force the parent's current | |||
//column index to the specified value, so that the updated index will | |||
//be the correct initial value for the next cell (see Rec 7.26.8) | |||
if( pList.getExplicit(PR_COLUMN_NUMBER) != null ) { | |||
((TableFObj) parent).setCurrentColumnIndex( | |||
pList.getExplicit(PR_COLUMN_NUMBER).getNumeric().getValue()); | |||
} | |||
} | |||
/** | |||
@@ -156,7 +166,11 @@ public class TableCell extends FObj { | |||
if (!blockItemFound) { | |||
missingChildElementError("marker* (%block;)+"); | |||
} | |||
//TODO Complain about startsRow|endsRow=true if parent is a table-row | |||
if( (startsRow() || endsRow()) | |||
&& getParent().getNameId() == FO_TABLE_ROW ) { | |||
getLogger().warn("starts-row/ends-row for fo:table-cells " | |||
+ "non-applicable for children of an fo:table-row."); | |||
} | |||
getFOEventHandler().endCell(this); | |||
} | |||
@@ -287,18 +301,11 @@ public class TableCell extends FObj { | |||
return commonBorderPaddingBackground; | |||
} | |||
/** | |||
* @return true if the "column-number" property was set. | |||
*/ | |||
public boolean hasColumnNumber() { | |||
return (columnNumber.getValue() >= 1); | |||
} | |||
/** | |||
* @return the "column-number" property. | |||
*/ | |||
public int getColumnNumber() { | |||
return Math.max(columnNumber.getValue(), 0); | |||
return columnNumber.getValue(); | |||
} | |||
/** @return true if "empty-cells" is "show" */ |
@@ -34,13 +34,9 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
/** | |||
* Class modelling the fo:table-column object. | |||
*/ | |||
public class TableColumn extends FObj { | |||
public class TableColumn extends TableFObj { | |||
// The value of properties relevant for fo:table-column. | |||
private CommonBorderPaddingBackground commonBorderPaddingBackground; | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private Numeric borderEndPrecedence; | |||
private Numeric borderStartPrecedence; | |||
private Numeric columnNumber; | |||
private Length columnWidth; | |||
private Numeric numberColumnsRepeated; | |||
@@ -72,21 +68,32 @@ public class TableColumn extends FObj { | |||
*/ | |||
public void bind(PropertyList pList) throws FOPException { | |||
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric(); | |||
columnWidth = pList.get(PR_COLUMN_WIDTH).getLength(); | |||
numberColumnsRepeated = pList.get(PR_NUMBER_COLUMNS_REPEATED).getNumeric(); | |||
numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric(); | |||
visibility = pList.get(PR_VISIBILITY).getEnum(); | |||
super.bind(pList); | |||
if (columnNumber.getValue() < 0) { | |||
//not catching 0 here because it is the indication that no | |||
//column-number has been specified | |||
throw new PropertyException("column-number must be 1 or bigger, " | |||
+ "but got " + columnNumber.getValue()); | |||
if( pList.getExplicit(PR_COLUMN_NUMBER) != null ) { | |||
if (columnNumber.getValue() <= 0) { | |||
//TODO: This is actually a non-fatal error. See Rec 7.26.8: | |||
//"A positive integer. If a negative or non-integer value | |||
// is provided, the value will be rounded to the | |||
// nearest integer value greater than or equal to 1." | |||
throw new PropertyException("column-number must be 1 or bigger, " | |||
+ "but got " + columnNumber); | |||
} else if( ((Table) parent).isColumnNumberUsed(columnNumber.getValue()) ) { | |||
throw new PropertyException("specified column-number \"" | |||
+ columnNumber | |||
+ "\" has already been assigned to a previous column"); | |||
} else { | |||
//force parent table's current column index | |||
//to the specified value, so that the updated index | |||
//will be the correct initial value for the next column | |||
//(see Rec 7.26.8) | |||
((Table) parent).setCurrentColumnIndex(columnNumber.getValue()); | |||
} | |||
} | |||
if (numberColumnsRepeated.getValue() <= 0) { | |||
throw new PropertyException("number-columns-repeated must be 1 or bigger, " | |||
@@ -135,13 +142,6 @@ public class TableColumn extends FObj { | |||
return columnWidth; | |||
} | |||
/** | |||
* @return true if the "column-number" property was set. | |||
*/ | |||
public boolean hasColumnNumber() { | |||
return (columnNumber.getValue() >= 1); | |||
} | |||
/** | |||
* @return the "column-number" property. | |||
*/ | |||
@@ -182,9 +182,7 @@ public class TableColumn extends FObj { | |||
/** @see java.lang.Object#toString() */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer("fo:table-column"); | |||
if (hasColumnNumber()) { | |||
sb.append(" column-number=").append(getColumnNumber()); | |||
} | |||
sb.append(" column-number=").append(getColumnNumber()); | |||
if (getNumberColumnsRepeated() > 1) { | |||
sb.append(" number-columns-repeated=").append(getNumberColumnsRepeated()); | |||
} |
@@ -0,0 +1,110 @@ | |||
package org.apache.fop.fo.flow; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.datatypes.Numeric; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.FObj; | |||
import org.apache.fop.fo.PropertyList; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
public abstract class TableFObj extends FObj { | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private Numeric borderEndPrecedence; | |||
private Numeric borderStartPrecedence; | |||
protected static class PendingSpan { | |||
protected int rowsLeft; | |||
public PendingSpan( int rows ) { | |||
rowsLeft = rows; | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("pending span: rowsLeft=").append(rowsLeft); | |||
return sb.toString(); | |||
} | |||
} | |||
public TableFObj(FONode parent) { | |||
super(parent); | |||
} | |||
public void bind(PropertyList pList) throws FOPException { | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
} | |||
/** | |||
* | |||
* @param side the side for which to return the border precedence | |||
* @return the "border-precedence" value for the given side | |||
*/ | |||
public Numeric getBorderPrecedence(int side) { | |||
switch( side ) { | |||
case CommonBorderPaddingBackground.BEFORE: | |||
return borderBeforePrecedence; | |||
case CommonBorderPaddingBackground.AFTER: | |||
return borderAfterPrecedence; | |||
case CommonBorderPaddingBackground.START: | |||
return borderStartPrecedence; | |||
case CommonBorderPaddingBackground.END: | |||
return borderEndPrecedence; | |||
default: | |||
return null; | |||
} | |||
} | |||
protected void setBorderPrecedence(int side, Numeric newPrecedence) { | |||
switch( side ) { | |||
case CommonBorderPaddingBackground.BEFORE: | |||
borderBeforePrecedence = newPrecedence; | |||
case CommonBorderPaddingBackground.AFTER: | |||
borderAfterPrecedence = newPrecedence; | |||
case CommonBorderPaddingBackground.START: | |||
borderStartPrecedence = newPrecedence; | |||
case CommonBorderPaddingBackground.END: | |||
borderEndPrecedence = newPrecedence; | |||
} | |||
} | |||
/** | |||
* Returns the current column index of the given TableFObj | |||
* (overridden for Table, TableBody, TableRow) | |||
* | |||
* @return the next column number to use | |||
*/ | |||
public int getCurrentColumnIndex() { | |||
return 0; | |||
} | |||
/** | |||
* Sets the current column index of the given TableFObj | |||
* (overridden for Table, TableBody, TableRow) | |||
*/ | |||
protected void setCurrentColumnIndex(int newIndex) { | |||
//do nothing by default | |||
} | |||
/** | |||
* Checks if a certain column-number is already occupied | |||
* (overridden for Table, TableBody, TableRow) | |||
* | |||
* @param colNr the column-number to check | |||
* @return true if column-number is already in use | |||
*/ | |||
protected boolean isColumnNumberUsed(int colNr) { | |||
return false; | |||
} | |||
/** | |||
* @return the Common Border, Padding, and Background Properties. | |||
*/ | |||
public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); | |||
} |
@@ -39,7 +39,8 @@ public class TableFooter extends TableBody { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
// getFOEventHandler().startBody(this); | |||
initPendingSpans(); | |||
//getFOEventHandler().startBody(this); | |||
} | |||
/** |
@@ -39,7 +39,8 @@ public class TableHeader extends TableBody { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
// getFOEventHandler().startHeader(this); | |||
initPendingSpans(); | |||
//getFOEventHandler().startHeader(this); | |||
} | |||
/** |
@@ -18,6 +18,9 @@ | |||
package org.apache.fop.fo.flow; | |||
import java.util.BitSet; | |||
import java.util.List; | |||
import org.xml.sax.Locator; | |||
import org.apache.fop.apps.FOPException; | |||
@@ -37,17 +40,13 @@ import org.apache.fop.fo.properties.LengthRangeProperty; | |||
/** | |||
* Class modelling the fo:table-row object. | |||
*/ | |||
public class TableRow extends FObj { | |||
public class TableRow extends TableFObj { | |||
// The value of properties relevant for fo:table-row. | |||
private CommonAccessibility commonAccessibility; | |||
private LengthRangeProperty blockProgressionDimension; | |||
private CommonAural commonAural; | |||
private CommonBorderPaddingBackground commonBorderPaddingBackground; | |||
private CommonRelativePosition commonRelativePosition; | |||
private Numeric borderAfterPrecedence; | |||
private Numeric borderBeforePrecedence; | |||
private Numeric borderEndPrecedence; | |||
private Numeric borderStartPrecedence; | |||
private int breakAfter; | |||
private int breakBefore; | |||
private Length height; | |||
@@ -59,6 +58,10 @@ public class TableRow extends FObj { | |||
// End of property values | |||
private boolean setup = false; | |||
private List pendingSpans; | |||
private BitSet usedColumnIndices; | |||
private int columnIndex = 1; | |||
/** | |||
* @param parent FONode that is the parent of this object | |||
@@ -76,10 +79,6 @@ public class TableRow extends FObj { | |||
commonAural = pList.getAuralProps(); | |||
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); | |||
commonRelativePosition = pList.getRelativePositionProps(); | |||
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); | |||
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); | |||
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); | |||
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); | |||
breakAfter = pList.get(PR_BREAK_AFTER).getEnum(); | |||
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum(); | |||
id = pList.get(PR_ID).getString(); | |||
@@ -88,6 +87,7 @@ public class TableRow extends FObj { | |||
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); | |||
keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); | |||
visibility = pList.get(PR_VISIBILITY).getEnum(); | |||
super.bind(pList); | |||
} | |||
/** | |||
@@ -107,6 +107,12 @@ public class TableRow extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
pendingSpans = ((TableBody) parent).pendingSpans; | |||
usedColumnIndices = ((TableBody) parent).usedColumnIndices; | |||
while( usedColumnIndices.get(columnIndex - 1) ) { | |||
columnIndex++; | |||
} | |||
checkId(id); | |||
getFOEventHandler().startRow(this); | |||
} | |||
@@ -118,6 +124,16 @@ public class TableRow extends FObj { | |||
if (childNodes == null) { | |||
missingChildElementError("(table-cell+)"); | |||
} | |||
if( ((TableBody) parent).isFirst(this) | |||
&& ((Table) parent.getParent()).columns == null ) { | |||
//force parent body's pendingSpans | |||
//to the one accumulated after processing this row | |||
((TableBody) parent).pendingSpans = pendingSpans; | |||
} | |||
((TableBody) parent).resetColumnIndex(); | |||
//release references | |||
pendingSpans = null; | |||
usedColumnIndices = null; | |||
getFOEventHandler().endRow(this); | |||
} | |||
@@ -131,6 +147,55 @@ public class TableRow extends FObj { | |||
invalidChildError(loc, nsURI, localName); | |||
} | |||
} | |||
/** | |||
* @see org.apache.fop.fo.FONode#addChildNode(FONode) | |||
*/ | |||
protected void addChildNode(FONode child) throws FOPException { | |||
TableCell cell = (TableCell) child; | |||
int rowSpan = cell.getNumberRowsSpanned(); | |||
int colSpan = cell.getNumberColumnsSpanned(); | |||
if( ((TableBody) parent).isFirst(this) | |||
&& ((Table) parent.getParent()).columns == null ) { | |||
if( pendingSpans == null ) { | |||
pendingSpans = new java.util.ArrayList(); | |||
} | |||
pendingSpans.add(null); | |||
if( usedColumnIndices == null ) { | |||
usedColumnIndices = new BitSet(); | |||
} | |||
} | |||
//if the current cell spans more than one row, | |||
//update pending span list for the next row | |||
if( rowSpan > 1 ) { | |||
for( int i = colSpan; --i >= 0; ) { | |||
pendingSpans.set(columnIndex - 1 + i, | |||
new PendingSpan(rowSpan)); | |||
} | |||
} | |||
//flag column indices used by this cell, | |||
//take into account that possibly not all column-numbers | |||
//are used by columns in the parent table (if any), | |||
//so a cell spanning three columns, might actually | |||
//take up more than three columnIndices... | |||
int startIndex = columnIndex - 1; | |||
int endIndex = startIndex + colSpan; | |||
if( ((Table) parent.getParent()).columns != null ) { | |||
List cols = ((Table) parent.getParent()).columns; | |||
int tmpIndex = endIndex; | |||
for( int i = startIndex; i <= tmpIndex; ++i ) { | |||
if( i < cols.size() && cols.get(i) == null ) { | |||
endIndex++; | |||
} | |||
} | |||
} | |||
usedColumnIndices.set(startIndex, endIndex); | |||
//update columnIndex for the next cell | |||
while( usedColumnIndices.get(columnIndex - 1) ) { | |||
columnIndex++; | |||
} | |||
super.addChildNode(cell); | |||
} | |||
/** | |||
* @return the "id" property. | |||
@@ -221,4 +286,33 @@ public class TableRow extends FObj { | |||
public int getNameId() { | |||
return FO_TABLE_ROW; | |||
} | |||
/** | |||
* Returns the current column index of the TableRow | |||
* | |||
* @return the next column number to use | |||
*/ | |||
public int getCurrentColumnIndex() { | |||
return columnIndex; | |||
} | |||
/** | |||
* Sets the current column index to a specific value | |||
* in case a column-number was explicitly specified | |||
* (used by TableCell.bind()) | |||
* | |||
*/ | |||
protected void setCurrentColumnIndex(int newIndex) { | |||
columnIndex = newIndex; | |||
} | |||
/** | |||
* Checks whether a given column-number is already in use | |||
* for the current row (used by TableCell.bind()); | |||
* | |||
* @return true if column-number is already occupied | |||
*/ | |||
protected boolean isColumnNumberUsed(int colNr) { | |||
return usedColumnIndices.get(colNr - 1); | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
/* | |||
* Copyright 2005 The Apache Software Foundation. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.fo.properties; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.FObj; | |||
import org.apache.fop.fo.PropertyList; | |||
import org.apache.fop.fo.expr.PropertyException; | |||
import org.apache.fop.fo.flow.TableFObj; | |||
import org.apache.fop.fo.flow.TableBody; | |||
public class ColumnNumberPropertyMaker extends NumberProperty.Maker { | |||
public ColumnNumberPropertyMaker(int propId) { | |||
super(propId); | |||
} | |||
/** | |||
* Set default column-number from parent's currentColumnIndex | |||
* | |||
* @return the default value for column-number | |||
*/ | |||
public Property make(PropertyList propertyList) throws PropertyException { | |||
FObj fo = propertyList.getFObj(); | |||
if( fo.getNameId() == Constants.FO_TABLE_CELL | |||
|| fo.getNameId() == Constants.FO_TABLE_COLUMN ) { | |||
TableFObj parent = (TableFObj) propertyList.getParentFObj(); | |||
int columnIndex = parent.getCurrentColumnIndex(); | |||
if( fo.getNameId() == Constants.FO_TABLE_CELL | |||
&& parent.getNameId() == Constants.FO_TABLE_BODY ) { | |||
boolean startsRow = propertyList.get(Constants.PR_STARTS_ROW) | |||
.getEnum() == Constants.EN_TRUE; | |||
//cell w/ starts-row="true", but previous cell | |||
//didn't have ends-row="true", so index has still has | |||
//to be reset (for other cases this already happened in | |||
//body.addChildNode()) | |||
if( startsRow && !((TableBody) parent).lastCellEndedRow() ) { | |||
//reset column index, and reassign... | |||
((TableBody) parent).resetColumnIndex(); | |||
columnIndex = parent.getCurrentColumnIndex(); | |||
} | |||
} | |||
return new NumberProperty(columnIndex); | |||
} else { | |||
throw new PropertyException("column-number property is only allowed on " | |||
+ "fo:table-cell or fo:table-column, not on " + fo.getName()); | |||
} | |||
} | |||
} |
@@ -60,7 +60,7 @@ public class ColumnSetup { | |||
ListIterator iter = rawCols.listIterator(); | |||
while (iter.hasNext()) { | |||
TableColumn col = (TableColumn)iter.next(); | |||
if (col.hasColumnNumber()) { | |||
if( col != null ) { | |||
colnum = col.getColumnNumber(); | |||
} | |||
for (int i = 0; i < col.getNumberColumnsRepeated(); i++) { | |||
@@ -151,7 +151,9 @@ public class ColumnSetup { | |||
public int getXOffset(int col, PercentBaseContext context) { | |||
int xoffset = 0; | |||
for (int i = 1; i < col; i++) { | |||
xoffset += getColumn(i).getColumnWidth().getValue(context); | |||
if( getColumn(i) != null ) { | |||
xoffset += getColumn(i).getColumnWidth().getValue(context); | |||
} | |||
} | |||
return xoffset; | |||
} |
@@ -439,8 +439,10 @@ public class TableContentLayoutManager implements PercentBaseContext { | |||
i < primary.getStartCol() | |||
+ primary.getCell().getNumberColumnsSpanned(); | |||
i++) { | |||
spanWidth += getTableLM().getColumns().getColumn(i + 1) | |||
.getColumnWidth().getValue(getTableLM()); | |||
if( getTableLM().getColumns().getColumn(i + 1) != null ) { | |||
spanWidth += getTableLM().getColumns().getColumn(i + 1) | |||
.getColumnWidth().getValue(getTableLM()); | |||
} | |||
} | |||
LayoutContext childLC = new LayoutContext(0); | |||
childLC.setStackLimit(context.getStackLimit()); //necessary? |
@@ -156,10 +156,12 @@ public class TableLayoutManager extends BlockStackingLayoutManager | |||
float factors = 0; | |||
for (Iterator i = columns.iterator(); i.hasNext();) { | |||
TableColumn column = (TableColumn) i.next(); | |||
Length width = column.getColumnWidth(); | |||
sumCols += width.getValue(this); | |||
if (width instanceof TableColLength) { | |||
factors += ((TableColLength) width).getTableUnits(); | |||
if( column != null ) { | |||
Length width = column.getColumnWidth(); | |||
sumCols += width.getValue(this); | |||
if (width instanceof TableColLength) { | |||
factors += ((TableColLength) width).getTableUnits(); | |||
} | |||
} | |||
} | |||
// sets TABLE_UNITS in case where one or more oldColumns is defined using |
@@ -362,15 +362,12 @@ public class TableRowIterator { | |||
while (iter.hasNext()) { | |||
TableCell cell = (TableCell)iter.next(); | |||
if (cell.hasColumnNumber()) { | |||
colnum = cell.getColumnNumber(); | |||
} else { | |||
//Skip columns with spanning grid units | |||
while (safelyGetListItem(gridUnits, colnum - 1) != null) { | |||
colnum++; | |||
} | |||
} | |||
colnum = cell.getColumnNumber(); | |||
//TODO: remove the check below??? | |||
//shouldn't happen here, since | |||
//overlapping cells already caught in | |||
//fo.flow.TableCell.bind()... | |||
if (safelyGetListItem(gridUnits, colnum - 1) != null) { | |||
log.error("Overlapping cell at position " + colnum); | |||
//TODO throw layout exception |