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 26KB

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