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

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