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

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