<td class="no">
no
</td>
- <td class="no">
- no
+ <td class="yes">
+ yes
</td>
<td align="center">
* @throws FOPException If an error occurs while building the PropertyList
*/
public void addAttributesToList(Attributes attributes) {
- /*
- * If font-size is set on this FO, must set it first, since
- * other attributes specified in terms of "ems" depend on it.
- */
- /** @todo When we do "shorthand" properties, must handle the
- * "font" property as well to see if font-size is set.
- */
- String attributeName = "font-size";
- String attributeValue = attributes.getValue(attributeName);
+ /*
+ * If column-number/number-columns-spanned are specified, then we
+ * need them before all others (possible from-table-column() on any
+ * other property further in the list...
+ */
+ String attributeName = "column-number";
+ String attributeValue = attributes.getValue(attributeName);
+ convertAttributeToProperty(attributes, attributeName,
+ attributeValue);
+ attributeName = "number-columns-spanned";
+ attributeValue = attributes.getValue(attributeName);
+ convertAttributeToProperty(attributes, attributeName,
+ attributeValue);
+
+ /*
+ * If font-size is set on this FO, must set it first, since
+ * other attributes specified in terms of "ems" depend on it.
+ */
+ /** @todo When we do "shorthand" properties, must handle the
+ * "font" property as well to see if font-size is set.
+ */
+ attributeName = "font-size";
+ attributeValue = attributes.getValue(attributeName);
+ convertAttributeToProperty(attributes, attributeName,
+ attributeValue);
+
+ for (int i = 0; i < attributes.getLength(); i++) {
+ attributeName = attributes.getQName(i);
+ attributeValue = attributes.getValue(i);
convertAttributeToProperty(attributes, attributeName,
attributeValue);
-
- for (int i = 0; i < attributes.getLength(); i++) {
- attributeName = attributes.getQName(i);
- attributeValue = attributes.getValue(i);
- convertAttributeToProperty(attributes, attributeName,
- attributeValue);
- }
+ }
}
/**
package org.apache.fop.fo.expr;
+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.Table;
+import org.apache.fop.fo.flow.TableFObj;
+import org.apache.fop.fo.flow.TableCell;
+import org.apache.fop.fo.flow.TableColumn;
import org.apache.fop.fo.properties.Property;
/**
*/
public Property eval(Property[] args,
PropertyInfo pInfo) throws PropertyException {
- /* uncomment when implementing
- String propName = args[0].getString();
- if (propName == null) {
- throw new PropertyException("Incorrect parameter to from-table-column function");
+
+ FObj fo = pInfo.getPropertyList().getFObj();
+
+ /* obtain property Id for the property for which the function is being
+ * evaluated */
+ int propId = 0;
+ if (args.length == 0) {
+ propId = pInfo.getPropertyMaker().getPropId();
+ } else {
+ 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: */
+ int columnNumber = -1;
+ int span = 0;
+ if (fo.getNameId() != Constants.FO_TABLE_CELL) {
+ // climb up to the nearest cell
+ do {
+ fo = (FObj) fo.getParent();
+ } while (fo.getNameId() != Constants.FO_TABLE_CELL
+ && fo.getNameId() != Constants.FO_PAGE_SEQUENCE);
+ if (fo.getNameId() == Constants.FO_TABLE_CELL) {
+ //column-number is available on the cell
+ columnNumber = ((TableCell) fo).getColumnNumber();
+ span = ((TableCell) fo).getNumberColumnsSpanned();
+ } else {
+ //means no table-cell was found...
+ throw new PropertyException("from-table-column() may only be used on "
+ + "fo:table-cell or its descendants.");
+ }
+ } else {
+ //column-number is only accurately available through the propertyList
+ columnNumber = pInfo.getPropertyList().get(Constants.PR_COLUMN_NUMBER)
+ .getNumeric().getValue();
+ span = pInfo.getPropertyList().get(Constants.PR_NUMBER_COLUMNS_SPANNED)
+ .getNumeric().getValue();
+ }
+
+ /* return the property from the column */
+ Table t = ((TableFObj) fo).getTable();
+ List cols = t.getColumns();
+ if (cols == null) {
+ //no columns defined => no match: return default value
+ return pInfo.getPropertyList().get(propId, false, true);
+ } else {
+ if (t.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)) {
+ //nop: just increment/decrement
+ }
+ if (t.isColumnNumberUsed(columnNumber)) {
+ return ((TableColumn) cols.get(columnNumber - 1)).getProperty(propId);
+ } else {
+ //no match: return default value
+ return pInfo.getPropertyList().get(propId, false, true);
+ }
+ }
+ }
+ } else {
+ throw new PropertyException("Incorrect parameter to from-table-column() function");
}
- */
- throw new PropertyException("The from-table-column() function is not implemented, yet!");
}
}
/** collection of columns in this table */
protected List columns = null;
- private BitSet usedColumnIndices = new BitSet();
private int columnIndex = 1;
+ private BitSet usedColumnIndices = new BitSet();
private TableBody tableHeader = null;
private TableBody tableFooter = null;
missingChildElementError(
"(marker*,table-column*,table-header?,table-footer?,table-body+)");
}
- //release reference
- usedColumnIndices = null;
+ if (columns != null && !columns.isEmpty()) {
+ for (int i = columns.size(); --i >= 0;) {
+ if (isColumnNumberUsed(i + 1)) {
+ ((TableColumn) columns.get(i)).releasePropertyList();
+ }
+ }
+ }
getFOEventHandler().endTable(this);
}
//in case column is repeated:
//for the time being, add the same column
//(colRepeat - 1) times to the columns list
- //TODO: need to force the column-number
- //TODO: need to make sure START/END BorderInfo
- // are completely independent instances (clones?)
- // = necessary for border-collapse="collapse"
- // if collapsing is handled in FOTree
+ //TODO: need to force the column-number (?)
for (int i = colRepeat - 1; --i >= 0;) {
columns.add(col);
}
columnIndex++;
}
}
+
/** @return true of table-layout="auto" */
public boolean isAutoLayout() {
return (tableLayout != EN_FIXED);
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 TableColumn.bind() in case the column-number
public void setCurrentColumnIndex(int newIndex) {
columnIndex = newIndex;
}
-
- /**
- * Checks if a certain column-number is already occupied
- *
- * @param colNr the column-number to check
- * @return true if column-number is already in use
- */
- protected boolean isColumnNumberUsed(int colNr) {
- return usedColumnIndices.get(colNr - 1);
- }
+
}
* @param colNr the column-number to check
* @return true if column-number is already occupied
*/
- protected boolean isColumnNumberUsed(int colNr) {
+ public boolean isColumnNumberUsed(int colNr) {
return usedColumnIndices.get(colNr - 1);
}
}
startsRow = pList.get(PR_STARTS_ROW).getEnum();
width = pList.get(PR_WIDTH).getLength();
super.bind(pList);
-
- //check if any of the column-numbers occupied by this cell
- //are already in use in the current row...
- int i = -1;
- int columnIndex = columnNumber.getValue();
- while (++i < getNumberColumnsSpanned()) {
- //if table has explicit columns and the column-number isn't
- //assigned to any column, increment further until the next
- //column is encountered
- if (getTable().columns != null) {
- while (columnIndex <= getTable().columns.size()
- && !getTable().isColumnNumberUsed(columnIndex)) {
- columnIndex++;
- }
- }
- //if column-number is already in use by another cell
- //in the current row => error!
- if (((TableFObj) parent).isColumnNumberUsed(columnIndex)) {
- throw new FOPException("fo:table-cell overlaps in column "
- + columnIndex, locator);
- }
- }
}
/**
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.StaticPropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.fo.properties.Property;
/**
* Class modelling the fo:table-column object.
// End of property values
private boolean defaultColumn;
+ private StaticPropertyList pList = null;
/**
* @param parent FONode that is the parent of this object
throw new PropertyException("number-columns-spanned must be 1 or bigger, "
+ "but got " + numberColumnsSpanned.getValue());
}
+ this.pList = new StaticPropertyList(this, pList);
}
/**
sb.append(" column-width=").append(getColumnWidth());
return sb.toString();
}
+
+ /**
+ * Retrieve a property value through its Id; used by from-table-column() function
+ *
+ * @param propId the id for the property to retrieve
+ * @return the requested Property
+ * @throws PropertyException
+ */
+ public Property getProperty(int propId) throws PropertyException {
+ return this.pList.getInherited(propId);
+ }
+
+ /**
+ * Clear the reference to the PropertyList (retained for from-table-column())
+ *
+ */
+ protected void releasePropertyList() {
+ this.pList = null;
+ }
}
* @param colNr the column-number to check
* @return true if column-number is already in use
*/
- protected boolean isColumnNumberUsed(int colNr) {
+ public boolean isColumnNumberUsed(int colNr) {
return false;
}
* @return the base table instance
*
*/
- protected Table getTable() {
+ public Table getTable() {
if (this.getNameId() == FO_TABLE) {
//node is a Table
//=> return itself
* @param colNr the column-number to check
* @return true if column-number is already occupied
*/
- protected boolean isColumnNumberUsed(int colNr) {
+ public boolean isColumnNumberUsed(int colNr) {
return usedColumnIndices.get(colNr - 1);
}
}
package org.apache.fop.fo.properties;
+import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
throws PropertyException {
Property p = super.get(0, propertyList, tryInherit, tryDefault);
- FObj fo = propertyList.getFObj();
+ TableFObj fo = (TableFObj) propertyList.getFObj();
TableFObj parent = (TableFObj) propertyList.getParentFObj();
+ int columnIndex = p.getNumeric().getValue();
- if (p.getNumeric().getValue() <= 0) {
- int columnIndex = parent.getCurrentColumnIndex();
+ if (columnIndex <= 0) {
fo.getLogger().warn("Specified negative or zero value for "
+ "column-number on " + fo.getName() + ": "
- + p.getNumeric().getValue() + " forced to "
- + columnIndex);
- return new NumberProperty(columnIndex);
+ + columnIndex + " forced to "
+ + parent.getCurrentColumnIndex());
+ return new NumberProperty(parent.getCurrentColumnIndex());
}
//TODO: check for non-integer value and round
+ if (fo.getNameId() == Constants.FO_TABLE_CELL) {
+ //check if any of the column-numbers occupied by this cell
+ //are already in use in the current row...
+ int i = -1;
+ int colspan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED)
+ .getNumeric().getValue();
+ while (++i < colspan) {
+ //if table has explicit columns and the column-number isn't
+ //assigned to any column, increment further until the next
+ //column is encountered
+ if (fo.getTable().getColumns() != null) {
+ while (columnIndex <= fo.getTable().getColumns().size()
+ && !fo.getTable().isColumnNumberUsed(columnIndex)) {
+ columnIndex++;
+ }
+ }
+ //if column-number is already in use by another cell
+ //in the current row => error!
+ if (parent.isColumnNumberUsed(columnIndex + i)) {
+ throw new PropertyException("fo:table-cell overlaps in column "
+ + (columnIndex + i));
+ }
+ }
+ }
+
//if column-number was explicitly specified, force the parent's current
//column index to the specified value, so that the updated index will
//be the correct initial value for the next cell (see Rec 7.26.8)
<changes>
<release version="FOP Trunk">
+ <action context="Code" dev="AD" type="add">
+ Added support for the from-table-column() function.
+ (Thanks to gerhard.oettl.at.oesoft.at for the inspiration.)
+ </action>
<action context="Code" dev="JM" type="fix" fixes-bug="38397">
Bugfix: Spanned cells could lead to an false error message about overlapping
cells and ultimately a NullPointerException.
<file>inline-progression-dimension_negative.fo</file>
<description>The code currently doesn't set negative values to 0mpt as mandated by the spec.</description>
</testcase>
+ <testcase>
+ <name>Markers and core function evaluation</name>
+ <file>from-table-column_marker.fo</file>
+ <description>The code currently evaluates this function according to the column in which the
+ marker appearsin the source document, rather than the column it is retrieved in.</description>
+ </testcase>
</disabled-testcases>
</fo:block>
</fo:block>
</fo:block>
- <!-- from-table-column (not implemented) -->
+ <fo:table border-collapse="separate" table-layout="fixed" width="100%">
+ <fo:table-column column-width="proportional-column-width(1)"
+ text-align="start" />
+ <fo:table-column column-width="proportional-column-width(1)"
+ text-align="center" />
+ <fo:table-column column-width="proportional-column-width(1)"
+ text-align="end" />
+ <fo:table-body>
+ <fo:table-cell starts-row="true">
+ <fo:block text-align="from-table-column()">
+ <test:assert property="text-align" expected="START" />
+ Start-aligned
+ </fo:block>
+ </fo:table-cell>
+ <fo:table-cell text-align="from-table-column()" column-number="3">
+ <test:assert property="text-align" expected="END" />
+ <fo:block>
+ <test:assert property="text-align" expected="END" />
+ End-aligned
+ </fo:block>
+ </fo:table-cell>
+ <fo:table-cell column-number="2">
+ <fo:block text-align="from-table-column()">
+ <test:assert property="text-align" expected="CENTER" />
+ Center-aligned
+ </fo:block>
+ </fo:table-cell>
+ </fo:table-body>
+ </fo:table>
+
<!-- merge-property-value (not implemented) -->
</fo:flow>
</fo:page-sequence>