blob: a5853cd9187b40699e2477e4ae07bfd01944c6f2 [file] [log] [blame]
/*
* 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.table;
import java.util.Iterator;
import java.util.List;
import org.apache.fop.fo.Constants;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.table.TableRowIterator;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.BreakUtil;
/**
* This class represents an effective row in a table and holds a list of grid units occupying
* the row as well as some additional values.
*/
public class EffRow {
/** Indicates that the row is the first in a table-body */
public static final int FIRST_IN_PART = GridUnit.FIRST_IN_PART;
/** Indicates that the row is the last in a table-body */
public static final int LAST_IN_PART = GridUnit.LAST_IN_PART;
private List gridUnits = new java.util.ArrayList();
private int index;
/** One of HEADER, FOOTER, BODY */
private int bodyType;
private MinOptMax height;
private MinOptMax explicitHeight;
/**
* Creates a new effective row instance.
* @param index index of the row
* @param bodyType type of body (one of HEADER, FOOTER, BODY as found on TableRowIterator)
* @param gridUnits the grid units this row is made of
*/
public EffRow(int index, int bodyType, List gridUnits) {
this.index = index;
this.bodyType = bodyType;
this.gridUnits = gridUnits;
// TODO this is ugly, but we may eventually be able to do without that index
for (Iterator guIter = gridUnits.iterator(); guIter.hasNext();) {
Object gu = guIter.next();
if (gu instanceof PrimaryGridUnit) {
((PrimaryGridUnit) gu).setRowIndex(index);
}
}
}
/** @return the index of the EffRow in the sequence of rows */
public int getIndex() {
return this.index;
}
/**
* @return an indicator what type of body this EffRow is in (one of HEADER, FOOTER, BODY
* as found on TableRowIterator)
*/
public int getBodyType() {
return this.bodyType;
}
/** @return the table-row FO for this EffRow, or null if there is no table-row. */
public TableRow getTableRow() {
return getGridUnit(0).getRow();
}
/**
* Returns the calculated height for this EffRow, including the cells'
* bpds/paddings/borders, and the table's border-separation.
*
* @return the row's height
*/
public MinOptMax getHeight() {
return this.height;
}
/**
* Sets the calculated height for this EffRow, including everything (cells' bpds,
* paddings, borders, and border-separation).
*
* @param mom the calculated height
*/
public void setHeight(MinOptMax mom) {
this.height = mom;
}
/** @return the explicit height of the EffRow (as specified through properties) */
public MinOptMax getExplicitHeight() {
return this.explicitHeight;
}
/**
* Sets the height for this row that resulted from the explicit height properties specified
* by the user.
* @param mom the height
*/
public void setExplicitHeight(MinOptMax mom) {
this.explicitHeight = mom;
}
/** @return the list of GridUnits for this EffRow */
public List getGridUnits() {
return gridUnits;
}
/**
* Returns the grid unit at a given position.
* @param column index of the grid unit in the row (zero based)
* @return the requested grid unit.
*/
public GridUnit getGridUnit(int column) {
return (GridUnit)gridUnits.get(column);
}
/**
* Returns the grid unit at a given position. In contrast to getGridUnit() this
* method returns null if there's no grid unit at the given position. The number of
* grid units for row x can be smaller than the number of grid units for row x-1.
* @param column index of the grid unit in the row (zero based)
* @return the requested grid unit or null if there's no grid unit at this position.
*/
public GridUnit safelyGetGridUnit(int column) {
if (column < gridUnits.size()) {
return (GridUnit)gridUnits.get(column);
} else {
return null;
}
}
/**
* Returns a flag for this effective row. Only a subset of the flags on GridUnit is supported.
* The flag is determined by inspecting flags on the EffRow's GridUnits.
* @param which the requested flag (one of {@link EffRow#FIRST_IN_PART} or {@link
* EffRow#LAST_IN_PART})
* @return true if the flag is set
*/
public boolean getFlag(int which) {
if (which == FIRST_IN_PART) {
return getGridUnit(0).getFlag(GridUnit.FIRST_IN_PART);
} else if (which == LAST_IN_PART) {
return getGridUnit(0).getFlag(GridUnit.LAST_IN_PART);
} else {
throw new IllegalArgumentException("Illegal flag queried: " + which);
}
}
/**
* Returns the strength of the keep constraint if the enclosing (if any) fo:table-row element
* of this row, or if any of the cells starting on this row, have keep-with-previous set.
*
* @return the strength of the keep-with-previous constraint
*/
public Keep getKeepWithPrevious() {
Keep keep = Keep.KEEP_AUTO;
TableRow row = getTableRow();
if (row != null) {
keep = Keep.getKeep(row.getKeepWithPrevious());
}
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
GridUnit gu = (GridUnit) iter.next();
if (gu.isPrimary()) {
keep = keep.compare(gu.getPrimary().getKeepWithPrevious());
}
}
return keep;
}
/**
* Returns the strength of the keep constraint if the enclosing (if any) fo:table-row element
* of this row, or if any of the cells ending on this row, have keep-with-next set.
*
* @return the strength of the keep-with-next constraint
*/
public Keep getKeepWithNext() {
Keep keep = Keep.KEEP_AUTO;
TableRow row = getTableRow();
if (row != null) {
keep = Keep.getKeep(row.getKeepWithNext());
}
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
GridUnit gu = (GridUnit) iter.next();
if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
keep = keep.compare(gu.getPrimary().getKeepWithNext());
}
}
return keep;
}
/**
* Returns the keep-together strength for this element. Note: The keep strength returned does
* not take the parent table's keeps into account!
* @return the keep-together strength
*/
public Keep getKeepTogether() {
TableRow row = getTableRow();
Keep keep = Keep.KEEP_AUTO;
if (row != null) {
keep = Keep.getKeep(row.getKeepTogether());
}
return keep;
}
/**
* Returns the break class for this row. This is a combination of break-before set on
* the first children of any cells starting on this row.
* <p><strong>Note:</strong> this method doesn't take into account break-before set on
* the enclosing fo:table-row element, if any, as it must be ignored if the row
* belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.2).
* <p><strong>Note:</strong> this works only after getNextKuthElements on the
* corresponding TableCellLM have been called!</p>
*
* @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
* Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
*/
public int getBreakBefore() {
int breakBefore = Constants.EN_AUTO;
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
GridUnit gu = (GridUnit) iter.next();
if (gu.isPrimary()) {
breakBefore = BreakUtil.compareBreakClasses(breakBefore,
gu.getPrimary().getBreakBefore());
}
}
return breakBefore;
}
/**
* Returns the break class for this row. This is a combination of break-after set on
* the last children of any cells ending on this row.
* <p><strong>Note:</strong> this method doesn't take into account break-after set on
* the enclosing fo:table-row element, if any, as it must be ignored if the row
* belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.1).
* <p><strong>Note:</strong> this works only after getNextKuthElements on the
* corresponding TableCellLM have been called!</p>
*
* @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
* Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
*/
public int getBreakAfter() {
int breakAfter = Constants.EN_AUTO;
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
GridUnit gu = (GridUnit) iter.next();
if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
breakAfter = BreakUtil.compareBreakClasses(breakAfter,
gu.getPrimary().getBreakAfter());
}
}
return breakAfter;
}
/** {@inheritDoc} */
public String toString() {
StringBuffer sb = new StringBuffer("EffRow {");
sb.append(index);
if (getBodyType() == TableRowIterator.BODY) {
sb.append(" in body");
} else if (getBodyType() == TableRowIterator.HEADER) {
sb.append(" in header");
} else {
sb.append(" in footer");
}
sb.append(", ").append(height);
sb.append(", ").append(explicitHeight);
sb.append(", ").append(gridUnits.size()).append(" gu");
sb.append("}");
return sb.toString();
}
}