Package org.apache.fop.fo.flow

Source Code of org.apache.fop.fo.flow.TableBody

/*
* 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: TableBody.java 488960 2006-12-20 08:34:28Z spepping $ */

package org.apache.fop.fo.flow;

// Java
import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

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.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.StaticPropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.flow.TableFObj.PendingSpan;
import org.apache.fop.fo.properties.CommonAccessibility;
import org.apache.fop.fo.properties.CommonAural;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonRelativePosition;

/**
* Class modelling the fo:table-body object.
*/
public class TableBody extends TableFObj {
    // The value of properties relevant for fo:table-body.
    private CommonBorderPaddingBackground commonBorderPaddingBackground;
    // Unused but valid items, commented out for performance:
    //     private CommonAccessibility commonAccessibility;
    //     private CommonAural commonAural;
    //     private CommonRelativePosition commonRelativePosition;
    //    private int visibility;
    // End of property values
   
    private PropertyList savedPropertyList;

    /**
     * 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;
   
    /**
     * @param parent FONode that is the parent of the object
     */
    public TableBody(FONode parent) {
        super(parent);
    }

    /**
     * @see FObj#bind(PropertyList)
     */
    public void bind(PropertyList pList) throws FOPException {
        commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
        super.bind(pList);
        //Used by convertCellsToRows()
        savedPropertyList = pList;
    }
   
    /**
     * @see org.apache.fop.fo.FONode#processNode(String, Locator, Attributes, PropertyList)
     */
    public void processNode(String elementName, Locator locator,
                            Attributes attlist, PropertyList pList)
                    throws FOPException {
        if (!inMarker()) {
            if (getTable().columns != null) {
                int cap = getTable().columns.size();
                pendingSpans = new java.util.ArrayList(cap);
                usedColumnIndices = new java.util.BitSet(cap);
            } else {
                pendingSpans = new java.util.ArrayList();
                usedColumnIndices = new java.util.BitSet();
            }
            setNextColumnIndex();
        }
        super.processNode(elementName, locator, attlist, pList);
    }

    /**
     * @see org.apache.fop.fo.FONode#startOfNode
     */
    protected void startOfNode() throws FOPException {
        getFOEventHandler().startBody(this);
    }

    /**
     * @see org.apache.fop.fo.FONode#endOfNode
     */
    protected void endOfNode() throws FOPException {
       
        if (!inMarker()) {
            // clean up
            savedPropertyList = null;
            pendingSpans = null;
            usedColumnIndices = null;
        }
       
        getFOEventHandler().endBody(this);
       
        if (!(tableRowsFound || tableCellsFound)) {
            if (getUserAgent().validateStrictly()) {
                missingChildElementError("marker* (table-row+|table-cell+)");
            } else {
                getLogger().error("fo:table-body must not be empty. "
                        + "Expected: marker* (table-row+|table-cell+)");
                getParent().removeChild(this);
            }
        }
       
        /*
        if (tableCellsFound) {
            convertCellsToRows();
        }
        */
    }

    /**
     * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
     * XSL Content Model: marker* (table-row+|table-cell+)
     */
    protected void validateChildNode(Locator loc, String nsURI, String localName)
        throws ValidationException {
        if (FO_URI.equals(nsURI)) {
            if (localName.equals("marker")) {
                if (tableRowsFound || tableCellsFound) {
                   nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)");
                }
            } else if (localName.equals("table-row")) {
                tableRowsFound = true;
                if (tableCellsFound) {
                    invalidChildError(loc, nsURI, localName, "Either fo:table-rows" +
                      " or fo:table-cells may be children of an " + getName() +
                      " but not both");
                }
            } else if (localName.equals("table-cell")) {
                tableCellsFound = true;
                if (tableRowsFound) {
                    invalidChildError(loc, nsURI, localName,
                            "Either fo:table-rows or fo:table-cells "
                            + "may be children of an "
                            + getName() + " but not both");
               
            } else {
                invalidChildError(loc, nsURI, localName);
            }
        } else {
            invalidChildError(loc, nsURI, localName);
        }
    }
   
