You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TableFObj.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.fo.flow.table;
  19. import org.xml.sax.Attributes;
  20. import org.xml.sax.Locator;
  21. import org.apache.fop.apps.FOPException;
  22. import org.apache.fop.datatypes.Numeric;
  23. import org.apache.fop.datatypes.ValidationPercentBaseContext;
  24. import org.apache.fop.fo.Constants;
  25. import org.apache.fop.fo.FONode;
  26. import org.apache.fop.fo.FObj;
  27. import org.apache.fop.fo.PropertyList;
  28. import org.apache.fop.fo.expr.PropertyException;
  29. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  30. import org.apache.fop.fo.properties.EnumNumber;
  31. import org.apache.fop.fo.properties.EnumProperty;
  32. import org.apache.fop.fo.properties.NumberProperty;
  33. import org.apache.fop.fo.properties.Property;
  34. import org.apache.fop.fo.properties.PropertyMaker;
  35. import org.apache.fop.fo.properties.StructurePointerPropertySet;
  36. import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
  37. /**
  38. * Common base class for table-related FOs
  39. */
  40. public abstract class TableFObj extends FObj implements StructurePointerPropertySet {
  41. private Numeric borderAfterPrecedence;
  42. private Numeric borderBeforePrecedence;
  43. private Numeric borderEndPrecedence;
  44. private Numeric borderStartPrecedence;
  45. private String ptr;
  46. ConditionalBorder borderBefore;
  47. ConditionalBorder borderAfter;
  48. BorderSpecification borderStart;
  49. BorderSpecification borderEnd;
  50. CollapsingBorderModel collapsingBorderModel;
  51. /**
  52. * Create a TableFObj instance that is a child
  53. * of the given {@link FONode}
  54. *
  55. * @param parent the parent {@link FONode}
  56. */
  57. public TableFObj(FONode parent) {
  58. super(parent);
  59. }
  60. /** {@inheritDoc} */
  61. public void bind(PropertyList pList) throws FOPException {
  62. super.bind(pList);
  63. borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric();
  64. borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
  65. borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
  66. borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric();
  67. ptr = pList.get(PR_X_PTR).getString();
  68. if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java
  69. && getNameId() != FO_TABLE_CELL
  70. && getCommonBorderPaddingBackground().hasPadding(
  71. ValidationPercentBaseContext.getPseudoContext())) {
  72. TableEventProducer eventProducer = TableEventProducer.Provider.get(
  73. getUserAgent().getEventBroadcaster());
  74. eventProducer.paddingNotApplicable(this, getName(), getLocator());
  75. }
  76. }
  77. /**
  78. * Return the value for the "border-precedence" property
  79. * for the given side.
  80. *
  81. * @param side the side for which to return the border precedence
  82. * @return the "border-precedence" value for the given side
  83. */
  84. public Numeric getBorderPrecedence(int side) {
  85. switch (side) {
  86. case CommonBorderPaddingBackground.BEFORE:
  87. return borderBeforePrecedence;
  88. case CommonBorderPaddingBackground.AFTER:
  89. return borderAfterPrecedence;
  90. case CommonBorderPaddingBackground.START:
  91. return borderStartPrecedence;
  92. case CommonBorderPaddingBackground.END:
  93. return borderEndPrecedence;
  94. default:
  95. return null;
  96. }
  97. }
  98. /**
  99. * Convenience method to returns a reference
  100. * to the base {@link Table} instance.
  101. *
  102. * @return the base table instance
  103. *
  104. */
  105. public Table getTable() {
  106. // Overridden in Table; for any other Table-node, recursive call to
  107. // parent.getTable()
  108. return ((TableFObj) parent).getTable();
  109. }
  110. /**
  111. * @return the Common Border, Padding, and Background Properties.
  112. */
  113. public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground();
  114. /**
  115. * {@link PropertyMaker} subclass for the column-number property
  116. */
  117. public static class ColumnNumberPropertyMaker extends PropertyMaker {
  118. /**
  119. * Constructor
  120. *
  121. * @param propId the id of the property for which the maker should
  122. * be created
  123. */
  124. public ColumnNumberPropertyMaker(int propId) {
  125. super(propId);
  126. }
  127. /** {@inheritDoc} */
  128. public Property make(PropertyList propertyList)
  129. throws PropertyException {
  130. FObj fo = propertyList.getFObj();
  131. return NumberProperty.getInstance(((ColumnNumberManagerHolder) fo.getParent())
  132. .getColumnNumberManager().getCurrentColumnNumber());
  133. }
  134. /**
  135. * {@inheritDoc}
  136. * Check the value of the column-number property.
  137. */
  138. public Property make(PropertyList propertyList, String value, FObj fo)
  139. throws PropertyException {
  140. Property p = super.make(propertyList, value, fo);
  141. int columnIndex = p.getNumeric().getValue();
  142. int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED)
  143. .getNumeric().getValue();
  144. // only check whether the column-number is occupied in case it was
  145. // specified on a fo:table-cell or fo:table-column
  146. int foId = propertyList.getFObj().getNameId();
  147. if (foId == FO_TABLE_COLUMN || foId == FO_TABLE_CELL) {
  148. ColumnNumberManagerHolder parent
  149. = (ColumnNumberManagerHolder) propertyList.getParentFObj();
  150. ColumnNumberManager columnIndexManager = parent.getColumnNumberManager();
  151. int lastIndex = columnIndex - 1 + colSpan;
  152. for (int i = columnIndex; i <= lastIndex; ++i) {
  153. if (columnIndexManager.isColumnNumberUsed(i)) {
  154. /* if column-number is already in use by another
  155. * cell/column => error!
  156. */
  157. TableEventProducer eventProducer
  158. = TableEventProducer.Provider.get(
  159. fo.getUserAgent().getEventBroadcaster());
  160. eventProducer.cellOverlap(
  161. this, propertyList.getFObj().getName(),
  162. i, propertyList.getFObj().getLocator());
  163. }
  164. }
  165. }
  166. return p;
  167. }
  168. /**
  169. * {@inheritDoc}
  170. * If the value is not positive, return a property whose value
  171. * is the next column number.
  172. */
  173. public Property convertProperty(Property p,
  174. PropertyList propertyList, FObj fo)
  175. throws PropertyException {
  176. if (p instanceof EnumProperty) {
  177. return EnumNumber.getInstance(p);
  178. }
  179. Number val = p.getNumber();
  180. if (val != null) {
  181. int i = Math.round(val.floatValue());
  182. int foId = propertyList.getFObj().getNameId();
  183. if (i <= 0) {
  184. if (foId == FO_TABLE_CELL || foId == FO_TABLE_COLUMN) {
  185. ColumnNumberManagerHolder parent =
  186. (ColumnNumberManagerHolder) propertyList.getParentFObj();
  187. ColumnNumberManager columnIndexManager = parent.getColumnNumberManager();
  188. i = columnIndexManager.getCurrentColumnNumber();
  189. } else {
  190. /* very exceptional case:
  191. * negative column-number specified on
  192. * a FO that is not a fo:table-cell or fo:table-column
  193. */
  194. i = 1;
  195. }
  196. TableEventProducer eventProducer =
  197. TableEventProducer.Provider.get(fo.getUserAgent().getEventBroadcaster());
  198. eventProducer.forceNextColumnNumber(this, propertyList.getFObj().getName(),
  199. val, i, propertyList.getFObj().getLocator());
  200. }
  201. return NumberProperty.getInstance(i);
  202. }
  203. return convertPropertyDatatype(p, propertyList, fo);
  204. }
  205. }
  206. /** {@inheritDoc} */
  207. public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException {
  208. super.processNode(elementName, locator, attlist, pList);
  209. Table table = getTable();
  210. if (!inMarker() && !table.isSeparateBorderModel()) {
  211. collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
  212. .getBorderCollapse());
  213. setCollapsedBorders();
  214. }
  215. }
  216. /** {@inheritDoc} */
  217. public String getPtr() {
  218. return ptr;
  219. }
  220. /**
  221. * Prepares the borders of this element if the collapsing-border model is in use.
  222. * Conflict resolution with parent elements is done where applicable.
  223. */
  224. protected void setCollapsedBorders() {
  225. createBorder(CommonBorderPaddingBackground.START);
  226. createBorder(CommonBorderPaddingBackground.END);
  227. createBorder(CommonBorderPaddingBackground.BEFORE);
  228. createBorder(CommonBorderPaddingBackground.AFTER);
  229. }
  230. /**
  231. * Creates a BorderSpecification from the border set on the given side. If no border
  232. * is set, a BorderSpecification with border-style none is created.
  233. *
  234. * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
  235. */
  236. private void createBorder(int side) {
  237. BorderSpecification borderSpec = new BorderSpecification(
  238. getCommonBorderPaddingBackground().getBorderInfo(side), getNameId());
  239. switch (side) {
  240. case CommonBorderPaddingBackground.BEFORE:
  241. borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel);
  242. break;
  243. case CommonBorderPaddingBackground.AFTER:
  244. borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel);
  245. break;
  246. case CommonBorderPaddingBackground.START:
  247. borderStart = borderSpec;
  248. break;
  249. case CommonBorderPaddingBackground.END:
  250. borderEnd = borderSpec;
  251. break;
  252. default: assert false;
  253. }
  254. }
  255. }