]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
- factored the management of column numbers into a separate helper class
authorVincent Hennebert <vhennebert@apache.org>
Tue, 30 Oct 2007 16:21:39 +0000 (16:21 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Tue, 30 Oct 2007 16:21:39 +0000 (16:21 +0000)
- moved the PendingSpan inner class from TableFObj into TableCellContainer, where it's a bit more appropriate
- simplified the getTable method in TableFObj by overriding it in Table
- simplified the propertyMaker for column-number: now it's the table-cell which notifies the parent table-body that it starts a new row. As an additional benefit the propertyMaker for starts-row is now called only once, instead of twice before
- reworked, factored and simplified the handling of column indices in TableCellContainer
- bugfix: repeated fo:table-column were not added at the right place in the column lists
- bugfix: width set on cell on second row was applied to the column's width, whereas it shouldn't
- checkstyle cleanup

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@590136 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java
src/java/org/apache/fop/fo/flow/ColumnNumberManager.java [new file with mode: 0644]
src/java/org/apache/fop/fo/flow/ColumnNumberManagerHolder.java [new file with mode: 0644]
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/TableCellContainer.java
src/java/org/apache/fop/fo/flow/TableColumn.java
src/java/org/apache/fop/fo/flow/TableFObj.java
src/java/org/apache/fop/fo/flow/TableRow.java

index 8b14a0c64c9c938fe09d588e3bd727f7598a12cc..651f9345102bd1b93338b7240b1a473c9b6c910c 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.FOPropertyMapping;
+import org.apache.fop.fo.flow.ColumnNumberManager;
 import org.apache.fop.fo.flow.Table;
 import org.apache.fop.fo.flow.TableCell;
 import org.apache.fop.fo.flow.TableColumn;
@@ -61,9 +62,9 @@ public class FromTableColumnFunction extends FunctionBase {
      */
     public Property eval(Property[] args,
                          PropertyInfo pInfo) throws PropertyException {
-        
+
         FObj fo = pInfo.getPropertyList().getFObj();
-        
+
         /* obtain property Id for the property for which the function is being
          * evaluated */
         int propId = 0;
@@ -73,7 +74,7 @@ public class FromTableColumnFunction extends FunctionBase {
             String propName = args[0].getString();
             propId = FOPropertyMapping.getPropertyId(propName);
         }
-        
+
         /* make sure we have a correct property id ... */
         if (propId != -1) {
             /* obtain column number for which the function is being evaluated: */
@@ -81,7 +82,7 @@ public class FromTableColumnFunction extends FunctionBase {
             int span = 0;
             if (fo.getNameId() != Constants.FO_TABLE_CELL) {
                 // climb up to the nearest cell
-                do { 
+                do {
                     fo = (FObj) fo.getParent();
                 } while (fo.getNameId() != Constants.FO_TABLE_CELL
                           && fo.getNameId() != Constants.FO_PAGE_SEQUENCE);
@@ -105,19 +106,20 @@ public class FromTableColumnFunction extends FunctionBase {
             /* return the property from the column */
             Table t = ((TableFObj) fo).getTable();
             List cols = t.getColumns();
+            ColumnNumberManager columnIndexManager = t.getColumnNumberManager();
             if (cols == null) {
                 //no columns defined => no match: return default value
                 return pInfo.getPropertyList().get(propId, false, true);
             } else {
-                if (t.isColumnNumberUsed(columnNumber)) {
+                if (columnIndexManager.isColumnNumberUsed(columnNumber)) {
                     //easiest case: exact match
                     return ((TableColumn) cols.get(columnNumber - 1)).getProperty(propId);
                 } else {
                     //no exact match: try all spans...
-                    while (--span > 0 && !t.isColumnNumberUsed(++columnNumber)) {
+                    while (--span > 0 && !columnIndexManager.isColumnNumberUsed(++columnNumber)) {
                         //nop: just increment/decrement
                     }
-                    if (t.isColumnNumberUsed(columnNumber)) {
+                    if (columnIndexManager.isColumnNumberUsed(columnNumber)) {
                         return ((TableColumn) cols.get(columnNumber - 1)).getProperty(propId);
                     } else {
                         //no match: return default value
diff --git a/src/java/org/apache/fop/fo/flow/ColumnNumberManager.java b/src/java/org/apache/fop/fo/flow/ColumnNumberManager.java
new file mode 100644 (file)
index 0000000..bc31440
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.flow;
+
+import java.util.BitSet;
+import java.util.List;
+
+import org.apache.fop.fo.flow.TableCellContainer.PendingSpan;
+
+/**
+ * Helper class maintaining a record of occupied columns and an index to the next
+ * non-occupied column.
+ */
+public class ColumnNumberManager {
+
+    private int columnNumber = 1;
+
+    /**
+     * We use the term "index" instead of "number" because, unlike column numbers, it's
+     * 0-based.
+     */
+    private BitSet usedColumnIndices = new BitSet();
+
+    /**
+     * Returns the number of the column that shall receive the next parsed cell.
+     * 
+     * @return a column number, 1-based
+     */
+    int getCurrentColumnNumber() {
+        return columnNumber;
+    }
+
+    /**
+     * Flags columns <code>start</code> to <code>end</code> as occupied,
+     * and updates the number of the next available column.
+     * 
+     * @param start start number, inclusive, 1-based
+     * @param end   end number, inclusive
+     */
+    void signalUsedColumnNumbers(int start, int end) {
+        for (int i = start - 1; i < end; i++) {
+            usedColumnIndices.set(i);
+        }
+
+        while (usedColumnIndices.get(columnNumber - 1)) {
+            columnNumber++;
+        }
+    }
+
+    /**
+     * Resets the record of occupied columns, taking into account columns already occupied
+     * by previous spanning cells, and computes the number of the first free column.
+     * 
+     * @param pendingSpans List&lt;PendingSpan&gt; of possible spans over the next row
+     */
+    void prepareForNextRow(List pendingSpans) {
+        usedColumnIndices.clear();
+        PendingSpan pSpan;
+        for (int i = 0; i < pendingSpans.size(); i++) {
+            pSpan = (PendingSpan) pendingSpans.get(i);
+            if (pSpan != null) {
+                pSpan.rowsLeft--;
+                if (pSpan.rowsLeft == 0) {
+                    pendingSpans.set(i, null);
+                } else {
+                    usedColumnIndices.set(i);
+                }
+            }
+        }
+        // Set columnNumber to the first available column
+        columnNumber = 1;
+        while (usedColumnIndices.get(columnNumber - 1)) {
+            columnNumber++;
+        }
+}
+
+    /**
+     * Checks whether a given column-number is already in use
+     * for the current row.
+     * 
+     * @param colNr the column-number to check
+     * @return true if column-number is already occupied
+     */
+    public boolean isColumnNumberUsed(int colNr) {
+        return usedColumnIndices.get(colNr - 1);
+    }
+
+    /**
+     * Sets the current column index to a specific value
+     * (used by ColumnNumberPropertyMaker.make() in case the 
+     *  column-number was explicitly specified on the cell)
+     * 
+     * @param newIndex  the new column index
+     */
+    void setCurrentColumnIndex(int newIndex) {
+        columnNumber = newIndex;
+    }
+
+}
diff --git a/src/java/org/apache/fop/fo/flow/ColumnNumberManagerHolder.java b/src/java/org/apache/fop/fo/flow/ColumnNumberManagerHolder.java
new file mode 100644 (file)
index 0000000..157ca74
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.flow;
+
+/**
+ * Marking interface for table-related classes which contain a ColumnNumberManager
+ * instance (Table, for registering columns, or TableCellContainer, for managing occupied
+ * cells).
+ */
+public interface ColumnNumberManagerHolder {
+
+    /**
+     * Returns the encapsulated ColumnNumberManage instance.
+     * 
+     * @return a {@link ColumnNumberManager} instance
+     */
+    ColumnNumberManager getColumnNumberManager();
+}
index e8f60701235f101d3a5011561d843f750f3879ba..7bc2d49ec469d53f3a06f0ea5aae57b798c8a65b 100644 (file)
 package org.apache.fop.fo.flow;
 
 import java.util.ArrayList;
-import java.util.BitSet;
 import java.util.List;
 
-import org.xml.sax.Locator;
-
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.datatypes.ValidationPercentBaseContext;
@@ -38,12 +35,13 @@ import org.apache.fop.fo.properties.CommonMarginBlock;
 import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.fo.properties.LengthPairProperty;
 import org.apache.fop.fo.properties.LengthRangeProperty;
+import org.xml.sax.Locator;
 
 /**
  * Class modelling the fo:table object.
  */
-public class Table extends TableFObj {
-    
+public class Table extends TableFObj implements ColumnNumberManagerHolder {
+
     /** properties */
     private CommonBorderPaddingBackground commonBorderPaddingBackground;
     private CommonMarginBlock commonMarginBlock;
@@ -65,35 +63,33 @@ public class Table extends TableFObj {
     //     private CommonRelativePosition commonRelativePosition;
     //     private int intrusionDisplace;
     //     private int writingMode;
-    
+
     /** extension properties */
     private Length widowContentLimit;
     private Length orphanContentLimit;
 
     /** collection of columns in this table */
     private List columns = new ArrayList();
-    
-    /** helper variables for implicit column-numbering */
-    private int columnIndex = 1;
-    private BitSet usedColumnIndices = new BitSet();
-    
+
+    private ColumnNumberManager columnNumberManager = new ColumnNumberManager();
+
     /** the table-header and -footer */
     private TableBody tableHeader = null;
     private TableBody tableFooter = null;
-  
+
     /** used for validation */
     private boolean tableColumnFound = false;
-    private boolean tableHeaderFound = false;   
-    private boolean tableFooterFound = false;   
-    private boolean tableBodyFound = false; 
+    private boolean tableHeaderFound = false;
+    private boolean tableFooterFound = false;
+    private boolean tableBodyFound = false;
 
     /**
-     * The table's property list. Used in case the table has 
-     * no explicit columns, as a parent property list to 
+     * The table's property list. Used in case the table has
+     * no explicit columns, as a parent property list to
      * internally generated TableColumns
      */
     private PropertyList propList;
-    
+
     /**
      * @param parent FONode that is the parent of this object
      */
@@ -133,7 +129,7 @@ public class Table extends TableFObj {
         if (tableLayout == EN_AUTO) {
             attributeWarning("table-layout=\"auto\" is currently not supported by FOP");
         }
-        if (!isSeparateBorderModel() 
+        if (!isSeparateBorderModel()
                 && getCommonBorderPaddingBackground().hasPadding(
                         ValidationPercentBaseContext.getPseudoContext())) {
             //See "17.6.2 The collapsing border model" in CSS2
@@ -141,7 +137,7 @@ public class Table extends TableFObj {
                     + " (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders)"
                     + ", but a non-zero value for padding was found. The padding will be ignored.");
         }
-        
+
         /* Store reference to the property list, so
          * new lists can be created in case the table has no
          * explicit columns
@@ -157,24 +153,24 @@ public class Table extends TableFObj {
         super.startOfNode();
         getFOEventHandler().startTable(this);
     }
-   
+
     /**
      * {@inheritDoc}
      * XSL Content Model: (marker*,table-column*,table-header?,table-footer?,table-body+)
      */
-    protected void validateChildNode(Locator loc, String nsURI, String localName) 
+    protected void validateChildNode(Locator loc, String nsURI, String localName)
         throws ValidationException {
         if (FO_URI.equals(nsURI)) {
             if ("marker".equals(localName)) {
-                if (tableColumnFound || tableHeaderFound || tableFooterFound 
+                if (tableColumnFound || tableHeaderFound || tableFooterFound
                         || tableBodyFound) {
-                   nodesOutOfOrderError(loc, "fo:marker", 
+                   nodesOutOfOrderError(loc, "fo:marker",
                        "(table-column*,table-header?,table-footer?,table-body+)");
                 }
             } else if ("table-column".equals(localName)) {
                 tableColumnFound = true;
                 if (tableHeaderFound || tableFooterFound || tableBodyFound) {
-                    nodesOutOfOrderError(loc, "fo:table-column", 
+                    nodesOutOfOrderError(loc, "fo:table-column",
                         "(table-header?,table-footer?,table-body+)");
                 }
             } else if ("table-header".equals(localName)) {
@@ -183,8 +179,8 @@ public class Table extends TableFObj {
                 } else {
                     tableHeaderFound = true;
                     if (tableFooterFound || tableBodyFound) {
-                        nodesOutOfOrderError(loc, "fo:table-header", 
-                            "(table-footer?,table-body+)"); 
+                        nodesOutOfOrderError(loc, "fo:table-header",
+                            "(table-footer?,table-body+)");
                     }
                 }
             } else if ("table-footer".equals(localName)) {
@@ -193,7 +189,7 @@ public class Table extends TableFObj {
                 } else {
                     tableFooterFound = true;
                     if (tableBodyFound && getUserAgent().validateStrictly()) {
-                        nodesOutOfOrderError(loc, "fo:table-footer", 
+                        nodesOutOfOrderError(loc, "fo:table-footer",
                             "(table-body+)");
                     }
                 }
@@ -211,7 +207,7 @@ public class Table extends TableFObj {
      * {@inheritDoc}
      */
     protected void endOfNode() throws FOPException {
-        
+
         if (!tableBodyFound) {
            missingChildElementError(
                    "(marker*,table-column*,table-header?,table-footer?"
@@ -228,16 +224,16 @@ public class Table extends TableFObj {
             this.propList = null;
         }
         getFOEventHandler().endTable(this);
-        
+
     }
 
     /**
      * {@inheritDoc}
      */
     protected void addChildNode(FONode child) throws FOPException {
-        
+
         int childId = child.getNameId();
-        
+
         switch (childId) {
         case FO_TABLE_COLUMN:
             if (!inMarker()) {
@@ -246,33 +242,32 @@ public class Table extends TableFObj {
                 columns.add((TableColumn) child);
             }
             return;
-        case FO_MARKER:
-            super.addChildNode(child);
-            return;
+        case FO_TABLE_FOOTER:
+            tableFooter = (TableBody) child;
+            break;
+        case FO_TABLE_HEADER:
+            tableHeader = (TableBody) child;
+            break;
         default:
-            switch (childId) {
-            case FO_TABLE_FOOTER:
-                tableFooter = (TableBody) child;
-                break;
-            case FO_TABLE_HEADER:
-                tableHeader = (TableBody) child;
-                break;
-            default:
-                super.addChildNode(child);
-            }
+            super.addChildNode(child);
         }
     }
-    
+
+    /** {@inheritDoc} */
+    public Table getTable() {
+        return this;
+    }
+
     /**
-     * Adds a default column to the columns list (called from 
-     * TableBody.addChildNode() when the table has no explicit 
+     * Adds a default column to the columns list (called from
+     * TableBody.addChildNode() when the table has no explicit
      * columns, and if processing the first row)
      * 
      * @param colWidth  the column's width (null if the default should be used)
      * @param colNr     the column-number from the cell
      * @throws FOPException  if there was an error creating the property list
      */
-    protected void addDefaultColumn(Length colWidth, int colNr) 
+    void addDefaultColumn(Length colWidth, int colNr)
                     throws FOPException {
         TableColumn defaultColumn = new TableColumn(this, true);
         PropertyList pList = new StaticPropertyList(
@@ -293,38 +288,29 @@ public class Table extends TableFObj {
      * used for determining initial values for column-number
      * 
      * @param col   the column to add
-     * @throws FOPException 
+     * @throws FOPException
      */
     private void addColumnNode(TableColumn col) {
-        
+
         int colNumber = col.getColumnNumber();
         int colRepeat = col.getNumberColumnsRepeated();
-        
-        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);
-            }
+
+        /* add nulls for non-occupied indices between
+         * the last column up to and including the current one
+         */
+        while (columns.size() < colNumber + colRepeat - 1) {
+            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 (?)
-            for (int i = colRepeat - 1; --i >= 0;) {
-                columns.add(col);
-            }
+
+        // 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 (?)
+        for (int i = colNumber - 1; i < colNumber + colRepeat - 1; i++) {
+            columns.set(i, col);
         }
-        //flag column indices used by this column
-        int startIndex = columnIndex - 1;
-        int endIndex = startIndex + colRepeat;
-        flagColumnIndices(startIndex, endIndex);
+
+        columnNumberManager.signalUsedColumnNumbers(colNumber, colNumber + colRepeat - 1);
     }
 
     /** @return true of table-layout="auto" */
@@ -345,7 +331,7 @@ public class Table extends TableFObj {
      * Returns the column at the given index, if any.
      * 
      * @param index index of the column to be retrieved, 0-based
-     * @return the corresponding column, or null if their is no column at the given index 
+     * @return the corresponding column, or null if their is no column at the given index
      */
     TableColumn getColumn(int index) {
         if (index >= columns.size()) {
@@ -355,6 +341,11 @@ public class Table extends TableFObj {
         }
     }
 
+    /**
+     * Returns the number of columns of this table.
+     * 
+     * @return the number of columns, implicit or explicit, in this table
+     */
     int getNumberOfColumns() {
         return columns.size();
     }
@@ -368,7 +359,7 @@ public class Table extends TableFObj {
     public TableBody getTableFooter() {
         return tableFooter;
     }
-    
+
     /** @return true if the table-header should be omitted at breaks */
     public boolean omitHeaderAtBreak() {
         return (this.tableOmitHeaderAtBreak == EN_TRUE);
@@ -392,7 +383,7 @@ public class Table extends TableFObj {
     public LengthRangeProperty getBlockProgressionDimension() {
         return blockProgressionDimension;
     }
-    
+
     /**
      * @return the Common Margin Properties-Block.
      */
@@ -440,7 +431,7 @@ public class Table extends TableFObj {
         return !getKeepTogether().getWithinPage().isAuto()
                 || !getKeepTogether().getWithinColumn().isAuto();
     }
-    
+
     /** @return the "border-collapse" property. */
     public int getBorderCollapse() {
         return borderCollapse;
@@ -450,12 +441,12 @@ public class Table extends TableFObj {
     public boolean isSeparateBorderModel() {
         return (getBorderCollapse() == EN_SEPARATE);
     }
-    
+
     /** @return the "border-separation" property. */
     public LengthPairProperty getBorderSeparation() {
         return borderSeparation;
     }
-    
+
     /** @return the "fox:widow-content-limit" extension property */
     public Length getWidowContentLimit() {
         return widowContentLimit;
@@ -477,50 +468,7 @@ public class Table extends TableFObj {
     }
 
     /**
-     * Returns the current column index of the Table
-     * 
-     * @return the next column number to use
-     */
-    public int getCurrentColumnIndex() {
-        return columnIndex;
-    }
-
-    /**
-     * 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
-     */
-    public boolean isColumnNumberUsed(int colNr) {
-        return usedColumnIndices.get(colNr - 1);
-    }
-
-    /**
-     * Sets the current column index of the given Table
-     * (used by ColumnNumberPropertyMaker.make() in case the column-number
-     * was explicitly specified)
-     * 
-     * @param   newIndex    the new value for column index
-     */
-    public void setCurrentColumnIndex(int newIndex) {
-        columnIndex = newIndex;
-    }
-    
-    /**
-     * {@inheritDoc} 
-     */
-    protected void flagColumnIndices(int start, int end) {
-        for (int i = start; i < end; i++) {
-            usedColumnIndices.set(i);
-        }
-        //set index for the next column to use
-        while (usedColumnIndices.get(columnIndex - 1)) {
-            columnIndex++;
-        }
-    }
-    
-    /**
-     * {@inheritDoc} 
+     * {@inheritDoc}
      */
     public FONode clone(FONode parent, boolean removeChildren)
         throws FOPException {
@@ -533,4 +481,9 @@ public class Table extends TableFObj {
         }
         return fobj;
     }
+
+    /** {@inheritDoc} */
+    public ColumnNumberManager getColumnNumberManager() {
+        return columnNumberManager;
+    }
 }
index cef5c78a1f263a227c48288646dfdfd9e35c8a57..e18675aa0fc9e8527e8337602c53a787da502aac 100644 (file)
 package org.apache.fop.fo.flow;
 
 // Java
-import java.util.BitSet;
-import java.util.List;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.Locator;
-
 import org.apache.fop.apps.FOPException;
-import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
 
 /**
  * Class modelling the fo:table-body object.
@@ -45,21 +40,20 @@ public class TableBody extends TableCellContainer {
     //     private CommonRelativePosition commonRelativePosition;
     //    private int visibility;
     // End of property values
-    
+
     /**
      * used for validation
      */
     protected boolean tableRowsFound = false;
     protected boolean tableCellsFound = false;
-    
+
     /**
      * used for initial values of column-number property
      */
-    protected List pendingSpans;
-    protected BitSet usedColumnIndices;
-    private int columnIndex = 1;
-    protected boolean firstRow = true;
-    
+    private boolean firstRow = true;
+
+    private boolean rowsStarted = false;
+
     /**
      * @param parent FONode that is the parent of the object
      */
@@ -74,12 +68,12 @@ public class TableBody extends TableCellContainer {
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         super.bind(pList);
     }
-    
+
     /**
-     * {@inheritDoc} 
+     * {@inheritDoc}
      */
-    public void processNode(String elementName, Locator locator, 
-                            Attributes attlist, PropertyList pList) 
+    public void processNode(String elementName, Locator locator,
+                            Attributes attlist, PropertyList pList)
                     throws FOPException {
         if (!inMarker()) {
             int cap = getTable().getNumberOfColumns();
@@ -87,8 +81,7 @@ public class TableBody extends TableCellContainer {
                 cap = 10; // Default value for ArrayList
             }
             pendingSpans = new java.util.ArrayList(cap);
-            usedColumnIndices = new java.util.BitSet(cap);
-            setNextColumnIndex();
+            columnNumberManager = new ColumnNumberManager();
         }
         super.processNode(elementName, locator, attlist, pList);
     }
@@ -104,14 +97,14 @@ public class TableBody extends TableCellContainer {
      * {@inheritDoc}
      */
     protected void endOfNode() throws FOPException {
-        
+
         if (!inMarker()) {
             pendingSpans = null;
-            usedColumnIndices = null;
+            columnNumberManager = null;
         }
-        
+
         getFOEventHandler().endBody(this);
-        
+
         if (!(tableRowsFound || tableCellsFound)) {
             if (getUserAgent().validateStrictly()) {
                 missingChildElementError("marker* (table-row+|table-cell+)");
@@ -120,14 +113,14 @@ public class TableBody extends TableCellContainer {
                         + "Expected: marker* (table-row+|table-cell+)");
                 getParent().removeChild(this);
             }
-        }        
+        }
     }
 
     /**
      * {@inheritDoc} String, String)
      * XSL Content Model: marker* (table-row+|table-cell+)
      */
-    protected void validateChildNode(Locator loc, String nsURI, String localName) 
+    protected void validateChildNode(Locator loc, String nsURI, String localName)
         throws ValidationException {
         if (FO_URI.equals(nsURI)) {
             if (localName.equals("marker")) {
@@ -144,11 +137,11 @@ public class TableBody extends TableCellContainer {
             } else if (localName.equals("table-cell")) {
                 tableCellsFound = true;
                 if (tableRowsFound) {
-                    invalidChildError(loc, nsURI, localName, 
+                    invalidChildError(loc, nsURI, localName,
                             "Either fo:table-rows or fo:table-cells "
-                            + "may be children of an " 
+                            + "may be children of an "
                             + getName() + " but not both");
-                }  
+                }
             } else {
                 invalidChildError(loc, nsURI, localName);
             }
@@ -156,29 +149,35 @@ public class TableBody extends TableCellContainer {
             invalidChildError(loc, nsURI, localName);
         }
     }
-    
+
     /**
      * {@inheritDoc}
      */
     protected void addChildNode(FONode child) throws FOPException {
         if (!inMarker()) {
-            if (firstRow) {
-                switch (child.getNameId()) {
-                case FO_TABLE_ROW:
+            switch (child.getNameId()) {
+            case FO_TABLE_ROW:
+                if (rowsStarted) {
+                    columnNumberManager.prepareForNextRow(pendingSpans);
+                }
+                rowsStarted = true;
+                break;
+            case FO_TABLE_CELL:
+                rowsStarted = true;
+                TableCell cell = (TableCell) child;
+                addTableCellChild(cell, firstRow);
+                if (cell.endsRow()) {
                     firstRow = false;
-                    break;
-                case FO_TABLE_CELL:
-                    TableCell cell = (TableCell) child;
-                    addTableCellChild(cell);
-                    break;
-                default:
-                    //nop
+                    columnNumberManager.prepareForNextRow(pendingSpans);
                 }
+                break;
+            default:
+                //nop
             }
         }
         super.addChildNode(child);
     }
-    
+
     /**
      * @return the Common Border, Padding, and Background Properties.
      */
@@ -203,139 +202,19 @@ public class TableBody extends TableCellContainer {
      * @return true if the given table row is the first row of this body.
      */
     public boolean isFirst(TableRow obj) {
-        return (firstChild == null 
+        return (firstChild == null
                 || firstChild == obj);
     }
 
-    /**
-     * Initializes list of pending row-spans; used for correctly
-     * assigning initial value for column-number for the
-     * cells of following rows
-     * (note: not literally mentioned in the Rec, but it is assumed
-     *  that, if the first cell in a given row spans two rows, then
-     *  the first cell of the following row will have an initial
-     *  column-number of 2, since the first column is already 
-     *  occupied...)
-     */
-    protected void initPendingSpans(FONode child) {
-        if (child.getNameId() == FO_TABLE_ROW) {
-            pendingSpans = ((TableRow) child).pendingSpans;
-        } else if (pendingSpans == null) {
-            int colNumber = getTable().getNumberOfColumns();
-            if (colNumber == 0) {
-                pendingSpans = new java.util.ArrayList();
-            } else {
-                pendingSpans = new java.util.ArrayList(colNumber);
-                for (int i = colNumber; --i >= 0;) {
-                    pendingSpans.add(null);
-                }
+    void signalNewRow() {
+        if (rowsStarted) {
+            firstRow = false;
+            TableCell previousCell = (TableCell) getChildNodes().lastNode();
+            if (!previousCell.endsRow()) {
+                columnNumberManager.prepareForNextRow(pendingSpans);
             }
         }
-    }
-        
-    /**
-     * Returns the current column index of the TableBody
-     * 
-     * @return the next column number to use
-     */
-    protected int getCurrentColumnIndex() {
-        return columnIndex;
+        rowsStarted = true;
     }
 
-    /**
-     * Sets the current column index to a specific value
-     * (used by ColumnNumberPropertyMaker.make() in case the 
-     *  column-number was explicitly specified on the cell)
-     * 
-     * @param newIndex  the new column index
-     */
-    protected void setCurrentColumnIndex(int newIndex) {
-        columnIndex = newIndex;
-    }
-
-    /**
-     * Resets the current column index for the TableBody
-     *
-     */
-    protected void resetColumnIndex() {
-        columnIndex = 1;
-        for (int i = usedColumnIndices.length(); --i >= 0;) {
-            usedColumnIndices.clear(i);
-        }
-        
-        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);
-                } else {
-                    usedColumnIndices.set(i);
-                }
-            }
-        }
-        if (!firstRow) {
-            setNextColumnIndex();
-        }
-    }
-
-    /**
-     * Increases columnIndex to the next available value
-     *
-     */
-    protected void setNextColumnIndex() {
-        while (usedColumnIndices.get(columnIndex - 1)) {
-            //increment columnIndex
-            columnIndex++;
-        }
-        //if the table has explicit columns, and
-        //the index is not assigned to any
-        //column, increment further until the next
-        //index occupied by a column...
-        while (columnIndex <= getTable().getNumberOfColumns()
-                && !getTable().isColumnNumberUsed(columnIndex) ) {
-            columnIndex++;
-        }
-    }
-
-    /**
-     * Checks whether the previous cell had 'ends-row="true"'
-     * 
-     * @return true if:
-     *          a) there is a previous cell, which
-     *             had ends-row="true"
-     *          b) there is no previous cell (implicit 
-     *             start of row)
-     */
-    protected boolean previousCellEndedRow() {
-        if (firstChild != null) {
-            FONode prevNode = getChildNodes().lastNode();
-            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;
-     * 
-     * @param   colNr   the column-number to check
-     * @return true if column-number is already occupied
-     */
-    public boolean isColumnNumberUsed(int colNr) {
-        return usedColumnIndices.get(colNr - 1);
-    }
-    
-    /**
-     * {@inheritDoc} 
-     */
-    protected void flagColumnIndices(int start, int end) {
-        for (int i = start; i < end; i++) {
-            usedColumnIndices.set(i);
-        }
-        setNextColumnIndex();
-    }
 }
index 585d670d32b698a2a5916fcdb830760e1c859e90..04eb904d8847bd531f9535da809be43ebc41d4e1 100644 (file)
@@ -55,7 +55,7 @@ public class TableCell extends TableFObj {
     //     private KeepProperty keepWithNext;
     //     private KeepProperty keepWithPrevious;
     // End of property values
-  
+
     /** used for FO validation */
     private boolean blockItemFound = false;
 
@@ -75,12 +75,16 @@ public class TableCell extends TableFObj {
         blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
         displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
         emptyCells = pList.get(PR_EMPTY_CELLS).getEnum();
+        startsRow = pList.get(PR_STARTS_ROW).getEnum();
+        // For properly computing columnNumber
+        if (startsRow() && getParent().getNameId() != FO_TABLE_ROW) {
+            ((TableBody) getParent()).signalNewRow();
+        }
         endsRow = pList.get(PR_ENDS_ROW).getEnum();
         columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue();
         numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric().getValue();
         numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric().getValue();
-        startsRow = pList.get(PR_STARTS_ROW).getEnum();
-        width = pList.get(PR_WIDTH).getLength();        
+        width = pList.get(PR_WIDTH).getLength();
     }
 
     /**
@@ -105,7 +109,7 @@ public class TableCell extends TableFObj {
                         + "enclosed by a fo:block will be dropped/ignored.");
             }
         }
-        if ((startsRow() || endsRow()) 
+        if ((startsRow() || endsRow())
                 && getParent().getNameId() == FO_TABLE_ROW ) {
             log.warn("starts-row/ends-row for fo:table-cells "
                     + "non-applicable for children of an fo:table-row.");
@@ -117,7 +121,7 @@ public class TableCell extends TableFObj {
      * {@inheritDoc}
      * XSL Content Model: marker* (%block;)+
      */
-    protected void validateChildNode(Locator loc, String nsURI, String localName) 
+    protected void validateChildNode(Locator loc, String nsURI, String localName)
         throws ValidationException {
         if (FO_URI.equals(nsURI) && localName.equals("marker")) {
             if (blockItemFound) {
@@ -148,12 +152,12 @@ public class TableCell extends TableFObj {
     public int getColumnNumber() {
         return columnNumber;
     }
-    
+
     /** @return true if "empty-cells" is "show" */
     public boolean showEmptyCells() {
         return (this.emptyCells == EN_SHOW);
     }
-    
+
     /**
      * @return the "number-columns-spanned" property.
      */
@@ -167,7 +171,7 @@ public class TableCell extends TableFObj {
     public int getNumberRowsSpanned() {
         return Math.max(numberRowsSpanned, 1);
     }
-    
+
     /**
      * @return the "block-progression-dimension" property.
      */
@@ -179,24 +183,24 @@ public class TableCell extends TableFObj {
     public int getDisplayAlign() {
         return displayAlign;
     }
-    
+
     /**
      * @return the "width" property.
      */
     public Length getWidth() {
         return width;
     }
-    
+
     /** @return true if the cell starts a row. */
     public boolean startsRow() {
         return (startsRow == EN_TRUE);
     }
-    
+
     /** @return true if the cell ends a row. */
     public boolean endsRow() {
         return (endsRow == EN_TRUE);
     }
-    
+
     /** {@inheritDoc} */
     public String getLocalName() {
         return "table-cell";
@@ -208,4 +212,5 @@ public class TableCell extends TableFObj {
     public final int getNameId() {
         return FO_TABLE_CELL;
     }
+
 }
index 9fa602a190a217b3ba723f574d9f366e42dd81ad..228e3c80d5274de9d6f410422c0579b8e2721aae 100644 (file)
@@ -28,28 +28,75 @@ import org.apache.fop.fo.FONode;
 /**
  * A common class for fo:table-body and fo:table-row which both can contain fo:table-cell.
  */
-public abstract class TableCellContainer extends TableFObj {
+public abstract class TableCellContainer extends TableFObj implements ColumnNumberManagerHolder {
+
+    /**
+     * Used for determining initial values for column-numbers
+     * in case of row-spanning cells
+     * (for clarity)
+     *
+     */
+    static class PendingSpan {
+
+        /**
+         * member variable holding the number of rows left
+         */
+        protected int rowsLeft;
+
+        /**
+         * Constructor
+         * 
+         * @param rows  number of rows spanned
+         */
+        public PendingSpan(int rows) {
+            rowsLeft = rows;
+        }
+    }
+
+    protected List pendingSpans;
+
+    protected ColumnNumberManager columnNumberManager;
 
     public TableCellContainer(FONode parent) {
         super(parent);
     }
 
-    protected void addTableCellChild(TableCell cell) throws FOPException {
-        Table t = getTable();
-        int colNr = cell.getColumnNumber();
+    protected void addTableCellChild(TableCell cell, boolean firstRow) throws FOPException {
+        int colNumber = cell.getColumnNumber();
         int colSpan = cell.getNumberColumnsSpanned();
+        int rowSpan = cell.getNumberRowsSpanned();
+
+        if (firstRow) {
+            handleCellWidth(cell, colNumber, colSpan);
+            updatePendingSpansSize(cell, colNumber, colSpan);
+        }
+
+        /* if the current cell spans more than one row,
+         * update pending span list for the next row
+         */
+        if (rowSpan > 1) {
+            for (int i = 0; i < colSpan; i++) {
+                pendingSpans.set(colNumber - 1 + i, new PendingSpan(rowSpan));
+            }
+        }
+
+        columnNumberManager.signalUsedColumnNumbers(colNumber, colNumber + colSpan - 1);
+    }
+
+    private void handleCellWidth(TableCell cell, int colNumber, int colSpan) throws FOPException {
+        Table t = getTable();
         Length colWidth = null;
 
         if (cell.getWidth().getEnum() != EN_AUTO
                 && colSpan == 1) {
             colWidth = cell.getWidth();
         }
-        
-        for (int i = colNr; i < colNr + colSpan; ++i) {
+
+        for (int i = colNumber; i < colNumber + colSpan; ++i) {
             TableColumn col = t.getColumn(i - 1);
             if (col == null) {
-                t.addDefaultColumn(colWidth, 
-                        i == colN
+                t.addDefaultColumn(colWidth,
+                        i == colNumber
                             ? cell.getColumnNumber()
                             : 0);
             } else {
@@ -61,97 +108,15 @@ public abstract class TableCellContainer extends TableFObj {
         }
     }
 
-    protected void addChildNode(FONode child) throws FOPException {
-        if (!inMarker() 
-                && child.getNameId() == FO_TABLE_CELL) {
-            /* update current column index for the table-body/table-row */
-            updateColumnIndex((TableCell) child);
+    private void updatePendingSpansSize(TableCell cell, int colNumber, int colSpan) {
+        while (pendingSpans.size() < colNumber + colSpan - 1) {
+            pendingSpans.add(null);
         }
-        super.addChildNode(child);
     }
 
-
-    private void updateColumnIndex(TableCell cell) {
-        
-        int rowSpan = cell.getNumberRowsSpanned();
-        int colSpan = cell.getNumberColumnsSpanned();
-        int columnIndex = getCurrentColumnIndex();
-        int i;
-        
-        if (getNameId() == FO_TABLE_ROW) {
-            
-            TableRow row = (TableRow) this;
-            
-            for (i = colSpan; 
-                    --i >= 0 || row.pendingSpans.size() < cell.getColumnNumber();) {
-                row.pendingSpans.add(null);
-            }
-            
-            /* if the current cell spans more than one row,
-             * update pending span list for the next row
-             */
-            if (rowSpan > 1) {
-                for (i = colSpan; --i >= 0;) {
-                    row.pendingSpans.set(columnIndex - 1 + i, 
-                            new PendingSpan(rowSpan));
-                }
-            }
-        } else {
-            
-            TableBody body = (TableBody) this;
-            
-            /* if body.firstRow is still true, and :
-             * a) the cell starts a row,
-             * b) there was a previous cell 
-             * c) that previous cell didn't explicitly end the previous row
-             *  => set firstRow flag to false
-             */
-            if (body.firstRow && cell.startsRow()) {
-                if (!body.previousCellEndedRow()) {
-                    body.firstRow = false;
-                }
-            }
-            
-            /* pendingSpans not initialized for the first row...
-             */
-            if (body.firstRow) {
-                for (i = colSpan; 
-                        --i >= 0|| body.pendingSpans.size() < cell.getColumnNumber();) {
-                    body.pendingSpans.add(null);
-                }
-            }
-            
-            /* if the current cell spans more than one row,
-             * update pending span list for the next row
-             */
-            if (rowSpan > 1) {
-                for (i = colSpan; --i >= 0;) {
-                    body.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;
-        List cols = getTable().getColumns();
-        int tmpIndex = endIndex;
-        for (i = startIndex; i <= tmpIndex; ++i) {
-            if (i < cols.size() && cols.get(i) == null) {
-                endIndex++;
-            }
-        }
-        flagColumnIndices(startIndex, endIndex);
-        if (getNameId() != FO_TABLE_ROW && cell.endsRow()) {
-            ((TableBody) this).firstRow = false;
-            ((TableBody) this).resetColumnIndex();
-        }
+    /** {@inheritDoc} */
+    public ColumnNumberManager getColumnNumberManager() {
+        return columnNumberManager;
     }
 
 }
index 30fb494f07452ac2c6a1537266331e8eba684c5f..775b27ff3d8ec4032bc86611ea1c954d9f4c5c62 100644 (file)
@@ -45,17 +45,17 @@ public class TableColumn extends TableFObj {
     // Unused but valid items, commented out for performance:
     //     private int visibility;
     // End of property values
-    
+
     private boolean defaultColumn;
     private PropertyList pList = null;
-    
+
     /**
      * @param parent FONode that is the parent of this object
      */
     public TableColumn(FONode parent) {
         this(parent, false);
     }
-    
+
     /**
      * @param parent FONode that is the parent of this object
      * @param defaultColumn true if this table-column has been manually created as a default column
@@ -64,7 +64,7 @@ public class TableColumn extends TableFObj {
         super(parent);
         this.defaultColumn = defaultColumn;
     }
-    
+
 
     /**
      * {@inheritDoc}
@@ -78,7 +78,7 @@ public class TableColumn extends TableFObj {
         numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED)
                                     .getNumeric().getValue();
         super.bind(pList);
-        
+
         if (numberColumnsRepeated <= 0) {
             throw new PropertyException("number-columns-repeated must be 1 or bigger, "
                     + "but got " + numberColumnsRepeated);
@@ -87,10 +87,10 @@ public class TableColumn extends TableFObj {
             throw new PropertyException("number-columns-spanned must be 1 or bigger, "
                     + "but got " + numberColumnsSpanned);
         }
-        
-        /* check for unspecified width and replace with default of 
+
+        /* check for unspecified width and replace with default of
          * proportional-column-width(1), in case of fixed table-layout
-         * warn only for explicit columns 
+         * warn only for explicit columns
          */
         if (columnWidth.getEnum() == EN_AUTO) {
             if (!this.defaultColumn && !getTable().isAutoLayout()) {
@@ -99,7 +99,7 @@ public class TableColumn extends TableFObj {
             }
             columnWidth = new TableColLength(1.0, this);
         }
-        
+
         /* in case of explicit columns, from-table-column()
          * can be used on descendants of the table-cells, so
          * we need a reference to the column's property list
@@ -128,8 +128,8 @@ public class TableColumn extends TableFObj {
      * {@inheritDoc}
      * XSL Content Model: empty
      */
-    protected void validateChildNode(Locator loc, 
-                        String nsURI, String localName) 
+    protected void validateChildNode(Locator loc,
+                        String nsURI, String localName)
         throws ValidationException {
             invalidChildError(loc, nsURI, localName);
     }
@@ -162,7 +162,7 @@ public class TableColumn extends TableFObj {
     public int getColumnNumber() {
         return columnNumber;
     }
-    
+
     /**
      * Used for setting the column-number for an implicit column
      * @param columnNumber
@@ -175,12 +175,12 @@ public class TableColumn extends TableFObj {
     public int getNumberColumnsRepeated() {
         return numberColumnsRepeated;
     }
-    
+
     /** @return value for number-columns-spanned. */
     public int getNumberColumnsSpanned() {
         return numberColumnsSpanned;
     }
-    
+
     /** {@inheritDoc} */
     public String getLocalName() {
         return "table-column";
@@ -190,11 +190,11 @@ public class TableColumn extends TableFObj {
     public int getNameId() {
         return FO_TABLE_COLUMN;
     }
-    
+
     /**
-     * Indicates whether this table-column has been created as 
-     * default column for this table in case no table-columns 
-     * have been defined. 
+     * Indicates whether this table-column has been created as
+     * default column for this table in case no table-columns
+     * have been defined.
      * Note that this only used to provide better
      * user feedback (see ColumnSetup).
      * @return true if this table-column has been created as default column
@@ -202,7 +202,7 @@ public class TableColumn extends TableFObj {
     public boolean isDefaultColumn() {
         return defaultColumn;
     }
-    
+
     /** {@inheritDoc} */
     public String toString() {
         StringBuffer sb = new StringBuffer("fo:table-column");
@@ -218,9 +218,9 @@ public class TableColumn extends TableFObj {
         sb.append(" column-width=").append(getColumnWidth());
         return sb.toString();
     }
-    
+
     /**
-     * Retrieve a property value through its Id; used by 
+     * Retrieve a property value through its Id; used by
      * from-table-column() function
      * 
      * @param propId    the id for the property to retrieve
@@ -230,12 +230,13 @@ public class TableColumn extends TableFObj {
     public Property getProperty(int propId) throws PropertyException {
         return this.pList.get(propId);
     }
-    
+
     /**
-     * Clear the reference to the PropertyList (retained for 
+     * Clear the reference to the PropertyList (retained for
      * from-table-column())
      */
     protected void releasePropertyList() {
         this.pList = null;
-    }    
+    }
+
 }
index bd5642febc71f0be52793d70093af85413b74a1b..e00559d3eb691e67ad360b53d68693b2401c64ae 100644 (file)
@@ -40,30 +40,7 @@ public abstract class TableFObj extends FObj {
     private Numeric borderBeforePrecedence;
     private Numeric borderEndPrecedence;
     private Numeric borderStartPrecedence;
-    
-    /**
-     * Used for determining initial values for column-numbers
-     * in case of row-spanning cells
-     * (for clarity)
-     *
-     */
-    protected static class PendingSpan {
-        
-        /**
-         * member variable holding the number of rows left
-         */
-        protected int rowsLeft;
-        
-        /**
-         * Constructor
-         * 
-         * @param rows  number of rows spanned
-         */
-        public PendingSpan(int rows) {
-            rowsLeft = rows;
-        }        
-    }
-    
+
     /**
      * Main constructor
      * 
@@ -113,73 +90,23 @@ public abstract class TableFObj extends FObj {
     }
 
     /**
-     * Returns the current column index of the given TableFObj
-     * (overridden for Table, TableBody, TableRow)
-     * 
-     * @return the next column number to use
-     */
-    protected int getCurrentColumnIndex() {
-        return 0;
-    }
-    
-    /**
-     * Sets the current column index of the given TableFObj
-     * used when a value for column-number is explicitly
-     * specified on the child FO (TableCell or TableColumn)
-     * (overridden for Table, TableBody, TableRow)
-     * 
-     * @param   newIndex    new value for column index
-     */
-    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
-     */
-    public boolean isColumnNumberUsed(int colNr) {
-        return false;
-    }
-    
-    /**
-     * Convenience method to returns a reference 
+     * Convenience method to returns a reference
      * to the base Table instance
      * 
      * @return  the base table instance
      * 
      */
     public Table getTable() {
-        if (this.getNameId() == FO_TABLE) {
-            //node is a Table
-            //=> return itself
-            return (Table) this;
-        } else {
-            //any other Table-node
-            //=> recursive call to parent.getTable()
-            return ((TableFObj) parent).getTable();
-        }
+        // Will be overridden in Table; for any other Table-node, recursive call to
+        // parent.getTable()
+        return ((TableFObj) parent).getTable();
     }
-    
+
     /**
      * @return the Common Border, Padding, and Background Properties.
      */
     public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground();
-    
-    /**
-     * Flags column indices from <code>start</code> to <code>end</code>,
-     * and updates the current column index.
-     * Overridden for Table, TableBody, TableRow
-     * @param start start index
-     * @param end   end index
-     */
-    protected void flagColumnIndices(int start, int end) {
-        //nop
-    }
-    
+
     /**
      * PropertyMaker subclass for the column-number property
      *
@@ -188,7 +115,7 @@ public abstract class TableFObj extends FObj {
 
         /**
          * Constructor
-         * @param propId    the id of the property for which the maker should 
+         * @param propId    the id of the property for which the maker should
          *                  be created
          */
         public ColumnNumberPropertyMaker(int propId) {
@@ -198,47 +125,36 @@ public abstract class TableFObj extends FObj {
         /**
          * {@inheritDoc}
          */
-        public Property make(PropertyList propertyList) 
+        public Property make(PropertyList propertyList)
                 throws PropertyException {
             FObj fo = propertyList.getFObj();
 
-            if (fo.getNameId() == Constants.FO_TABLE_CELL
-                    || fo.getNameId() == Constants.FO_TABLE_COLUMN) {
-                if (fo.getNameId() == Constants.FO_TABLE_CELL
-                        && fo.getParent().getNameId() != Constants.FO_TABLE_ROW
-                        && (propertyList.get(Constants.PR_STARTS_ROW).getEnum() 
-                                == Constants.EN_TRUE)) {
-                    TableBody parent = (TableBody) fo.getParent();
-                    if (!parent.previousCellEndedRow()) {
-                        parent.resetColumnIndex();
-                    }
-                }
-            }
-            return NumberProperty.getInstance(
-                    ((TableFObj) fo.getParent()).getCurrentColumnIndex());
+            return NumberProperty.getInstance(((ColumnNumberManagerHolder) fo.getParent())
+                    .getColumnNumberManager().getCurrentColumnNumber());
         }
-        
-        
+
+
         /**
-         * Check the value of the column-number property. 
-         * Return the parent's column index (initial value) in case 
+         * Check the value of the column-number property.
+         * Return the parent's column index (initial value) in case
          * of a negative or zero value
          * 
          * @see org.apache.fop.fo.properties.PropertyMaker#make(PropertyList, String, FObj)
          */
-        public Property make(PropertyList propertyList, String value, FObj fo) 
+        public Property make(PropertyList propertyList, String value, FObj fo)
                     throws PropertyException {
             Property p = super.make(propertyList, value, fo);
-            
-            TableFObj parent = (TableFObj) propertyList.getParentFObj();
-            
+
+            ColumnNumberManagerHolder parent
+                    = (ColumnNumberManagerHolder) propertyList.getParentFObj();
+            ColumnNumberManager columnIndexManager =  parent.getColumnNumberManager();
             int columnIndex = p.getNumeric().getValue();
             if (columnIndex <= 0) {
                 log.warn("Specified negative or zero value for "
                         + "column-number on " + fo.getName() + ": "
-                        + columnIndex + " forced to " 
-                        + parent.getCurrentColumnIndex());
-                return NumberProperty.getInstance(parent.getCurrentColumnIndex());
+                        + columnIndex + " forced to "
+                        + columnIndexManager.getCurrentColumnNumber());
+                return NumberProperty.getInstance(columnIndexManager.getCurrentColumnNumber());
             } else {
                 double tmpIndex = p.getNumeric().getNumericValue();
                 if (tmpIndex - columnIndex > 0.0) {
@@ -248,15 +164,15 @@ public abstract class TableFObj extends FObj {
                     p = NumberProperty.getInstance(columnIndex);
                 }
             }
-            
-            parent.setCurrentColumnIndex(columnIndex);
-            
+
+            columnIndexManager.setCurrentColumnIndex(columnIndex);
+
             int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED)
                                 .getNumeric().getValue();
             int i = -1;
             while (++i < colSpan) {
-                if (parent.isColumnNumberUsed(columnIndex + i)) {
-                    /* if column-number is already in use by another 
+                if (columnIndexManager.isColumnNumberUsed(columnIndex + i)) {
+                    /* if column-number is already in use by another
                      * cell/column => error!
                      */
                     StringBuffer errorMessage = new StringBuffer();
@@ -271,7 +187,7 @@ public abstract class TableFObj extends FObj {
                     throw new PropertyException(errorMessage.toString());
                 }
             }
-            
+
             return p;
         }
     }
index b6feeabba12669bd1b18327312f17a2d10110e03..bbc8081a66aa2a02e52e65c2a6d7cb8f95774acd 100644 (file)
 
 package org.apache.fop.fo.flow;
 
-import java.util.BitSet;
-import java.util.List;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.Locator;
-
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.FONode;
@@ -33,6 +27,8 @@ import org.apache.fop.fo.ValidationException;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.fo.properties.LengthRangeProperty;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
 
 /**
  * Class modelling the fo:table-row object.
@@ -53,10 +49,6 @@ public class TableRow extends TableCellContainer {
     //     private CommonRelativePosition commonRelativePosition;
     //     private int visibility;
     // End of property values
-    
-    protected List pendingSpans;
-    protected BitSet usedColumnIndices;
-    private int columnIndex = 1;
 
     /**
      * @param parent FONode that is the parent of this object
@@ -67,7 +59,7 @@ public class TableRow extends TableCellContainer {
 
     /** {@inheritDoc} */
     public void bind(PropertyList pList) throws FOPException {
-        blockProgressionDimension 
+        blockProgressionDimension
             = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
@@ -80,16 +72,12 @@ public class TableRow extends TableCellContainer {
     }
 
     /** {@inheritDoc} */
-    public void processNode(String elementName, Locator locator, 
+    public void processNode(String elementName, Locator locator,
             Attributes attlist, PropertyList pList) throws FOPException {
         if (!inMarker()) {
             TableBody body = (TableBody) parent;
-            body.resetColumnIndex();
             pendingSpans = body.pendingSpans;
-            usedColumnIndices = body.usedColumnIndices;
-            while (usedColumnIndices.get(columnIndex - 1)) {
-                columnIndex++;
-            }
+            columnNumberManager = body.columnNumberManager;
         }
         super.processNode(elementName, locator, attlist, pList);
     }
@@ -99,11 +87,9 @@ public class TableRow extends TableCellContainer {
      */
     protected void addChildNode(FONode child) throws FOPException {
         if (!inMarker()) {
+            TableCell cell = (TableCell) child;
             TableBody body = (TableBody) getParent();
-            if (body.isFirst(this)) {
-                TableCell cell = (TableCell) child;
-                addTableCellChild(cell);
-            }
+            addTableCellChild(cell, body.isFirst(this));
         }
         super.addChildNode(child);
     }
@@ -125,7 +111,7 @@ public class TableRow extends TableCellContainer {
         }
         if (!inMarker()) {
             pendingSpans = null;
-            usedColumnIndices = null;
+            columnNumberManager = null;
         }
         getFOEventHandler().endRow(this);
     }
@@ -134,14 +120,14 @@ public class TableRow extends TableCellContainer {
      * {@inheritDoc} String, String)
      * XSL Content Model: (table-cell+)
      */
-    protected void validateChildNode(Locator loc, String nsURI, 
-                                     String localName) 
+    protected void validateChildNode(Locator loc, String nsURI,
+                                     String localName)
         throws ValidationException {
         if (!(FO_URI.equals(nsURI) && localName.equals("table-cell"))) {
             invalidChildError(loc, nsURI, localName);
         }
-    }    
-    
+    }
+
     /** @return the "break-after" property. */
     public int getBreakAfter() {
         return breakAfter;
@@ -168,7 +154,7 @@ public class TableRow extends TableCellContainer {
     }
 
     /**
-     * Convenience method to check if a keep-together 
+     * Convenience method to check if a keep-together
      * constraint is specified.
      * @return true if keep-together is active.
      */
@@ -176,9 +162,9 @@ public class TableRow extends TableCellContainer {
         return !getKeepTogether().getWithinPage().isAuto()
                 || !getKeepTogether().getWithinColumn().isAuto();
     }
-    
+
     /**
-     * Convenience method to check if a keep-with-next 
+     * Convenience method to check if a keep-with-next
      * constraint is specified.
      * @return true if keep-with-next is active.
      */
@@ -186,9 +172,9 @@ public class TableRow extends TableCellContainer {
         return !getKeepWithNext().getWithinPage().isAuto()
                 || !getKeepWithNext().getWithinColumn().isAuto();
     }
-    
+
     /**
-     * Convenience method to check if a keep-with-previous 
+     * Convenience method to check if a keep-with-previous
      * constraint is specified.
      * @return true if keep-with-previous is active.
      */
@@ -196,7 +182,7 @@ public class TableRow extends TableCellContainer {
         return !getKeepWithPrevious().getWithinPage().isAuto()
                 || !getKeepWithPrevious().getWithinColumn().isAuto();
     }
-    
+
     /**
      * @return the "block-progression-dimension" property.
      */
@@ -217,7 +203,7 @@ public class TableRow extends TableCellContainer {
     public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
         return commonBorderPaddingBackground;
     }
-    
+
     /** {@inheritDoc} */
     public String getLocalName() {
         return "table-row";
@@ -227,48 +213,4 @@ public class TableRow extends TableCellContainer {
     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 ColumnNumberPropertyMaker.make())
-     * 
-     * @param newIndex  new value for column index
-     */
-    public void setCurrentColumnIndex(int newIndex) {
-        columnIndex = newIndex;
-    }
-
-    /**
-     * Checks whether a given column-number is already in use
-     * for the current row (used by TableCell.bind());
-     * 
-     * @param colNr the column-number to check
-     * @return true if column-number is already occupied
-     */
-    public boolean isColumnNumberUsed(int colNr) {
-        return usedColumnIndices.get(colNr - 1);
-    }
-    
-    /**
-     * {@inheritDoc} 
-     */
-    protected void flagColumnIndices(int start, int end) {
-        for (int i = start; i < end; i++) {
-            usedColumnIndices.set(i);
-        }
-        // update columnIndex for the next cell
-        while (usedColumnIndices.get(columnIndex - 1)) {
-            columnIndex++;
-        }
-    }    
 }