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.

EffRow.java 10KB

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 java.util.Iterator;
  20. import java.util.List;
  21. import org.apache.fop.fo.Constants;
  22. import org.apache.fop.layoutmgr.table.TableRowIterator;
  23. import org.apache.fop.traits.MinOptMax;
  24. import org.apache.fop.util.BreakUtil;
  25. /**
  26. * This class represents an effective row in a table and holds a list of grid units occupying
  27. * the row as well as some additional values.
  28. */
  29. public class EffRow {
  30. /** Indicates that the row is the first in a table-body */
  31. public static final int FIRST_IN_PART = GridUnit.FIRST_IN_PART;
  32. /** Indicates that the row is the last in a table-body */
  33. public static final int LAST_IN_PART = GridUnit.LAST_IN_PART;
  34. private List gridUnits = new java.util.ArrayList();
  35. private int index;
  36. /** One of HEADER, FOOTER, BODY */
  37. private int bodyType;
  38. private MinOptMax height;
  39. private MinOptMax explicitHeight;
  40. /**
  41. * Creates a new effective row instance.
  42. * @param index index of the row
  43. * @param bodyType type of body (one of HEADER, FOOTER, BODY as found on TableRowIterator)
  44. * @param gridUnits the grid units this row is made of
  45. */
  46. public EffRow(int index, int bodyType, List gridUnits) {
  47. this.index = index;
  48. this.bodyType = bodyType;
  49. this.gridUnits = gridUnits;
  50. // TODO this is ugly, but we may eventually be able to do without that index
  51. for (Iterator guIter = gridUnits.iterator(); guIter.hasNext();) {
  52. Object gu = guIter.next();
  53. if (gu instanceof PrimaryGridUnit) {
  54. ((PrimaryGridUnit) gu).setRowIndex(index);
  55. }
  56. }
  57. }
  58. /** @return the index of the EffRow in the sequence of rows */
  59. public int getIndex() {
  60. return this.index;
  61. }
  62. /**
  63. * @return an indicator what type of body this EffRow is in (one of HEADER, FOOTER, BODY
  64. * as found on TableRowIterator)
  65. */
  66. public int getBodyType() {
  67. return this.bodyType;
  68. }
  69. /** @return the table-row FO for this EffRow, or null if there is no table-row. */
  70. public TableRow getTableRow() {
  71. return getGridUnit(0).getRow();
  72. }
  73. /**
  74. * Returns the calculated height for this EffRow, including the cells'
  75. * bpds/paddings/borders, and the table's border-separation.
  76. *
  77. * @return the row's height
  78. */
  79. public MinOptMax getHeight() {
  80. return this.height;
  81. }
  82. /**
  83. * Sets the calculated height for this EffRow, including everything (cells' bpds,
  84. * paddings, borders, and border-separation).
  85. *
  86. * @param mom the calculated height
  87. */
  88. public void setHeight(MinOptMax mom) {
  89. this.height = mom;
  90. }
  91. /** @return the explicit height of the EffRow (as specified through properties) */
  92. public MinOptMax getExplicitHeight() {
  93. return this.explicitHeight;
  94. }
  95. /**
  96. * Sets the height for this row that resulted from the explicit height properties specified
  97. * by the user.
  98. * @param mom the height
  99. */
  100. public void setExplicitHeight(MinOptMax mom) {
  101. this.explicitHeight = mom;
  102. }
  103. /** @return the list of GridUnits for this EffRow */
  104. public List getGridUnits() {
  105. return gridUnits;
  106. }
  107. /**
  108. * Returns the grid unit at a given position.
  109. * @param column index of the grid unit in the row (zero based)
  110. * @return the requested grid unit.
  111. */
  112. public GridUnit getGridUnit(int column) {
  113. return (GridUnit)gridUnits.get(column);
  114. }
  115. /**
  116. * Returns the grid unit at a given position. In contrast to getGridUnit() this
  117. * method returns null if there's no grid unit at the given position. The number of
  118. * grid units for row x can be smaller than the number of grid units for row x-1.
  119. * @param column index of the grid unit in the row (zero based)
  120. * @return the requested grid unit or null if there's no grid unit at this position.
  121. */
  122. public GridUnit safelyGetGridUnit(int column) {
  123. if (column < gridUnits.size()) {
  124. return (GridUnit)gridUnits.get(column);
  125. } else {
  126. return null;
  127. }
  128. }
  129. /**
  130. * Returns a flag for this effective row. Only a subset of the flags on GridUnit is supported.
  131. * The flag is determined by inspecting flags on the EffRow's GridUnits.
  132. * @param which the requested flag (one of {@link EffRow#FIRST_IN_PART} or {@link
  133. * EffRow#LAST_IN_PART})
  134. * @return true if the flag is set
  135. */
  136. public boolean getFlag(int which) {
  137. if (which == FIRST_IN_PART) {
  138. return getGridUnit(0).getFlag(GridUnit.FIRST_IN_PART);
  139. } else if (which == LAST_IN_PART) {
  140. return getGridUnit(0).getFlag(GridUnit.LAST_IN_PART);
  141. } else {
  142. throw new IllegalArgumentException("Illegal flag queried: " + which);
  143. }
  144. }
  145. /**
  146. * Returns true if the enclosing (if any) fo:table-row element of this row, or if any
  147. * of the cells starting on this row, have keep-with-previous set.
  148. *
  149. * @return true if this row must be kept with the previous content
  150. */
  151. public boolean mustKeepWithPrevious() {
  152. boolean keepWithPrevious = false;
  153. TableRow row = getTableRow();
  154. if (row != null) {
  155. keepWithPrevious = row.mustKeepWithPrevious();
  156. }
  157. for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
  158. GridUnit gu = (GridUnit) iter.next();
  159. if (gu.isPrimary()) {
  160. keepWithPrevious |= gu.getPrimary().mustKeepWithPrevious();
  161. }
  162. }
  163. return keepWithPrevious;
  164. }
  165. /**
  166. * Returns true if the enclosing (if any) fo:table-row element of this row, or if any
  167. * of the cells ending on this row, have keep-with-next set.
  168. *
  169. * @return true if this row must be kept with the next content
  170. */
  171. public boolean mustKeepWithNext() {
  172. boolean keepWithNext = false;
  173. TableRow row = getTableRow();
  174. if (row != null) {
  175. keepWithNext = row.mustKeepWithNext();
  176. }
  177. for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
  178. GridUnit gu = (GridUnit) iter.next();
  179. if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
  180. keepWithNext |= gu.getPrimary().mustKeepWithNext();
  181. }
  182. }
  183. return keepWithNext;
  184. }
  185. /**
  186. * Returns true if this row is enclosed by an fo:table-row element that has
  187. * keep-together set.
  188. *
  189. * @return true if this row must be kept together
  190. */
  191. public boolean mustKeepTogether() {
  192. TableRow row = getTableRow();
  193. return row != null && row.mustKeepTogether();
  194. }
  195. /**
  196. * Returns the break class for this row. This is a combination of break-before set on
  197. * the first children of any cells starting on this row.
  198. * <p><strong>Note:</strong> this method doesn't take into account break-before set on
  199. * the enclosing fo:table-row element, if any, as it must be ignored if the row
  200. * belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.2).
  201. * <p><strong>Note:</strong> this works only after getNextKuthElements on the
  202. * corresponding TableCellLM have been called!</p>
  203. *
  204. * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
  205. * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
  206. */
  207. public int getBreakBefore() {
  208. int breakBefore = Constants.EN_AUTO;
  209. for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
  210. GridUnit gu = (GridUnit) iter.next();
  211. if (gu.isPrimary()) {
  212. breakBefore = BreakUtil.compareBreakClasses(breakBefore,
  213. gu.getPrimary().getBreakBefore());
  214. }
  215. }
  216. return breakBefore;
  217. }
  218. /**
  219. * Returns the break class for this row. This is a combination of break-after set on
  220. * the last children of any cells ending on this row.
  221. * <p><strong>Note:</strong> this method doesn't take into account break-after set on
  222. * the enclosing fo:table-row element, if any, as it must be ignored if the row
  223. * belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.1).
  224. * <p><strong>Note:</strong> this works only after getNextKuthElements on the
  225. * corresponding TableCellLM have been called!</p>
  226. *
  227. * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
  228. * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
  229. */
  230. public int getBreakAfter() {
  231. int breakAfter = Constants.EN_AUTO;
  232. for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
  233. GridUnit gu = (GridUnit) iter.next();
  234. if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
  235. breakAfter = BreakUtil.compareBreakClasses(breakAfter,
  236. gu.getPrimary().getBreakAfter());
  237. }
  238. }
  239. return breakAfter;
  240. }
  241. /** {@inheritDoc} */
  242. public String toString() {
  243. StringBuffer sb = new StringBuffer("EffRow {");
  244. sb.append(index);
  245. if (getBodyType() == TableRowIterator.BODY) {
  246. sb.append(" in body");
  247. } else if (getBodyType() == TableRowIterator.HEADER) {
  248. sb.append(" in header");
  249. } else {
  250. sb.append(" in footer");
  251. }
  252. sb.append(", ").append(height);
  253. sb.append(", ").append(explicitHeight);
  254. sb.append(", ").append(gridUnits.size()).append(" gu");
  255. sb.append("}");
  256. return sb.toString();
  257. }
  258. }