    /**
     * @see org.apache.fop.fo.FONode#addChildNode(FONode)
     */
    protected void addChildNode(FONode child) throws FOPException {
        if (!inMarker()) {
            if (firstRow) {
                Table t = getTable();
               
                if (t.columns == null) {
                    t.columns = new java.util.ArrayList();
                }
               
                switch (child.getNameId()) {
                case FO_TABLE_ROW:
                    firstRow = false;
                    break;
                case FO_TABLE_CELL:
                    TableCell cell = (TableCell) child;
                    int colNr = cell.getColumnNumber();
                    int colSpan = cell.getNumberColumnsSpanned();
                    Length colWidth = null;

                    if (cell.getWidth().getEnum() != EN_AUTO
                            && colSpan == 1) {
                        colWidth = cell.getWidth();
                    }
                   
                    for (int i = colNr; i < colNr + colSpan; ++i) {
                        if (t.columns.size() < i
                                || t.columns.get(i - 1) == null) {
                            t.addDefaultColumn(colWidth,
                                    i == colNr
                                        ? cell.getColumnNumber()
                                        : 0);
                        } else {
                            TableColumn col =
                                (TableColumn) t.columns.get(i - 1);
                            if (!col.isDefaultColumn()
                                    && colWidth != null) {
                                col.setColumnWidth(colWidth);
                            }
                        }
                    }
                    break;
                default:
                    //nop
                }
            }
        }
        super.addChildNode(child);
    }
   
    /**
     * If table-cells are used as direct children of a table-body|header|footer
     * they are replaced in this method by proper table-rows.
     * @throws FOPException if there's a problem binding the TableRow's
     *         properties.
     */
    // TODO: This is currently unused. Why is it here?
    private void convertCellsToRows() throws FOPException {
        //getLogger().debug("Converting cells to rows...");
        List cells = new java.util.ArrayList(childNodes);
        childNodes.clear();
        Iterator i = cells.iterator();
        TableRow row = null;
        while (i.hasNext()) {
            TableCell cell = (TableCell) i.next();
            if (cell.startsRow() && (row != null)) {
                childNodes.add(row);
                row = null;
            }
            if (row == null) {
                row = new TableRow(this);
                PropertyList pList = new StaticPropertyList(row,
                        savedPropertyList);
                pList.setWritingMode();
                row.bind(pList);
            }
            row.addReplacedCell(cell);
            if (cell.endsRow()) {
                childNodes.add(row);
                row = null;
            }
        }
        if (row != null) {
            childNodes.add(row);
        }
    }
   
    /**
     * @return the Common Border, Padding, and Background Properties.
     */
    public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
        return commonBorderPaddingBackground;
    }

    /** @see org.apache.fop.fo.FONode#getLocalName() */
    public String getLocalName() {
        return "table-body";
    }

    /**
     * @see org.apache.fop.fo.FObj#getNameId()
     */
    public int getNameId() {
        return FO_TABLE_BODY;
    }

    /**
     * @param obj table row in question
     * @return true if the given table row is the first row of this body.
     */
    public boolean isFirst(TableRow obj) {
        return (childNodes == null
                || (!childNodes.isEmpty()
                    && childNodes.get(0) == obj));
    }

    /**
     * @param obj table row in question
     * @return true if the given table row is the first row of this body.
     */
    public boolean isLast(TableRow obj) {
        return (childNodes == null
                || (childNodes.size() > 0
                    && childNodes.get(childNodes.size() - 1) == 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) {
            if (getTable().columns != null) {
                List tableCols = getTable().columns;
                pendingSpans = new java.util.ArrayList(tableCols.size());
                for (int i = tableCols.size(); --i >= 0;) {
                    pendingSpans.add(null);
                }
            } else {
                pendingSpans = new java.util.ArrayList();
            }
        }
    }
       
    /**
     * Returns the current column index of the TableBody
     *
     * @return the next column number to use
     */
    protected int getCurrentColumnIndex() {
        return columnIndex;
    }

    /**
     * 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...
        if (getTable().columns != null) {
            while (columnIndex <= getTable().columns.size()
                    && !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 (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;
     *
     * @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);
    }
   
    /**
     * @see org.apache.fop.fo.flow.TableFObj#flagColumnIndices(int, int)
     */
    protected void flagColumnIndices(int start, int end) {
        for (int i = start; i < end; i++) {
            usedColumnIndices.set(i);
        }
        setNextColumnIndex();
    }
}
TOP

Related Classes of org.apache.fop.fo.flow.TableBody

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.