您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * $Id: Row.java,v 1.14 2003/03/07 07:58:51 jeremias Exp $
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. package org.apache.fop.layoutmgr.table;
  52. import org.apache.fop.fo.PropertyManager;
  53. import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
  54. import org.apache.fop.layoutmgr.LayoutProcessor;
  55. import org.apache.fop.layoutmgr.LeafPosition;
  56. import org.apache.fop.layoutmgr.BreakPoss;
  57. import org.apache.fop.layoutmgr.LayoutContext;
  58. import org.apache.fop.layoutmgr.PositionIterator;
  59. import org.apache.fop.layoutmgr.BreakPossPosIter;
  60. import org.apache.fop.layoutmgr.Position;
  61. import org.apache.fop.layoutmgr.TraitSetter;
  62. import org.apache.fop.area.Area;
  63. import org.apache.fop.area.Block;
  64. import org.apache.fop.traits.MinOptMax;
  65. import org.apache.fop.fo.properties.CommonBorderAndPadding;
  66. import org.apache.fop.fo.properties.CommonBackground;
  67. import java.util.Iterator;
  68. import java.util.ArrayList;
  69. import java.util.List;
  70. /**
  71. * LayoutManager for a table-row FO.
  72. * The row contains cells that are organised according to the columns.
  73. * A break in a table row will contain breaks for each table cell.
  74. * If there are row spanning cells then these cells belong to this row
  75. * but effect the occupied columns of future rows.
  76. */
  77. public class Row extends BlockStackingLayoutManager {
  78. private List cellList = null;
  79. private List columns = null;
  80. private int rowHeight;
  81. private int yoffset;
  82. private CommonBorderAndPadding borderProps = null;
  83. private CommonBackground backgroundProps;
  84. private class RowPosition extends LeafPosition {
  85. protected List cellBreaks;
  86. protected RowPosition(LayoutProcessor lm, int pos, List l) {
  87. super(lm, pos);
  88. cellBreaks = l;
  89. }
  90. }
  91. /**
  92. * Create a new row layout manager.
  93. *
  94. */
  95. public Row() {
  96. }
  97. /**
  98. * Initialize properties for this layout manager.
  99. *
  100. * @param propMgr the property manager for the fo
  101. */
  102. protected void initProperties(PropertyManager propMgr) {
  103. borderProps = propMgr.getBorderAndPadding();
  104. backgroundProps = propMgr.getBackgroundProps();
  105. }
  106. /**
  107. * Set the columns from the table.
  108. *
  109. * @param cols the list of columns for this table
  110. */
  111. public void setColumns(List cols) {
  112. columns = cols;
  113. }
  114. private void setupCells() {
  115. cellList = new ArrayList();
  116. // add cells to list
  117. while (childLMiter.hasNext()) {
  118. curChildLM = (LayoutProcessor) childLMiter.next();
  119. curChildLM.setUserAgent(getUserAgent());
  120. curChildLM.setParent(this);
  121. curChildLM.init();
  122. cellList.add(curChildLM);
  123. }
  124. }
  125. /**
  126. * Get the layout manager for a cell.
  127. *
  128. * @param pos the position of the cell
  129. * @return the cell layout manager
  130. */
  131. protected Cell getCellLM(int pos) {
  132. if (cellList == null) {
  133. setupCells();
  134. }
  135. if (pos < cellList.size()) {
  136. return (Cell)cellList.get(pos);
  137. }
  138. return null;
  139. }
  140. /**
  141. * Get the next break possibility.
  142. * A row needs to get the possible breaks for each cell
  143. * in the row and find a suitable break across all cells.
  144. *
  145. * @param context the layout context for getting breaks
  146. * @return the next break possibility
  147. */
  148. public BreakPoss getNextBreakPoss(LayoutContext context) {
  149. LayoutProcessor curLM; // currently active LM
  150. BreakPoss lastPos = null;
  151. List breakList = new ArrayList();
  152. int min = 0;
  153. int opt = 0;
  154. int max = 0;
  155. int cellcount = 0;
  156. boolean over = false;
  157. while ((curLM = getCellLM(cellcount++)) != null) {
  158. List childBreaks = new ArrayList();
  159. MinOptMax stackSize = new MinOptMax();
  160. // Set up a LayoutContext
  161. // the ipd is from the current column
  162. int ipd = context.getRefIPD();
  163. BreakPoss bp;
  164. LayoutContext childLC = new LayoutContext(0);
  165. childLC.setStackLimit(
  166. MinOptMax.subtract(context.getStackLimit(),
  167. stackSize));
  168. int size = columns.size();
  169. Column col;
  170. if (cellcount > size - 1) {
  171. col = (Column)columns.get(size - 1);
  172. } else {
  173. col = (Column)columns.get(cellcount - 1);
  174. }
  175. childLC.setRefIPD(col.getWidth().getValue());
  176. while (!curLM.isFinished()) {
  177. if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
  178. if (stackSize.opt + bp.getStackingSize().opt > context.getStackLimit().max) {
  179. // reset to last break
  180. if (lastPos != null) {
  181. LayoutProcessor lm = lastPos.getLayoutManager();
  182. lm.resetPosition(lastPos.getPosition());
  183. if (lm != curLM) {
  184. curLM.resetPosition(null);
  185. }
  186. } else {
  187. curLM.resetPosition(null);
  188. }
  189. over = true;
  190. break;
  191. }
  192. stackSize.add(bp.getStackingSize());
  193. lastPos = bp;
  194. childBreaks.add(bp);
  195. if (bp.nextBreakOverflows()) {
  196. over = true;
  197. break;
  198. }
  199. childLC.setStackLimit(MinOptMax.subtract(
  200. context.getStackLimit(), stackSize));
  201. }
  202. }
  203. // the min is the maximum min of all cells
  204. if (stackSize.min > min) {
  205. min = stackSize.min;
  206. }
  207. // the optimum is the maximum of all optimums
  208. if (stackSize.opt > opt) {
  209. opt = stackSize.opt;
  210. }
  211. // the maximum is the largest maximum
  212. if (stackSize.max > max) {
  213. max = stackSize.max;
  214. }
  215. breakList.add(childBreaks);
  216. }
  217. rowHeight = opt;
  218. MinOptMax rowSize = new MinOptMax(min, opt, max);
  219. boolean fin = true;
  220. cellcount = 0;
  221. while ((curLM = getCellLM(cellcount++)) != null) {
  222. if (!curLM.isFinished()) {
  223. fin = false;
  224. break;
  225. }
  226. }
  227. setFinished(fin);
  228. RowPosition rp = new RowPosition(this, breakList.size() - 1, breakList);
  229. BreakPoss breakPoss = new BreakPoss(rp);
  230. if (over) {
  231. breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true);
  232. }
  233. breakPoss.setStackingSize(rowSize);
  234. return breakPoss;
  235. }
  236. /**
  237. * Reset the layoutmanager "iterator" so that it will start
  238. * with the passed Position's generating LM
  239. * on the next call to getChildLM.
  240. * @param pos a Position returned by a child layout manager
  241. * representing a potential break decision.
  242. * If pos is null, then back up to the first child LM.
  243. */
  244. protected void reset(Position pos) {
  245. LayoutProcessor curLM; // currently active LM
  246. int cellcount = 0;
  247. if (pos == null) {
  248. while ((curLM = getCellLM(cellcount)) != null) {
  249. curLM.resetPosition(null);
  250. cellcount++;
  251. }
  252. } else {
  253. RowPosition rpos = (RowPosition)pos;
  254. List breaks = rpos.cellBreaks;
  255. while ((curLM = getCellLM(cellcount)) != null) {
  256. List childbreaks = (List)breaks.get(cellcount);
  257. curLM.resetPosition((Position)childbreaks.get(childbreaks.size() - 1));
  258. cellcount++;
  259. }
  260. }
  261. setFinished(false);
  262. }
  263. /**
  264. * Set the y position offset of this row.
  265. * This is used to set the position of the areas returned by this row.
  266. *
  267. * @param off the y offset
  268. */
  269. public void setYOffset(int off) {
  270. yoffset = off;
  271. }
  272. /**
  273. * Add the areas for the break points.
  274. * This sets the offset of each cell as it is added.
  275. *
  276. * @param parentIter the position iterator
  277. * @param layoutContext the layout context for adding areas
  278. */
  279. public void addAreas(PositionIterator parentIter,
  280. LayoutContext layoutContext) {
  281. getParentArea(null);
  282. addID();
  283. Cell childLM;
  284. int iStartPos = 0;
  285. LayoutContext lc = new LayoutContext(0);
  286. while (parentIter.hasNext()) {
  287. RowPosition lfp = (RowPosition) parentIter.next();
  288. // Add the block areas to Area
  289. int cellcount = 0;
  290. int xoffset = 0;
  291. for (Iterator iter = lfp.cellBreaks.iterator(); iter.hasNext();) {
  292. List cellsbr = (List)iter.next();
  293. PositionIterator breakPosIter;
  294. breakPosIter = new BreakPossPosIter(cellsbr, 0, cellsbr.size());
  295. iStartPos = lfp.getLeafPos() + 1;
  296. int size = columns.size();
  297. Column col;
  298. if (cellcount > size - 1) {
  299. col = (Column)columns.get(size - 1);
  300. } else {
  301. col = (Column)columns.get(cellcount);
  302. cellcount++;
  303. }
  304. while ((childLM = (Cell)breakPosIter.getNextChildLM()) != null) {
  305. childLM.setXOffset(xoffset);
  306. childLM.setYOffset(yoffset);
  307. childLM.setRowHeight(rowHeight);
  308. childLM.addAreas(breakPosIter, lc);
  309. }
  310. xoffset += col.getWidth().getValue();
  311. }
  312. }
  313. flush();
  314. }
  315. /**
  316. * Get the row height of the row after adjusting.
  317. * Should only be called after adding the row areas.
  318. *
  319. * @return the row height of this row after adjustment
  320. */
  321. public int getRowHeight() {
  322. return rowHeight;
  323. }
  324. /**
  325. * Return an Area which can contain the passed childArea. The childArea
  326. * may not yet have any content, but it has essential traits set.
  327. * In general, if the LayoutManager already has an Area it simply returns
  328. * it. Otherwise, it makes a new Area of the appropriate class.
  329. * It gets a parent area for its area by calling its parent LM.
  330. * Finally, based on the dimensions of the parent area, it initializes
  331. * its own area. This includes setting the content IPD and the maximum
  332. * BPD.
  333. *
  334. * @param childArea the child area
  335. * @return the parent are for the child
  336. */
  337. public Area getParentArea(Area childArea) {
  338. return parentLM.getParentArea(childArea);
  339. }
  340. /**
  341. * Add the child.
  342. * Rows return the areas returned by the child elements.
  343. * This simply adds the area to the parent layout manager.
  344. *
  345. * @param childArea the child area
  346. */
  347. public void addChild(Area childArea) {
  348. parentLM.addChild(childArea);
  349. }
  350. /**
  351. * Reset the position of this layout manager.
  352. *
  353. * @param resetPos the position to reset to
  354. */
  355. public void resetPosition(Position resetPos) {
  356. if (resetPos == null) {
  357. reset(null);
  358. }
  359. }
  360. /**
  361. * Get the area for this row for background.
  362. *
  363. * @return the row area
  364. */
  365. public Area getRowArea() {
  366. Area block = new Block();
  367. if (backgroundProps != null) {
  368. TraitSetter.addBackground(block, backgroundProps);
  369. }
  370. return block;
  371. }
  372. }