]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Implementation for initial values of the column-number property
authorAndreas L. Delmelle <adelmelle@apache.org>
Sat, 17 Sep 2005 23:59:25 +0000 (23:59 +0000)
committerAndreas L. Delmelle <adelmelle@apache.org>
Sat, 17 Sep 2005 23:59:25 +0000 (23:59 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@289865 13f79535-47bb-0310-9956-ffa450edef68

14 files changed:
src/java/org/apache/fop/fo/FOPropertyMapping.java
src/java/org/apache/fop/fo/flow/Table.java
src/java/org/apache/fop/fo/flow/TableBody.java
src/java/org/apache/fop/fo/flow/TableCell.java
src/java/org/apache/fop/fo/flow/TableColumn.java
src/java/org/apache/fop/fo/flow/TableFObj.java [new file with mode: 0644]
src/java/org/apache/fop/fo/flow/TableFooter.java
src/java/org/apache/fop/fo/flow/TableHeader.java
src/java/org/apache/fop/fo/flow/TableRow.java
src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java
src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java

index fca91b15b108ae89696c3c6079e2a69b0d7db9e5..d03e623e5ecf85225895859857aa88369586b6bc 100644 (file)
@@ -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
index e958c3c641a412092766a923df6d712504d4422c..474efc6b7a6b7d44477991d5ba139f6d2268091b 100644 (file)
@@ -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);
+    }
 }
index f5d91e6a41538be44080f3125ccc42998fb805a9..5d44fec4701676f733ac58b8bb6a38eb989deefd 100644 (file)
@@ -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);
+    }
 }
 
index b3583d37f014b82a91662512e4e1b5df6e31422a..216ada8ab289e6f7206b9e0dc7a7d5a9149b07d6 100644 (file)
@@ -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" */
index a0aa9d64739ca8958bbf6deae5d094e5b978d294..107c1df7f58bb122462303655e435655df779c15 100644 (file)
@@ -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());
         }
diff --git a/src/java/org/apache/fop/fo/flow/TableFObj.java b/src/java/org/apache/fop/fo/flow/TableFObj.java
new file mode 100644 (file)
index 0000000..3592c00
--- /dev/null
@@ -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();
+
+}
index 09cba1cc342e1f3947e8e56c9338603bf1e069e6..d0ec6de66e08f08c472f60353897d08db8e4b929 100644 (file)
@@ -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);
     }
 
     /**
index 41187b060ecd7fa9dd6559af8fc7c04a66a1f839..4745daf987d6a127f17a03f268e8622e988a5912 100644 (file)
@@ -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);
     }
 
     /**
index 516be056e1eb93a08db4a9b968fc802959d79687..18baabf2cdad43229ab0fe3ee5162f1c4ff70f13 100644 (file)
@@ -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);
+    }
 }
diff --git a/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java b/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java
new file mode 100644 (file)
index 0000000..f4ab5c6
--- /dev/null
@@ -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());
+        }
+    }
+}
index 8df556afcdd880d41130cfe0473694cbd1212ace..cf3a6af0590ff737cfbebcb1ce0b16335ee6bdbf 100644 (file)
@@ -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;
     }
index bb4112483e6f2d33a9ac64e0c595632d6b2442c0..cbaf1a8f3c41da43507d77299208b2f243e2342e 100644 (file)
@@ -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?
index 1a5bf7fa5c432446d7ee19ec556ed6afdc2ae6c1..5b1576c977b871e947d83c26741efed3676f5432 100644 (file)
@@ -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 
index e6d6ff3307a9238c66df67eefa2e80a04cd2b4db..0781d4ee608694fbd12238405b81ea013c24275b 100644 (file)
@@ -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