001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: TableAndCaptionLayoutManager.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.layoutmgr.table;
021:
022: import org.apache.fop.fo.flow.TableAndCaption;
023: import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
024: import org.apache.fop.layoutmgr.LayoutContext;
025: import org.apache.fop.layoutmgr.PositionIterator;
026: import org.apache.fop.layoutmgr.Position;
027: import org.apache.fop.area.Area;
028: import org.apache.fop.area.Block;
029:
030: /**
031: * LayoutManager for a table-and-caption FO.
032: * A table and caption consists of a table and a caption.
033: * The caption contains blocks that are positioned next to the
034: * table on the caption side.
035: * The caption blocks have an implicit keep with the table.
036: * @todo Implement getNextKnuthElements()
037: */
038: public class TableAndCaptionLayoutManager extends
039: BlockStackingLayoutManager {
040: private TableAndCaption fobj;
041:
042: private Block curBlockArea;
043:
044: //private List childBreaks = new java.util.ArrayList();
045:
046: /**
047: * Create a new table and caption layout manager.
048: * @param node table-and-caption FO
049: */
050: public TableAndCaptionLayoutManager(TableAndCaption node) {
051: super (node);
052: fobj = node;
053: }
054:
055: /**
056: * Get the next break possibility.
057: *
058: * @param context the layout context for getting breaks
059: * @return the next break possibility
060: */
061: /*
062: public BreakPoss getNextBreakPoss(LayoutContext context) {
063: LayoutManager curLM; // currently active LM
064:
065: MinOptMax stackSize = new MinOptMax();
066: // if starting add space before
067: // stackSize.add(spaceBefore);
068: BreakPoss lastPos = null;
069:
070: // if there is a caption then get the side and work out when
071: // to handle it
072:
073: while ((curLM = getChildLM()) != null) {
074: // Make break positions and return blocks!
075: // Set up a LayoutContext
076: int ipd = context.getRefIPD();
077: BreakPoss bp;
078:
079: LayoutContext childLC = new LayoutContext(0);
080: // if line layout manager then set stack limit to ipd
081: // line LM actually generates a LineArea which is a block
082: childLC.setStackLimit(
083: MinOptMax.subtract(context.getStackLimit(),
084: stackSize));
085: childLC.setRefIPD(ipd);
086:
087: boolean over = false;
088: while (!curLM.isFinished()) {
089: if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
090: if (stackSize.opt + bp.getStackingSize().opt > context.getStackLimit().max) {
091: // reset to last break
092: if (lastPos != null) {
093: LayoutManager lm = lastPos.getLayoutManager();
094: lm.resetPosition(lastPos.getPosition());
095: if (lm != curLM) {
096: curLM.resetPosition(null);
097: }
098: } else {
099: curLM.resetPosition(null);
100: }
101: over = true;
102: break;
103: }
104: stackSize.add(bp.getStackingSize());
105: lastPos = bp;
106: childBreaks.add(bp);
107:
108: if (bp.nextBreakOverflows()) {
109: over = true;
110: break;
111: }
112:
113: childLC.setStackLimit(MinOptMax.subtract(
114: context.getStackLimit(), stackSize));
115: }
116: }
117: BreakPoss breakPoss = new BreakPoss(
118: new LeafPosition(this, childBreaks.size() - 1));
119: if (over) {
120: breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true);
121: }
122: breakPoss.setStackingSize(stackSize);
123: return breakPoss;
124: }
125: setFinished(true);
126: return null;
127: }*/
128:
129: /**
130: * Add the areas.
131: *
132: * @param parentIter the position iterator
133: * @param layoutContext the layout context for adding areas
134: */
135: public void addAreas(PositionIterator parentIter,
136: LayoutContext layoutContext) {
137: getParentArea(null);
138: getPSLM().addIDToPage(fobj.getId());
139:
140: /* TODO: Reimplement using Knuth approach
141: LayoutManager childLM;
142: int iStartPos = 0;
143: LayoutContext lc = new LayoutContext(0);
144: while (parentIter.hasNext()) {
145: LeafPosition lfp = (LeafPosition) parentIter.next();
146: // Add the block areas to Area
147: PositionIterator breakPosIter = new BreakPossPosIter(
148: childBreaks, iStartPos, lfp.getLeafPos() + 1);
149: iStartPos = lfp.getLeafPos() + 1;
150: while ((childLM = breakPosIter.getNextChildLM()) != null) {
151: childLM.addAreas(breakPosIter, lc);
152: }
153: }*/
154:
155: flush();
156:
157: //childBreaks.clear();
158: curBlockArea = null;
159: }
160:
161: /**
162: * Return an Area which can contain the passed childArea. The childArea
163: * may not yet have any content, but it has essential traits set.
164: * In general, if the LayoutManager already has an Area it simply returns
165: * it. Otherwise, it makes a new Area of the appropriate class.
166: * It gets a parent area for its area by calling its parent LM.
167: * Finally, based on the dimensions of the parent area, it initializes
168: * its own area. This includes setting the content IPD and the maximum
169: * BPD.
170: *
171: * @param childArea the child area to locate the parent
172: * @return the area for this table and caption
173: */
174: public Area getParentArea(Area childArea) {
175: if (curBlockArea == null) {
176: curBlockArea = new Block();
177: // Set up dimensions
178: // Must get dimensions from parent area
179: Area parentArea = parentLM.getParentArea(curBlockArea);
180: int referenceIPD = parentArea.getIPD();
181: curBlockArea.setIPD(referenceIPD);
182: // Get reference IPD from parentArea
183: setCurrentArea(curBlockArea); // ??? for generic operations
184: }
185: return curBlockArea;
186: }
187:
188: /**
189: * Add the child to the current area.
190: *
191: * @param childArea the area to add
192: */
193: public void addChildArea(Area childArea) {
194: if (curBlockArea != null) {
195: curBlockArea.addBlock((Block) childArea);
196: }
197: }
198:
199: /**
200: * Reset the position of this layout manager.
201: *
202: * @param resetPos the position to reset to
203: */
204: public void resetPosition(Position resetPos) {
205: if (resetPos == null) {
206: reset(null);
207: }
208: }
209: }
|