blob: 5b1d85d2b7f8cd9810e4861b0fb72fc5101565be [file] [log] [blame]
/*
* 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.layoutmgr.table;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.Table;
import org.apache.fop.fo.flow.TableBody;
import org.apache.fop.fo.flow.TableCell;
import org.apache.fop.fo.flow.TableColumn;
import org.apache.fop.fo.flow.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
/**
* This class represents one grid unit inside a table.
*/
public class GridUnit {
/** Indicates that the grid unit is in the first column. */
public static final int IN_FIRST_COLUMN = 0;
/** Indicates that the grid unit is in the last column. */
public static final int IN_LAST_COLUMN = 1;
/** Indicates that the grid unit is in the first row (context: table). */
public static final int FIRST_IN_TABLE = 2;
/** Indicates that the grid unit is in the first row (context: body). */
public static final int FIRST_IN_BODY = 3;
/** Indicates that the grid unit is in the last row (context: body). */
public static final int LAST_IN_BODY = 4;
/** Indicates that the grid unit is in the last row (context: table). */
public static final int LAST_IN_TABLE = 5;
/** Primary grid unit */
private PrimaryGridUnit primary;
/** Table cell which occupies this grid unit */
private TableCell cell;
/** Table row which occupied this grid unit (may be null) */
private TableRow row;
/** Table column that this grid unit belongs to */
private TableColumn column;
/** start index of grid unit within row in column direction */
private int startCol;
/** index of grid unit within cell in column direction */
private int colSpanIndex;
/** index of grid unit within cell in row direction */
private int rowSpanIndex;
/** effective borders for a cell slot */
private CommonBorderPaddingBackground effBorders;
/** flags for the grid unit */
private byte flags = 0;
public GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
this(null, cell, column, startCol, colSpanIndex);
}
public GridUnit(PrimaryGridUnit primary, TableColumn column, int startCol, int colSpanIndex) {
this(primary, primary.getCell(), column, startCol, colSpanIndex);
}
protected GridUnit(PrimaryGridUnit primary, TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
this.primary = primary;
this.cell = cell;
this.column = column;
this.startCol = startCol;
this.colSpanIndex = colSpanIndex;
}
public TableCell getCell() {
return this.cell;
}
public TableColumn getColumn() {
return this.column;
}
public TableRow getRow() {
if (this.row != null) {
return this.row;
} else if (getCell().getParent() instanceof TableRow) {
return (TableRow)getCell().getParent();
} else {
return null;
}
}
/**
* Sets the table-row FO, if applicable.
* @param rowFO the table-row FO
*/
public void setRow(TableRow rowFO) {
this.row = rowFO;
}
public TableBody getBody() {
FONode node = getCell();
while (node != null && !(node instanceof TableBody)) {
node = node.getParent();
}
return (TableBody)node;
}
public Table getTable() {
FONode node = getBody();
while (node != null && !(node instanceof Table)) {
node = node.getParent();
}
return (Table)node;
}
/**
* @return the primary grid unit if this is a spanned grid unit
*/
public PrimaryGridUnit getPrimary() {
return (isPrimary() ? (PrimaryGridUnit)this : this.primary);
}
public boolean isPrimary() {
return false;
}
public boolean isEmpty() {
return this.cell == null;
}
public int getStartCol() {
return this.startCol;
}
/** @return true if the grid unit is the last in column spanning direction */
public boolean isLastGridUnitColSpan() {
if (cell != null) {
return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
} else {
return true;
}
}
/** @return true if the grid unit is the last in column spanning direction */
public boolean isLastGridUnitRowSpan() {
if (cell != null) {
return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
} else {
return true;
}
}
/**
* @return the index of the grid unit inside a cell in row direction
*/
public int getRowSpanIndex() {
return this.rowSpanIndex;
}
/**
* @return the index of the grid unit inside a cell in column direction
*/
public int getColSpanIndex() {
return this.colSpanIndex;
}
/**
* Returns a BorderInfo instance for a side of the currently applicable cell before border
* resolution (i.e. the value from the FO). A return value of null indicates an empty cell.
* See CollapsingBorderModel(EyeCatching) where this method is used.
* @param side for which side to return the BorderInfo
* @return the requested BorderInfo instance or null if the grid unit is an empty cell
*/
public BorderInfo getOriginalBorderInfoForCell(int side) {
if (cell != null) {
return cell.getCommonBorderPaddingBackground().getBorderInfo(side);
} else {
return null;
}
}
/**
* @return the resolved normal borders for this grid unit
*/
public CommonBorderPaddingBackground getBorders() {
return this.effBorders;
}
/**
* @return true if the grid unit has any borders.
*/
public boolean hasBorders() {
return (getBorders() != null) && getBorders().hasBorder();
}
/**
* Assigns the borders from the given cell to this cell info. Used in
* case of separate border model.
*/
public void assignBorderForSeparateBorderModel() {
if (cell != null) {
this.effBorders = cell.getCommonBorderPaddingBackground();
}
}
/**
* Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
* @param other neighbouring grid unit if any
* @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
*/
public void resolveBorder(GridUnit other, int side) {
resolveBorder(other, side, 0);
}
/**
* Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
* @param other neighbouring grid unit if any
* @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
* @param resFlags flags for the border resolution
*/
public void resolveBorder(GridUnit other, int side, int resFlags) {
CollapsingBorderModel borderModel = CollapsingBorderModel.getBorderModelFor(
getTable().getBorderCollapse());
if (this.effBorders == null) {
this.effBorders = new CommonBorderPaddingBackground();
}
this.effBorders.setBorderInfo(
borderModel.determineWinner(this, other,
side, resFlags), side);
}
public boolean getFlag(int which) {
return (flags & (1 << which)) != 0;
}
public void setFlag(int which, boolean value) {
if (value) {
flags |= (1 << which); //set flag
} else {
flags &= ~(1 << which); //clear flag
}
}
/**
* @return the grid unit just below this grid unit if the cell is spanning.
*/
public GridUnit createNextRowSpanningGridUnit() {
if (isLastGridUnitRowSpan()) {
return null;
} else {
//cloning the current GridUnit with adjustments
GridUnit gu = new GridUnit(getPrimary(), getColumn(), startCol, colSpanIndex);
gu.rowSpanIndex = rowSpanIndex + 1;
return gu;
}
}
/** @see java.lang.Object#toString() */
public String toString() {
StringBuffer sb = new StringBuffer();
if (isEmpty()) {
sb.append("EMPTY");
} else if (isPrimary()) {
sb.append("Primary");
}
sb.append("GridUnit:");
if (colSpanIndex > 0) {
sb.append(" colSpan=").append(colSpanIndex);
}
if (rowSpanIndex > 0) {
sb.append(" rowSpan=").append(rowSpanIndex);
}
sb.append(" startCol=").append(startCol);
sb.append(" flags=").append(Integer.toBinaryString(flags));
return sb.toString();
}
}