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.

PrimaryGridUnit.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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.LinkedList;
  20. import java.util.List;
  21. import org.apache.fop.fo.Constants;
  22. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  23. import org.apache.fop.layoutmgr.ElementListUtils;
  24. import org.apache.fop.layoutmgr.table.TableCellLayoutManager;
  25. /**
  26. * This class represents a primary grid unit of a spanned cell. This is the "before-start"
  27. * (top-left, usually) grid unit of the span.
  28. */
  29. public class PrimaryGridUnit extends GridUnit {
  30. /** Cell layout manager. */
  31. private TableCellLayoutManager cellLM;
  32. /** List of Knuth elements representing the contents of the cell. */
  33. private LinkedList elements;
  34. /** Index of the row where this cell starts. */
  35. private int rowIndex;
  36. /** Index of the column where this cell starts. */
  37. private int colIndex;
  38. /** Links to the spanned grid units. (List of GridUnit arrays, one array represents a row) */
  39. private List rows;
  40. /** The calculated size of the cell's content. (cached value) */
  41. private int contentLength = -1;
  42. private boolean isSeparateBorderModel;
  43. private int halfBorderSeparationBPD;
  44. private boolean keepWithPrevious;
  45. private boolean keepWithNext;
  46. private int breakBefore = Constants.EN_AUTO;
  47. private int breakAfter = Constants.EN_AUTO;
  48. /**
  49. * Creates a new primary grid unit.
  50. *
  51. * @param cell table cell which occupies this grid unit
  52. * @param colIndex index of the column this grid unit belongs to, zero-based
  53. */
  54. PrimaryGridUnit(TableCell cell, int colIndex) {
  55. super(cell, 0, 0);
  56. this.colIndex = colIndex;
  57. this.isSeparateBorderModel = cell.getTable().isSeparateBorderModel(); // TODO
  58. this.halfBorderSeparationBPD = cell.getTable().getBorderSeparation().getBPD().getLength()
  59. .getValue() / 2; // TODO
  60. }
  61. public TableCellLayoutManager getCellLM() {
  62. assert cellLM != null;
  63. return cellLM;
  64. }
  65. /** {@inheritDoc} */
  66. public PrimaryGridUnit getPrimary() {
  67. return this;
  68. }
  69. /** {@inheritDoc} */
  70. public boolean isPrimary() {
  71. return true;
  72. }
  73. /**
  74. * Sets the Knuth elements for the table cell containing this grid unit.
  75. *
  76. * @param elements a list of ListElement (?)
  77. */
  78. public void setElements(LinkedList elements) {
  79. this.elements = elements;
  80. }
  81. public LinkedList getElements() {
  82. return this.elements;
  83. }
  84. /**
  85. * Returns the widths of the border-before and -after for this cell. In the separate
  86. * border model the border-separation is included. In the collapsing model only half
  87. * of them is counted, since the other halves belong to the neighbouring cells; also,
  88. * the returned value is the maximum of the segments of each applicable grid unit.
  89. *
  90. * @return the sum of the before and after border widths
  91. */
  92. public int getBeforeAfterBorderWidth() {
  93. return getBeforeBorderWidth(0, ConditionalBorder.NORMAL)
  94. + getAfterBorderWidth(ConditionalBorder.NORMAL);
  95. }
  96. /**
  97. * Returns the width of the before-border for the given row-span of this cell. In the
  98. * separate border model half of the border-separation is included. In the collapsing
  99. * model only half of the border is counted, since the other half belongs to the
  100. * preceding cell; also, the returned value is the maximum of the segments of each
  101. * applicable grid unit.
  102. *
  103. * @param rowIndex index of the span for which the border must be computed, 0-based
  104. * @param which one of {@link ConditionalBorder#NORMAL},
  105. * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
  106. * @return the before border width
  107. */
  108. public int getBeforeBorderWidth(int rowIndex, int which) {
  109. if (isSeparateBorderModel) {
  110. if (getCell() == null) {
  111. return 0;
  112. } else {
  113. CommonBorderPaddingBackground cellBorders = getCell()
  114. .getCommonBorderPaddingBackground();
  115. switch (which) {
  116. case ConditionalBorder.NORMAL:
  117. case ConditionalBorder.LEADING_TRAILING:
  118. return cellBorders.getBorderBeforeWidth(false) + halfBorderSeparationBPD;
  119. case ConditionalBorder.REST:
  120. if (cellBorders.getBorderInfo(CommonBorderPaddingBackground.BEFORE).getWidth()
  121. .isDiscard()) {
  122. return 0;
  123. } else {
  124. return cellBorders.getBorderBeforeWidth(true) + halfBorderSeparationBPD;
  125. }
  126. default:
  127. assert false;
  128. return 0;
  129. }
  130. }
  131. } else {
  132. int width = 0;
  133. GridUnit[] row = (GridUnit[]) rows.get(rowIndex);
  134. for (int i = 0; i < row.length; i++) {
  135. width = Math.max(width,
  136. row[i].getBorderBefore(which).getRetainedWidth());
  137. }
  138. return width / 2;
  139. }
  140. }
  141. /**
  142. * Returns the width of the before-after for the given row-span of this cell. In the
  143. * separate border model half of the border-separation is included. In the collapsing
  144. * model only half of the border is counted, since the other half belongs to the
  145. * following cell; also, the returned value is the maximum of the segments of each
  146. * applicable grid unit.
  147. *
  148. * @param rowIndex index of the span for which the border must be computed, 0-based
  149. * @param which one of {@link ConditionalBorder#NORMAL},
  150. * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
  151. * @return the after border width
  152. */
  153. public int getAfterBorderWidth(int rowIndex, int which) {
  154. if (isSeparateBorderModel) {
  155. if (getCell() == null) {
  156. return 0;
  157. } else {
  158. CommonBorderPaddingBackground cellBorders = getCell()
  159. .getCommonBorderPaddingBackground();
  160. switch (which) {
  161. case ConditionalBorder.NORMAL:
  162. case ConditionalBorder.LEADING_TRAILING:
  163. return cellBorders.getBorderAfterWidth(false) + halfBorderSeparationBPD;
  164. case ConditionalBorder.REST:
  165. if (cellBorders.getBorderInfo(CommonBorderPaddingBackground.AFTER).getWidth()
  166. .isDiscard()) {
  167. return 0;
  168. } else {
  169. return cellBorders.getBorderAfterWidth(true) + halfBorderSeparationBPD;
  170. }
  171. default:
  172. assert false;
  173. return 0;
  174. }
  175. }
  176. } else {
  177. int width = 0;
  178. GridUnit[] row = (GridUnit[]) rows.get(rowIndex);
  179. for (int i = 0; i < row.length; i++) {
  180. width = Math.max(width,
  181. row[i].getBorderAfter(which).getRetainedWidth());
  182. }
  183. return width / 2;
  184. }
  185. }
  186. /**
  187. * Returns the width of the before-after for the last row-span of this cell. See
  188. * {@link #getAfterBorderWidth(int, int)}.
  189. *
  190. * @param which one of {@link ConditionalBorder#NORMAL},
  191. * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
  192. * @return the after border width
  193. */
  194. public int getAfterBorderWidth(int which) {
  195. return getAfterBorderWidth(getCell().getNumberRowsSpanned() - 1, which);
  196. }
  197. /** @return the length of the cell content. */
  198. public int getContentLength() {
  199. if (contentLength < 0) {
  200. contentLength = ElementListUtils.calcContentLength(elements);
  201. }
  202. return contentLength;
  203. }
  204. /** @return true if cell/row has an explicit BPD/height */
  205. public boolean hasBPD() {
  206. if (!getCell().getBlockProgressionDimension().getOptimum(null).isAuto()) {
  207. return true;
  208. }
  209. if (getRow() != null
  210. && !getRow().getBlockProgressionDimension().getOptimum(null).isAuto()) {
  211. return true;
  212. }
  213. return false;
  214. }
  215. /**
  216. * Returns the grid units belonging to the same span as this one.
  217. *
  218. * @return a list of GridUnit[], each array corresponds to a row
  219. */
  220. public List getRows() {
  221. return this.rows;
  222. }
  223. public void addRow(GridUnit[] row) {
  224. if (rows == null) {
  225. rows = new java.util.ArrayList();
  226. }
  227. rows.add(row);
  228. }
  229. void setRowIndex(int rowIndex) {
  230. this.rowIndex = rowIndex;
  231. }
  232. /**
  233. * Returns the index of the row this grid unit belongs to. This is the index, in the
  234. * enclosing table part, of the first row spanned by the cell. Note that if the table
  235. * has several table-body children, then the index grows continuously across them;
  236. * they are considered to form one single part, the "body of the table".
  237. *
  238. * @return the index of the row this grid unit belongs to, 0-based.
  239. */
  240. public int getRowIndex() {
  241. return rowIndex;
  242. }
  243. /**
  244. * Returns the index of the column this grid unit belongs to.
  245. *
  246. * @return the column index, 0-based
  247. */
  248. public int getColIndex() {
  249. return colIndex;
  250. }
  251. /**
  252. * Returns the widths of the start- and end-borders of the span this grid unit belongs
  253. * to.
  254. *
  255. * @return a two-element array containing the widths of the start-border then the
  256. * end-border
  257. */
  258. public int[] getStartEndBorderWidths() {
  259. int[] widths = new int[2];
  260. if (getCell() == null) {
  261. return widths;
  262. } else if (getCell().getTable().isSeparateBorderModel()) {
  263. widths[0] = getCell().getCommonBorderPaddingBackground().getBorderStartWidth(false);
  264. widths[1] = getCell().getCommonBorderPaddingBackground().getBorderEndWidth(false);
  265. } else {
  266. for (int i = 0; i < rows.size(); i++) {
  267. GridUnit[] gridUnits = (GridUnit[])rows.get(i);
  268. widths[0] = Math.max(widths[0],
  269. gridUnits[0].borderStart.getBorderInfo().getRetainedWidth());
  270. widths[1] = Math.max(widths[1], gridUnits[gridUnits.length - 1].borderEnd
  271. .getBorderInfo().getRetainedWidth());
  272. }
  273. }
  274. return widths;
  275. }
  276. /** {@inheritDoc} */
  277. public String toString() {
  278. StringBuffer sb = new StringBuffer(super.toString());
  279. sb.append(" rowIndex=").append(rowIndex);
  280. sb.append(" colIndex=").append(colIndex);
  281. return sb.toString();
  282. }
  283. /** @return true if this cell spans over more than one grid unit. */
  284. public boolean hasSpanning() {
  285. return (getCell().getNumberColumnsSpanned() > 1)
  286. || (getCell().getNumberRowsSpanned() > 1);
  287. }
  288. /**
  289. * Creates a cellLM for the corresponding table-cell. A new one must be created
  290. * for each new static-content (TODO).
  291. */
  292. public void createCellLM() {
  293. cellLM = new TableCellLayoutManager(cell, this);
  294. }
  295. /**
  296. * Returns true if the first child block (or its descendants) of this cell has
  297. * keep-with-previous.
  298. *
  299. * @return the value of keep-with-previous
  300. */
  301. public boolean mustKeepWithPrevious() {
  302. return keepWithPrevious;
  303. }
  304. /**
  305. * Don't use, reserved for TableCellLM. TODO
  306. */
  307. public void setKeepWithPrevious() {
  308. this.keepWithPrevious = true;
  309. }
  310. /**
  311. * Returns true if the last child block (or its descendants) of this cell has
  312. * keep-with-next.
  313. *
  314. * @return the value of keep-with-next
  315. */
  316. public boolean mustKeepWithNext() {
  317. return keepWithNext;
  318. }
  319. /**
  320. * Don't use, reserved for TableCellLM. TODO
  321. */
  322. public void setKeepWithNext() {
  323. this.keepWithNext = true;
  324. }
  325. /**
  326. * Returns the class of the before break for the first child element of this cell.
  327. *
  328. * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
  329. * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
  330. */
  331. public int getBreakBefore() {
  332. return breakBefore;
  333. }
  334. /**
  335. * Don't use, reserved for TableCellLM. TODO
  336. *
  337. * @param breakBefore the breakBefore to set
  338. */
  339. public void setBreakBefore(int breakBefore) {
  340. this.breakBefore = breakBefore;
  341. }
  342. /**
  343. * Returns the class of the before after for the last child element of this cell.
  344. *
  345. * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
  346. * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
  347. */
  348. public int getBreakAfter() {
  349. return breakAfter;
  350. }
  351. /**
  352. * Don't use, reserved for TableCellLM. TODO
  353. *
  354. * @param breakAfter the breakAfter to set
  355. */
  356. public void setBreakAfter(int breakAfter) {
  357. this.breakAfter = breakAfter;
  358. }
  359. }