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.

TableCellLayoutManager.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  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.layoutmgr.table;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import org.apache.commons.logging.Log;
  22. import org.apache.commons.logging.LogFactory;
  23. import org.apache.fop.area.Area;
  24. import org.apache.fop.area.Block;
  25. import org.apache.fop.area.Trait;
  26. import org.apache.fop.fo.flow.table.ConditionalBorder;
  27. import org.apache.fop.fo.flow.table.GridUnit;
  28. import org.apache.fop.fo.flow.table.PrimaryGridUnit;
  29. import org.apache.fop.fo.flow.table.Table;
  30. import org.apache.fop.fo.flow.table.TableCell;
  31. import org.apache.fop.fo.flow.table.TableColumn;
  32. import org.apache.fop.fo.flow.table.TablePart;
  33. import org.apache.fop.fo.flow.table.TableRow;
  34. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  35. import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
  36. import org.apache.fop.layoutmgr.AreaAdditionUtil;
  37. import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
  38. import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
  39. import org.apache.fop.layoutmgr.ElementListUtils;
  40. import org.apache.fop.layoutmgr.Keep;
  41. import org.apache.fop.layoutmgr.KnuthBox;
  42. import org.apache.fop.layoutmgr.KnuthElement;
  43. import org.apache.fop.layoutmgr.KnuthGlue;
  44. import org.apache.fop.layoutmgr.KnuthPenalty;
  45. import org.apache.fop.layoutmgr.LayoutContext;
  46. import org.apache.fop.layoutmgr.LayoutManager;
  47. import org.apache.fop.layoutmgr.Position;
  48. import org.apache.fop.layoutmgr.PositionIterator;
  49. import org.apache.fop.layoutmgr.SpaceResolver;
  50. import org.apache.fop.layoutmgr.TraitSetter;
  51. import org.apache.fop.traits.BorderProps;
  52. import org.apache.fop.traits.MinOptMax;
  53. import org.apache.fop.util.ListUtil;
  54. /**
  55. * LayoutManager for a table-cell FO.
  56. * A cell contains blocks. These blocks fill the cell.
  57. */
  58. public class TableCellLayoutManager extends BlockStackingLayoutManager
  59. implements BlockLevelLayoutManager {
  60. /**
  61. * logging instance
  62. */
  63. private static Log log = LogFactory.getLog(TableCellLayoutManager.class);
  64. private PrimaryGridUnit primaryGridUnit;
  65. private Block curBlockArea;
  66. private int xoffset;
  67. private int yoffset;
  68. private int cellIPD;
  69. private int totalHeight;
  70. private int usedBPD;
  71. private boolean emptyCell = true;
  72. /**
  73. * Create a new Cell layout manager.
  74. * @param node table-cell FO for which to create the LM
  75. * @param pgu primary grid unit for the cell
  76. */
  77. public TableCellLayoutManager(TableCell node, PrimaryGridUnit pgu) {
  78. super(node);
  79. this.primaryGridUnit = pgu;
  80. }
  81. /** @return the table-cell FO */
  82. public TableCell getTableCell() {
  83. return (TableCell)this.fobj;
  84. }
  85. private boolean isSeparateBorderModel() {
  86. return getTable().isSeparateBorderModel();
  87. }
  88. /**
  89. * @return the table owning this cell
  90. */
  91. public Table getTable() {
  92. return getTableCell().getTable();
  93. }
  94. /** {@inheritDoc} */
  95. protected int getIPIndents() {
  96. int[] startEndBorderWidths = primaryGridUnit.getStartEndBorderWidths();
  97. startIndent = startEndBorderWidths[0];
  98. endIndent = startEndBorderWidths[1];
  99. if (isSeparateBorderModel()) {
  100. int borderSep = getTable().getBorderSeparation().getLengthPair().getIPD().getLength()
  101. .getValue(this);
  102. startIndent += borderSep / 2;
  103. endIndent += borderSep / 2;
  104. } else {
  105. startIndent /= 2;
  106. endIndent /= 2;
  107. }
  108. startIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false,
  109. this);
  110. endIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingEnd(false, this);
  111. return startIndent + endIndent;
  112. }
  113. /**
  114. * {@inheritDoc}
  115. */
  116. public List getNextKnuthElements(LayoutContext context, int alignment) {
  117. MinOptMax stackLimit = context.getStackLimitBP();
  118. referenceIPD = context.getRefIPD();
  119. cellIPD = referenceIPD;
  120. cellIPD -= getIPIndents();
  121. List returnedList;
  122. List contentList = new LinkedList();
  123. List returnList = new LinkedList();
  124. LayoutManager curLM; // currently active LM
  125. LayoutManager prevLM = null; // previously active LM
  126. while ((curLM = getChildLM()) != null) {
  127. LayoutContext childLC = LayoutContext.newInstance();
  128. // curLM is a ?
  129. childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit));
  130. childLC.setRefIPD(cellIPD);
  131. // get elements from curLM
  132. returnedList = curLM.getNextKnuthElements(childLC, alignment);
  133. if (childLC.isKeepWithNextPending()) {
  134. log.debug("child LM signals pending keep with next");
  135. }
  136. if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
  137. primaryGridUnit.setKeepWithPrevious(childLC.getKeepWithPreviousPending());
  138. childLC.clearKeepWithPreviousPending();
  139. }
  140. if (prevLM != null
  141. && !ElementListUtils.endsWithForcedBreak(contentList)) {
  142. // there is a block handled by prevLM
  143. // before the one handled by curLM
  144. addInBetweenBreak(contentList, context, childLC);
  145. }
  146. contentList.addAll(returnedList);
  147. if (returnedList.isEmpty()) {
  148. //Avoid NoSuchElementException below (happens with empty blocks)
  149. continue;
  150. }
  151. if (childLC.isKeepWithNextPending()) {
  152. //Clear and propagate
  153. context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
  154. childLC.clearKeepWithNextPending();
  155. }
  156. prevLM = curLM;
  157. }
  158. primaryGridUnit.setKeepWithNext(context.getKeepWithNextPending());
  159. returnedList = new LinkedList();
  160. if (!contentList.isEmpty()) {
  161. wrapPositionElements(contentList, returnList);
  162. } else {
  163. // In relaxed validation mode, table-cells having no children are authorised.
  164. // Add a zero-width block here to not have to take this special case into
  165. // account later
  166. // Copied from BlockStackingLM
  167. returnList.add(new KnuthBox(0, notifyPos(new Position(this)), true));
  168. }
  169. //Space resolution
  170. SpaceResolver.resolveElementList(returnList);
  171. if (((KnuthElement) returnList.get(0)).isForcedBreak()) {
  172. primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.get(0)).getBreakClass());
  173. returnList.remove(0);
  174. assert !returnList.isEmpty();
  175. }
  176. final KnuthElement lastItem = (KnuthElement) ListUtil
  177. .getLast(returnList);
  178. if (lastItem.isForcedBreak()) {
  179. KnuthPenalty p = (KnuthPenalty) lastItem;
  180. primaryGridUnit.setBreakAfter(p.getBreakClass());
  181. p.setPenalty(0);
  182. }
  183. setFinished(true);
  184. return returnList;
  185. }
  186. /**
  187. * Set the y offset of this cell.
  188. * This offset is used to set the absolute position of the cell.
  189. *
  190. * @param off the y direction offset
  191. */
  192. public void setYOffset(int off) {
  193. yoffset = off;
  194. }
  195. /**
  196. * Set the x offset of this cell (usually the same as its parent row).
  197. * This offset is used to determine the absolute position of the cell.
  198. *
  199. * @param off the x offset
  200. */
  201. public void setXOffset(int off) {
  202. xoffset = off;
  203. }
  204. /**
  205. * Set the content height for this cell. This method is used during
  206. * addAreas() stage.
  207. *
  208. * @param h the height of the contents of this cell
  209. */
  210. public void setContentHeight(int h) {
  211. usedBPD = h;
  212. }
  213. /**
  214. * Sets the total height of this cell on the current page. That is, the cell's bpd
  215. * plus before and after borders and paddings, plus the table's border-separation.
  216. *
  217. * @param h the height of cell
  218. */
  219. public void setTotalHeight(int h) {
  220. totalHeight = h;
  221. }
  222. /**
  223. * Add the areas for the break points. The cell contains block stacking layout
  224. * managers that add block areas.
  225. *
  226. * <p>In the collapsing-border model, the borders of a cell that spans over several
  227. * rows or columns are drawn separately for each grid unit. Therefore we must know the
  228. * height of each grid row spanned over by the cell. Also, if the cell is broken over
  229. * two pages we must know which spanned grid rows are present on the current page.</p>
  230. *
  231. * @param parentIter the iterator of the break positions
  232. * @param layoutContext the layout context for adding the areas
  233. * @param spannedGridRowHeights in collapsing-border model for a spanning cell, height
  234. * of each spanned grid row
  235. * @param startRow first grid row on the current page spanned over by the cell,
  236. * inclusive
  237. * @param endRow last grid row on the current page spanned over by the cell, inclusive
  238. * @param borderBeforeWhich one of {@link ConditionalBorder#NORMAL},
  239. * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
  240. * @param borderAfterWhich one of {@link ConditionalBorder#NORMAL},
  241. * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
  242. * @param firstOnPage true if the cell will be the very first one on the page, in
  243. * which case collapsed before borders must be drawn in the outer mode
  244. * @param lastOnPage true if the cell will be the very last one on the page, in which
  245. * case collapsed after borders must be drawn in the outer mode
  246. * @param painter painter
  247. * @param firstRowHeight height of the first row spanned by this cell (may be zero if
  248. * this row is placed on a previous page). Used to calculate the placement of the
  249. * row's background image if any
  250. */
  251. public void addAreas( // CSOK: ParameterNumber
  252. PositionIterator parentIter, LayoutContext layoutContext, int[] spannedGridRowHeights,
  253. int startRow, int endRow, int borderBeforeWhich, int borderAfterWhich,
  254. boolean firstOnPage, boolean lastOnPage, RowPainter painter, int firstRowHeight) {
  255. getParentArea(null);
  256. addId();
  257. int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich);
  258. int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich);
  259. CommonBorderPaddingBackground padding = primaryGridUnit.getCell()
  260. .getCommonBorderPaddingBackground();
  261. int paddingRectBPD = totalHeight - borderBeforeWidth - borderAfterWidth;
  262. int cellBPD = paddingRectBPD;
  263. cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this);
  264. cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this);
  265. addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, paddingRectBPD);
  266. if (isSeparateBorderModel()) {
  267. if (!emptyCell || getTableCell().showEmptyCells()) {
  268. if (borderBeforeWidth > 0) {
  269. int halfBorderSepBPD = getTableCell().getTable().getBorderSeparation().getBPD()
  270. .getLength().getValue() / 2;
  271. adjustYOffset(curBlockArea, halfBorderSepBPD);
  272. }
  273. TraitSetter.addBorders(curBlockArea,
  274. getTableCell().getCommonBorderPaddingBackground(),
  275. borderBeforeWidth == 0, borderAfterWidth == 0,
  276. false, false, this);
  277. }
  278. } else {
  279. boolean inFirstColumn = (primaryGridUnit.getColIndex() == 0);
  280. boolean inLastColumn = (primaryGridUnit.getColIndex()
  281. + getTableCell().getNumberColumnsSpanned() == getTable()
  282. .getNumberOfColumns());
  283. if (!primaryGridUnit.hasSpanning()) {
  284. adjustYOffset(curBlockArea, -borderBeforeWidth);
  285. //Can set the borders directly if there's no span
  286. boolean[] outer = new boolean[] {firstOnPage, lastOnPage, inFirstColumn,
  287. inLastColumn};
  288. TraitSetter.addCollapsingBorders(curBlockArea,
  289. primaryGridUnit.getBorderBefore(borderBeforeWhich),
  290. primaryGridUnit.getBorderAfter(borderAfterWhich),
  291. primaryGridUnit.getBorderStart(),
  292. primaryGridUnit.getBorderEnd(), outer);
  293. } else {
  294. adjustYOffset(curBlockArea, borderBeforeWidth);
  295. Block[][] blocks = new Block[getTableCell().getNumberRowsSpanned()][getTableCell()
  296. .getNumberColumnsSpanned()];
  297. GridUnit[] gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(startRow);
  298. for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) {
  299. GridUnit gu = gridUnits[x];
  300. BorderInfo border = gu.getBorderBefore(borderBeforeWhich);
  301. int borderWidth = border.getRetainedWidth() / 2;
  302. if (borderWidth > 0) {
  303. addBorder(blocks, startRow, x, Trait.BORDER_BEFORE, border, firstOnPage);
  304. adjustYOffset(blocks[startRow][x], -borderWidth);
  305. adjustBPD(blocks[startRow][x], -borderWidth);
  306. }
  307. }
  308. gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(endRow);
  309. for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) {
  310. GridUnit gu = gridUnits[x];
  311. BorderInfo border = gu.getBorderAfter(borderAfterWhich);
  312. int borderWidth = border.getRetainedWidth() / 2;
  313. if (borderWidth > 0) {
  314. addBorder(blocks, endRow, x, Trait.BORDER_AFTER, border, lastOnPage);
  315. adjustBPD(blocks[endRow][x], -borderWidth);
  316. }
  317. }
  318. for (int y = startRow; y <= endRow; y++) {
  319. gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(y);
  320. BorderInfo border = gridUnits[0].getBorderStart();
  321. int borderWidth = border.getRetainedWidth() / 2;
  322. if (borderWidth > 0) {
  323. addBorder(blocks, y, 0, Trait.BORDER_START, border, inFirstColumn);
  324. adjustXOffset(blocks[y][0], borderWidth);
  325. adjustIPD(blocks[y][0], -borderWidth);
  326. }
  327. border = gridUnits[gridUnits.length - 1].getBorderEnd();
  328. borderWidth = border.getRetainedWidth() / 2;
  329. if (borderWidth > 0) {
  330. addBorder(blocks, y, gridUnits.length - 1, Trait.BORDER_END, border,
  331. inLastColumn);
  332. adjustIPD(blocks[y][gridUnits.length - 1], -borderWidth);
  333. }
  334. }
  335. int dy = yoffset;
  336. for (int y = startRow; y <= endRow; y++) {
  337. int bpd = spannedGridRowHeights[y - startRow];
  338. int dx = xoffset;
  339. for (int x = 0; x < gridUnits.length; x++) {
  340. int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x)
  341. .getColumnWidth().getValue(getParent());
  342. if (blocks[y][x] != null) {
  343. Block block = blocks[y][x];
  344. adjustYOffset(block, dy);
  345. adjustXOffset(block, dx);
  346. adjustIPD(block, ipd);
  347. adjustBPD(block, bpd);
  348. parentLayoutManager.addChildArea(block);
  349. }
  350. dx += ipd;
  351. }
  352. dy += bpd;
  353. }
  354. }
  355. }
  356. TraitSetter.addPadding(curBlockArea,
  357. padding,
  358. borderBeforeWhich == ConditionalBorder.REST,
  359. borderAfterWhich == ConditionalBorder.REST,
  360. false, false, this);
  361. //Handle display-align
  362. if (usedBPD < cellBPD) {
  363. if (getTableCell().getDisplayAlign() == EN_CENTER) {
  364. Block space = new Block();
  365. space.setBPD((cellBPD - usedBPD) / 2);
  366. curBlockArea.addBlock(space);
  367. } else if (getTableCell().getDisplayAlign() == EN_AFTER) {
  368. Block space = new Block();
  369. space.setBPD(cellBPD - usedBPD);
  370. curBlockArea.addBlock(space);
  371. }
  372. }
  373. AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
  374. // Re-adjust the cell's bpd as it may have been modified by the previous call
  375. // for some reason (?)
  376. curBlockArea.setBPD(cellBPD);
  377. // Add background after we know the BPD
  378. if (!isSeparateBorderModel() || !emptyCell || getTableCell().showEmptyCells()) {
  379. TraitSetter.addBackground(curBlockArea,
  380. getTableCell().getCommonBorderPaddingBackground(), this);
  381. }
  382. flush();
  383. curBlockArea = null;
  384. notifyEndOfLayout();
  385. }
  386. /** Adds background areas for the column, body and row, if any. */
  387. private void addBackgroundAreas(RowPainter painter, int firstRowHeight, int borderBeforeWidth,
  388. int paddingRectBPD) {
  389. TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex());
  390. if (column.getCommonBorderPaddingBackground().hasBackground()) {
  391. Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth);
  392. ((TableLayoutManager) parentLayoutManager).registerColumnBackgroundArea(column,
  393. colBackgroundArea, -startIndent);
  394. }
  395. TablePart body = primaryGridUnit.getTablePart();
  396. if (body.getCommonBorderPaddingBackground().hasBackground()) {
  397. painter.registerPartBackgroundArea(
  398. getBackgroundArea(paddingRectBPD, borderBeforeWidth));
  399. }
  400. TableRow row = primaryGridUnit.getRow();
  401. if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) {
  402. Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth);
  403. ((TableLayoutManager) parentLayoutManager).addBackgroundArea(rowBackgroundArea);
  404. TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(),
  405. parentLayoutManager,
  406. -xoffset - startIndent, -borderBeforeWidth,
  407. parentLayoutManager.getContentAreaIPD(), firstRowHeight);
  408. }
  409. }
  410. private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border,
  411. boolean outer) {
  412. if (blocks[i][j] == null) {
  413. blocks[i][j] = new Block();
  414. blocks[i][j].addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
  415. blocks[i][j].setPositioning(Block.ABSOLUTE);
  416. }
  417. blocks[i][j].addTrait(side, new BorderProps(border.getStyle(),
  418. border.getRetainedWidth(), border.getColor(),
  419. outer ? BorderProps.COLLAPSE_OUTER : BorderProps.COLLAPSE_INNER));
  420. }
  421. private static void adjustXOffset(Block block, int amount) {
  422. block.setXOffset(block.getXOffset() + amount);
  423. }
  424. private static void adjustYOffset(Block block, int amount) {
  425. block.setYOffset(block.getYOffset() + amount);
  426. }
  427. private static void adjustIPD(Block block, int amount) {
  428. block.setIPD(block.getIPD() + amount);
  429. }
  430. private static void adjustBPD(Block block, int amount) {
  431. block.setBPD(block.getBPD() + amount);
  432. }
  433. private Block getBackgroundArea(int bpd, int borderBeforeWidth) {
  434. CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground();
  435. int paddingStart = padding.getPaddingStart(false, this);
  436. int paddingEnd = padding.getPaddingEnd(false, this);
  437. Block block = new Block();
  438. TraitSetter.setProducerID(block, getTable().getId());
  439. block.setPositioning(Block.ABSOLUTE);
  440. block.setIPD(cellIPD + paddingStart + paddingEnd);
  441. block.setBPD(bpd);
  442. block.setXOffset(xoffset + startIndent - paddingStart);
  443. block.setYOffset(yoffset + borderBeforeWidth);
  444. return block;
  445. }
  446. /**
  447. * Return an Area which can contain the passed childArea. The childArea
  448. * may not yet have any content, but it has essential traits set.
  449. * In general, if the LayoutManager already has an Area it simply returns
  450. * it. Otherwise, it makes a new Area of the appropriate class.
  451. * It gets a parent area for its area by calling its parent LM.
  452. * Finally, based on the dimensions of the parent area, it initializes
  453. * its own area. This includes setting the content IPD and the maximum
  454. * BPD.
  455. *
  456. * @param childArea the child area to get the parent for
  457. * @return the parent area
  458. */
  459. public Area getParentArea(Area childArea) {
  460. if (curBlockArea == null) {
  461. curBlockArea = new Block();
  462. curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
  463. TraitSetter.setProducerID(curBlockArea, getTableCell().getId());
  464. curBlockArea.setPositioning(Block.ABSOLUTE);
  465. curBlockArea.setXOffset(xoffset + startIndent);
  466. curBlockArea.setYOffset(yoffset);
  467. curBlockArea.setIPD(cellIPD);
  468. /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);
  469. // Get reference IPD from parentArea
  470. setCurrentArea(curBlockArea); // ??? for generic operations
  471. }
  472. return curBlockArea;
  473. }
  474. /**
  475. * Add the child to the cell block area.
  476. *
  477. * @param childArea the child to add to the cell
  478. */
  479. public void addChildArea(Area childArea) {
  480. if (curBlockArea != null) {
  481. curBlockArea.addBlock((Block) childArea);
  482. }
  483. }
  484. /**
  485. * {@inheritDoc}
  486. */
  487. public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
  488. // TODO Auto-generated method stub
  489. return 0;
  490. }
  491. /**
  492. * {@inheritDoc}
  493. */
  494. public void discardSpace(KnuthGlue spaceGlue) {
  495. // TODO Auto-generated method stub
  496. }
  497. /** {@inheritDoc} */
  498. public Keep getKeepTogether() {
  499. // keep-together does not apply to fo:table-cell
  500. return Keep.KEEP_AUTO;
  501. }
  502. /** {@inheritDoc} */
  503. public Keep getKeepWithNext() {
  504. return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!)
  505. }
  506. /** {@inheritDoc} */
  507. public Keep getKeepWithPrevious() {
  508. return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!)
  509. }
  510. // --------- Property Resolution related functions --------- //
  511. /**
  512. * Returns the IPD of the content area
  513. * @return the IPD of the content area
  514. */
  515. public int getContentAreaIPD() {
  516. return cellIPD;
  517. }
  518. /**
  519. * Returns the BPD of the content area
  520. * @return the BPD of the content area
  521. */
  522. public int getContentAreaBPD() {
  523. if (curBlockArea != null) {
  524. return curBlockArea.getBPD();
  525. } else {
  526. log.error("getContentAreaBPD called on unknown BPD");
  527. return -1;
  528. }
  529. }
  530. /**
  531. * {@inheritDoc}
  532. */
  533. public boolean getGeneratesReferenceArea() {
  534. return true;
  535. }
  536. /**
  537. * {@inheritDoc}
  538. */
  539. public boolean getGeneratesBlockArea() {
  540. return true;
  541. }
  542. }