aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/apache/fop/layoutmgr
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/apache/fop/layoutmgr')
-rw-r--r--src/org/apache/fop/layoutmgr/AbstractLayoutManager.java61
-rw-r--r--src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java24
-rw-r--r--src/org/apache/fop/layoutmgr/BlockLayoutManager.java9
-rw-r--r--src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java7
-rw-r--r--src/org/apache/fop/layoutmgr/BreakPossPosIter.java2
-rw-r--r--src/org/apache/fop/layoutmgr/ContentLayoutManager.java10
-rw-r--r--src/org/apache/fop/layoutmgr/FlowLayoutManager.java11
-rw-r--r--src/org/apache/fop/layoutmgr/LayoutManager.java49
-rw-r--r--src/org/apache/fop/layoutmgr/PageLayoutManager.java13
-rw-r--r--src/org/apache/fop/layoutmgr/PositionIterator.java2
-rw-r--r--src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java22
-rw-r--r--src/org/apache/fop/layoutmgr/table/Body.java213
-rw-r--r--src/org/apache/fop/layoutmgr/table/Caption.java190
-rw-r--r--src/org/apache/fop/layoutmgr/table/Cell.java215
-rw-r--r--src/org/apache/fop/layoutmgr/table/Column.java92
-rw-r--r--src/org/apache/fop/layoutmgr/table/Row.java277
-rw-r--r--src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java192
-rw-r--r--src/org/apache/fop/layoutmgr/table/TableLayoutManager.java291
18 files changed, 1634 insertions, 46 deletions
diff --git a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java
index 519eaade8..34682b143 100644
--- a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java
@@ -8,14 +8,12 @@
package org.apache.fop.layoutmgr;
import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.FONode;
import org.apache.fop.area.Area;
import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.PropertyManager;
import java.util.ListIterator;
-import java.util.ArrayList;
/**
* The base class for all LayoutManagers.
@@ -106,18 +104,10 @@ public abstract class AbstractLayoutManager implements LayoutManager {
return m_curChildLM;
}
while (m_childLMiter.hasNext()) {
- Object obj = m_childLMiter.next();
- if (obj instanceof LayoutManager) {
- m_curChildLM = (LayoutManager) obj;
- m_curChildLM.setParentLM(this);
- m_curChildLM.init();
- return m_curChildLM;
- } else {
- m_childLMiter.remove();
- //log.warn(
- // "child LM not a LayoutManager: " +
- // obj.getClass().getName());
- }
+ m_curChildLM = (LayoutManager) m_childLMiter.next();
+ m_curChildLM.setParentLM(this);
+ m_curChildLM.init();
+ return m_curChildLM;
}
return null;
}
@@ -257,26 +247,69 @@ public abstract class AbstractLayoutManager implements LayoutManager {
return false;
}
+ /**
+ * Delegate getting the current page number to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
public String getCurrentPageNumber() {
return parentLM.getCurrentPageNumber();
}
+ /**
+ * Delegate resolving the id reference to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
public PageViewport resolveRefID(String ref) {
return parentLM.resolveRefID(ref);
}
+ /**
+ * Add the id to the page.
+ * If the id string is not null then add the id to the current page.
+ */
protected void addID() {
if(foID != null) {
addIDToPage(foID);
}
}
+ /**
+ * Delegate adding id reference to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
public void addIDToPage(String id) {
parentLM.addIDToPage(id);
}
+ /**
+ * Delegate adding unresolved area to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
public void addUnresolvedArea(String id, Resolveable res) {
parentLM.addUnresolvedArea(id, res);
}
+
+ /**
+ * Delegate adding marker to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
+ public void addMarker(String name, LayoutManager lm, boolean start) {
+ parentLM.addMarker(name, lm, start);
+ }
+
+ /**
+ * Delegate retrieve marker to the parent layout manager.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
+ public LayoutManager retrieveMarker(String name, int pos, int boundary) {
+ return parentLM.retrieveMarker(name, pos, boundary);
+ }
+
}
diff --git a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
index 4c6ea73ff..dbca5cdd0 100644
--- a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
@@ -231,27 +231,26 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager {
if (curBlockArea == null) {
viewportBlockArea = new BlockViewport();
if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) {
- Rectangle2D rect = new Rectangle2D.Double(abProps.left,
- abProps.top, abProps.right - abProps.left,
- abProps.bottom - abProps.top);
- viewportBlockArea.setBounds(rect);
+ viewportBlockArea.setXOffset(abProps.left);
+ viewportBlockArea.setYOffset(abProps.top);
+ viewportBlockArea.setWidth(abProps.right - abProps.left);
+ viewportBlockArea.setHeight(abProps.bottom - abProps.top);
+
viewportBlockArea.setCTM(absoluteCTM);
viewportBlockArea.setClip(clip);
} else {
double[] vals = absoluteCTM.toArray();
boolean rotated = vals[0] == 0.0;
if(rotated) {
- Rectangle2D rect = new Rectangle2D.Double(0, 0,
- relDims.bpd, getRotatedIPD());
- viewportBlockArea.setBounds(rect);
+ viewportBlockArea.setWidth(relDims.bpd);
+ viewportBlockArea.setHeight(getRotatedIPD());
viewportBlockArea.setCTM(absoluteCTM);
viewportBlockArea.setClip(clip);
} else if(vals[0] == -1.0) {
// need to set bpd to actual size for rotation
// and stacking
- Rectangle2D rect = new Rectangle2D.Double(0, 0,
- relDims.ipd, relDims.bpd);
- viewportBlockArea.setBounds(rect);
+ viewportBlockArea.setWidth(relDims.ipd);
+ viewportBlockArea.setWidth(relDims.bpd);
viewportBlockArea.setCTM(absoluteCTM);
viewportBlockArea.setClip(clip);
}
@@ -289,5 +288,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager {
reset(null);
}
}
+
+ public void addMarker(String name, LayoutManager lm, boolean start) {
+ parentLM.addMarker(name, lm, start);
+ }
+
}
diff --git a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
index bf507a965..ec6e58c18 100644
--- a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -211,20 +211,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager {
public boolean addChild(Area childArea) {
if (curBlockArea != null) {
if (childArea instanceof LineArea) {
- // Something about widows and orphans
- // Position the line area and calculate size...
curBlockArea.addLineArea((LineArea) childArea);
- MinOptMax targetDim = parentArea.getAvailBPD();
- MinOptMax currentDim = curBlockArea.getContentBPD();
- //if(currentDim.min > targetDim.max) {
- // return true;
- //}
-
return false;
} else {
curBlockArea.addBlock((Block) childArea);
- //return super.addChild(childArea);
return false;
}
diff --git a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
index 1b091a662..249500931 100644
--- a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
@@ -1,6 +1,6 @@
/*
* $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
@@ -48,8 +48,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager {
this.parentArea = parentArea;
}
-
-
protected MinOptMax resolveSpaceSpecifier(Area nextArea) {
SpaceSpecifier spaceSpec = new SpaceSpecifier(false);
// Area prevArea = getCurrentArea().getLast();
@@ -126,8 +124,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager {
* Force current area to be added to parent area.
*/
protected boolean flush() {
- if (getCurrentArea() != null)
+ if (getCurrentArea() != null) {
return parentLM.addChild(getCurrentArea());
+ }
return false;
}
diff --git a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
index b9342b28c..9d9eaf5d5 100644
--- a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
+++ b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
@@ -13,7 +13,7 @@ import java.util.List;
public class BreakPossPosIter extends PositionIterator {
private int m_iterCount ;
- BreakPossPosIter(List bpList, int startPos, int endPos) {
+ public BreakPossPosIter(List bpList, int startPos, int endPos) {
super(bpList.listIterator(startPos));
m_iterCount = endPos - startPos;
}
diff --git a/src/org/apache/fop/layoutmgr/ContentLayoutManager.java b/src/org/apache/fop/layoutmgr/ContentLayoutManager.java
index 7ca005c0c..a27d7f120 100644
--- a/src/org/apache/fop/layoutmgr/ContentLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/ContentLayoutManager.java
@@ -178,5 +178,15 @@ public class ContentLayoutManager implements LayoutManager {
public void addUnresolvedArea(String id, Resolveable res) {
parentLM.addUnresolvedArea(id, res);
}
+
+ /** @see org.apache.fop.layoutmgr.LayoutManager */
+ public void addMarker(String name, LayoutManager lm, boolean start) {
+ parentLM.addMarker(name, lm, start);
+ }
+
+ /** @see org.apache.fop.layoutmgr.LayoutManager */
+ public LayoutManager retrieveMarker(String name, int pos, int boundary) {
+ return parentLM.retrieveMarker(name, pos, boundary);
+ }
}
diff --git a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java
index 4b12bd385..4d4dc0e02 100644
--- a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java
@@ -138,5 +138,16 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
reset(null);
}
}
+
+ /**
+ * Retrieve marker is not allowed in the flow so this reports an
+ * error and returns null.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
+ public LayoutManager retrieveMarker(String name, int pos, int boundary) {
+ // error cannot retrieve markers in flow
+ return null;
+ }
}
diff --git a/src/org/apache/fop/layoutmgr/LayoutManager.java b/src/org/apache/fop/layoutmgr/LayoutManager.java
index cac65a075..664730fd9 100644
--- a/src/org/apache/fop/layoutmgr/LayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/LayoutManager.java
@@ -64,11 +64,60 @@ public interface LayoutManager {
public void getWordChars(StringBuffer sbChars, Position bp1,
Position bp2);
+ /**
+ * Get the string of the current page number.
+ *
+ * @return the string for the current page number
+ */
public String getCurrentPageNumber();
+ /**
+ * Resolve the id reference.
+ * This is called by an area looking for an id reference.
+ * If the id reference is not found then it should add a resolveable object.
+ *
+ * @param ref the id reference
+ * @return the page containing the id reference or null if not found
+ */
public PageViewport resolveRefID(String ref);
+ /**
+ * Add an id to the page.
+ * @todo add the location of the area on the page
+ *
+ * @param id the id reference to add.
+ */
public void addIDToPage(String id);
+ /**
+ * Add an unresolved area.
+ * The is used to add a resolveable object to the page for a given id.
+ *
+ * @param id the id reference this object needs for resolving
+ * @param res the resolveable object
+ */
public void addUnresolvedArea(String id, Resolveable res);
+
+ /**
+ * Add the marker.
+ * A number of formatting objects may contain markers. This
+ * method is used to add those markers to the page.
+ *
+ * @param name the marker class name
+ * @param lm the layout manager of the marker child
+ * @param start true if the formatting object is starting false is finishing
+ */
+ public void addMarker(String name, LayoutManager lm, boolean start);
+
+ /**
+ * Retrieve a marker.
+ * This method is used when retrieve a marker.
+ *
+ * @param name the class name of the marker
+ * @param pos the retrieve position
+ * @param boundary the boundary for retrieving the marker
+ * @return the layout manaager of the retrieved marker if any
+ */
+ public LayoutManager retrieveMarker(String name, int pos, int boundary);
+
}
diff --git a/src/org/apache/fop/layoutmgr/PageLayoutManager.java b/src/org/apache/fop/layoutmgr/PageLayoutManager.java
index a1a09d6f7..c22bc589e 100644
--- a/src/org/apache/fop/layoutmgr/PageLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/PageLayoutManager.java
@@ -164,6 +164,19 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable
areaTree.addUnresolvedID(id, curPage);
}
+ public void addMarker(String name, LayoutManager lm, boolean start) {
+ if(start) {
+ // add marker to page on area tree
+ } else {
+ // add end marker to page on area tree
+ }
+ }
+
+ public LayoutManager retrieveMarker(String name, int pos, int boundary) {
+ // get marker from the current markers on area tree
+ return null;
+ }
+
/**
* For now, only handle normal flow areas.
*/
diff --git a/src/org/apache/fop/layoutmgr/PositionIterator.java b/src/org/apache/fop/layoutmgr/PositionIterator.java
index 66d5e3a3e..5e951a09f 100644
--- a/src/org/apache/fop/layoutmgr/PositionIterator.java
+++ b/src/org/apache/fop/layoutmgr/PositionIterator.java
@@ -23,7 +23,7 @@ public abstract class PositionIterator implements Iterator {
//checkNext();
}
- LayoutManager getNextChildLM() {
+ public LayoutManager getNextChildLM() {
// Move to next "segment" of iterator, ie: new childLM
if (m_childLM == null && m_nextObj != null) {
m_childLM = getLM(m_nextObj);
diff --git a/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
index 9932e1a45..b4c673e74 100644
--- a/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
@@ -1,19 +1,18 @@
/*
* $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
package org.apache.fop.layoutmgr;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.properties.Constants;
-import org.apache.fop.area.*;
+import org.apache.fop.area.RegionReference;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
import java.util.ArrayList;
-import java.util.List;
/**
* LayoutManager for an fo:flow object.
@@ -24,7 +23,7 @@ import java.util.List;
public class StaticContentLayoutManager extends BlockStackingLayoutManager {
private RegionReference region;
- ArrayList blockBreaks = new ArrayList();
+ private ArrayList blockBreaks = new ArrayList();
public StaticContentLayoutManager(FObj fobj) {
super(fobj);
@@ -46,7 +45,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
if (!curLM.isFinished()) {
if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
blockBreaks.add(bp);
- if(bp.isForcedBreak()) {
+ if (bp.isForcedBreak()) {
System.out.println("Forced breaks are not allowed in static content");
return null;
}
@@ -98,5 +97,14 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
return region;
}
+ /**
+ * Markers are not allowed in static areas so this reports an
+ * error and does nothing.
+ *
+ * @see org.apache.fop.layoutmgr.LayoutManager
+ */
+ public void addMarker(String name, LayoutManager lm, boolean start) {
+ // error markers not allowed in static
+ }
}
diff --git a/src/org/apache/fop/layoutmgr/table/Body.java b/src/org/apache/fop/layoutmgr/table/Body.java
new file mode 100644
index 000000000..902c14bea
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/Body.java
@@ -0,0 +1,213 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LayoutManager for a table-header, table-footer and table body FO.
+ * These fo objects have either rows or cells underneath.
+ * Cells are organised into rows.
+ */
+public class Body extends BlockStackingLayoutManager {
+
+ private boolean rows = true;
+ private List columns;
+
+ private int yoffset;
+ private int bodyHeight;
+
+ private Block curBlockArea;
+
+ private ArrayList childBreaks = new ArrayList();
+
+ /**
+ * Create a new body layout manager.
+ *
+ * @param fobj the formatting object that created this manager
+ */
+ public Body(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Set the columns from the table.
+ *
+ * @param cols the list of columns used for this body
+ */
+ public void setColumns(List cols) {
+ columns = cols;
+ }
+
+ /**
+ * Breaks for this layout manager are of the form of before
+ * or after a row and inside a row.
+ *
+ * @param context the layout context for finding the breaks
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ Row curLM; // currently active LM
+
+ MinOptMax stackSize = new MinOptMax();
+ BreakPoss lastPos = null;
+
+ while ((curLM = (Row)getChildLM()) != null) {
+ // Make break positions
+ // Set up a LayoutContext
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimit(
+ MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+ childLC.setRefIPD(ipd);
+
+ curLM.setColumns(columns);
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ childBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new LeafPosition(this, childBreaks.size() - 1));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+ }
+
+ setFinished(true);
+ return null;
+ }
+
+ /**
+ * Set the y offset of this body within the table.
+ * This is used to set the row offsets.
+ *
+ * @param off the y offset position
+ */
+ public void setYOffset(int off) {
+ yoffset = off;
+ }
+
+ /**
+ * Add the areas for the break points.
+ * This sets the offset of each row as it is added.
+ *
+ * @param parentIter the position iterator
+ * @param layoutContext the layout context for adding areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ Row childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ int rowoffset = 0;
+ while (parentIter.hasNext()) {
+ LeafPosition lfp = (LeafPosition) parentIter.next();
+ // Add the block areas to Area
+ PositionIterator breakPosIter =
+ new BreakPossPosIter(childBreaks, iStartPos,
+ lfp.getLeafPos() + 1);
+ iStartPos = lfp.getLeafPos() + 1;
+ while ((childLM = (Row)breakPosIter.getNextChildLM()) != null) {
+ childLM.setYOffset(yoffset + rowoffset);
+ childLM.addAreas(breakPosIter, lc);
+ rowoffset += childLM.getRowHeight();
+ }
+ }
+ bodyHeight = rowoffset;
+
+ flush();
+
+ childBreaks.clear();
+ curBlockArea = null;
+ }
+
+ /**
+ * Get the body height of the body after adjusting.
+ * Should only be called after adding the body areas.
+ *
+ * @return the body height of this body
+ */
+ public int getBodyHeight() {
+ return bodyHeight;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area
+ * @return the parent are of the child
+ */
+ public Area getParentArea(Area childArea) {
+ return parentLM.getParentArea(childArea);
+ }
+
+ /**
+ * Add the child area.
+ * The table-header, table-footer and table-body areas return
+ * the areas return by the children.
+ *
+ * @param childArea the child area to add
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ return parentLM.addChild(childArea);
+ }
+
+ /**
+ * Reset the position of the layout manager.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/Caption.java b/src/org/apache/fop/layoutmgr/table/Caption.java
new file mode 100644
index 000000000..4e310034c
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/Caption.java
@@ -0,0 +1,190 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.ArrayList;
+
+/**
+ * LayoutManager for a table-caption FO.
+ * The table caption contains blocks that are placed beside the
+ * table.
+ */
+public class Caption extends BlockStackingLayoutManager {
+
+ private Block curBlockArea;
+
+ private ArrayList childBreaks = new ArrayList();
+
+ /**
+ * Create a new Caption layout manager.
+ *
+ * @param fobj the formatting object that created this manager
+ */
+ public Caption(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Get the next break position for the caption.
+ *
+ * @param context the layout context for finding breaks
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ LayoutManager curLM; // currently active LM
+
+ MinOptMax stackSize = new MinOptMax();
+ // if starting add space before
+ // stackSize.add(spaceBefore);
+ BreakPoss lastPos = null;
+
+ // if there is a caption then get the side and work out when
+ // to handle it
+
+ while ((curLM = getChildLM()) != null) {
+ // Make break positions and return blocks!
+ // Set up a LayoutContext
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ // if line layout manager then set stack limit to ipd
+ // line LM actually generates a LineArea which is a block
+ childLC.setStackLimit(
+ MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+ childLC.setRefIPD(ipd);
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ childBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new LeafPosition(this, childBreaks.size() - 1));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+ }
+ setFinished(true);
+ return null;
+ }
+
+ /**
+ * Add the areas to the parent.
+ *
+ * @param parentIter the position iterator of the breaks
+ * @param layoutContext the layout context for adding areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ LayoutManager childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ while (parentIter.hasNext()) {
+ LeafPosition lfp = (LeafPosition) parentIter.next();
+ // Add the block areas to Area
+ PositionIterator breakPosIter =
+ new BreakPossPosIter(childBreaks, iStartPos,
+ lfp.getLeafPos() + 1);
+ iStartPos = lfp.getLeafPos() + 1;
+ while ((childLM = breakPosIter.getNextChildLM()) != null) {
+ childLM.addAreas(breakPosIter, lc);
+ }
+ }
+
+ flush();
+
+ childBreaks.clear();
+ curBlockArea = null;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area
+ * @return the parent area from this caption
+ */
+ public Area getParentArea(Area childArea) {
+ if (curBlockArea == null) {
+ curBlockArea = new Block();
+ // Set up dimensions
+ // Must get dimensions from parent area
+ Area parentArea = parentLM.getParentArea(curBlockArea);
+ int referenceIPD = parentArea.getIPD();
+ curBlockArea.setIPD(referenceIPD);
+ // Get reference IPD from parentArea
+ setCurrentArea(curBlockArea); // ??? for generic operations
+ }
+ return curBlockArea;
+ }
+
+ /**
+ * Add the child to the caption area.
+ *
+ * @param childArea the child area to add
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ if (curBlockArea != null) {
+ curBlockArea.addBlock((Block) childArea);
+ //return super.addChild(childArea);
+
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Reset the layout position.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/Cell.java b/src/org/apache/fop/layoutmgr/table/Cell.java
new file mode 100644
index 000000000..57dd6b2cf
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/Cell.java
@@ -0,0 +1,215 @@
+/*
+ * $Id$
+ * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.ArrayList;
+
+/**
+ * LayoutManager for a table-cell FO.
+ * A cell contains blocks. These blocks fill the cell.
+ */
+public class Cell extends BlockStackingLayoutManager {
+
+ private Block curBlockArea;
+
+ private ArrayList childBreaks = new ArrayList();
+
+ private int xoffset;
+ private int yoffset;
+ private int cellIPD;
+
+ /**
+ * Create a new Cell layout manager.
+ * @param fobj the formatting object for the cell
+ */
+ public Cell(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Get the next break possibility for this cell.
+ * A cell contains blocks so there are breaks around the blocks
+ * and inside the blocks.
+ *
+ * @param context the layout context
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ LayoutManager curLM; // currently active LM
+
+ MinOptMax stackSize = new MinOptMax();
+ // if starting add space before
+ // stackSize.add(spaceBefore);
+ BreakPoss lastPos = null;
+
+ cellIPD = context.getRefIPD();
+
+ while ((curLM = getChildLM()) != null) {
+ // Set up a LayoutContext
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimit(MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+ childLC.setRefIPD(ipd);
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ childBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new LeafPosition(this, childBreaks.size() - 1));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+ }
+ setFinished(true);
+ return null;
+ }
+
+ /**
+ * Set the y offset of this cell.
+ * This offset is used to set the absolute position of the cell.
+ *
+ * @param off the y direction offset
+ */
+ public void setYOffset(int off) {
+ yoffset = off;
+ }
+
+ /**
+ * Set the x offset of this cell.
+ * This offset is used to set the absolute position of the cell.
+ *
+ * @param off the x offset
+ */
+ public void setXOffset(int off) {
+ xoffset = off;
+ }
+
+ /**
+ * Add the areas for the break points.
+ * The cell contains block stacking layout managers
+ * that add block areas.
+ *
+ * @param parentIter the iterator of the break positions
+ * @param layoutContext the layout context for adding the areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ LayoutManager childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ while (parentIter.hasNext()) {
+ LeafPosition lfp = (LeafPosition) parentIter.next();
+ // Add the block areas to Area
+ PositionIterator breakPosIter =
+ new BreakPossPosIter(childBreaks, iStartPos,
+ lfp.getLeafPos() + 1);
+ iStartPos = lfp.getLeafPos() + 1;
+ while ((childLM = breakPosIter.getNextChildLM()) != null) {
+ childLM.addAreas(breakPosIter, lc);
+ }
+ }
+
+ flush();
+
+ childBreaks.clear();
+ curBlockArea = null;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area to get the parent for
+ * @return the parent area
+ */
+ public Area getParentArea(Area childArea) {
+ if (curBlockArea == null) {
+ curBlockArea = new Block();
+ curBlockArea.setPositioning(Block.ABSOLUTE);
+ // set position
+ curBlockArea.setXOffset(xoffset);
+ curBlockArea.setYOffset(yoffset);
+ curBlockArea.setWidth(cellIPD);
+ //curBlockArea.setHeight();
+
+ // Set up dimensions
+ Area parentArea = parentLM.getParentArea(curBlockArea);
+ int referenceIPD = parentArea.getIPD();
+ curBlockArea.setIPD(referenceIPD);
+ // Get reference IPD from parentArea
+ setCurrentArea(curBlockArea); // ??? for generic operations
+ }
+ return curBlockArea;
+ }
+
+ /**
+ * Add the child to the cell block area.
+ *
+ * @param childArea the child to add to the cell
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ if (curBlockArea != null) {
+ curBlockArea.addBlock((Block) childArea);
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Reset the position of the layout.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/Column.java b/src/org/apache/fop/layoutmgr/table/Column.java
new file mode 100644
index 000000000..c44de25cb
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/Column.java
@@ -0,0 +1,92 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.AbstractLayoutManager;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.fo.flow.TableColumn;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+
+/**
+ * LayoutManager for a table-column FO.
+ * The table creates an area for the table-column background, this class
+ * is used to do the area creation. This is used during the layout to handle
+ * column properties.
+ */
+public class Column extends AbstractLayoutManager {
+ private int columnWidth;
+
+ /**
+ * Create a new column layout manager.
+ *
+ * @param fobj the table-column formatting object
+ */
+ public Column(TableColumn fobj) {
+ super(fobj);
+ columnWidth = fobj.getColumnWidth();
+ }
+
+ /**
+ * Get the next break possibility.
+ * Columns do not create or return any areas.
+ *
+ * @param context the layout context
+ * @return the break possibility, always null
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ return null;
+ }
+
+ /**
+ * Add the areas.
+ * Although this adds no areas it is used to add the id
+ * reference of the table-column.
+ *
+ * @param parentIter the position iterator
+ * @param layoutContext the context
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ addID();
+ }
+
+ /**
+ * Get the parent area.
+ * This does nothing.
+ *
+ * @param childArea the child area
+ * @return always null
+ */
+ public Area getParentArea(Area childArea) {
+ return null;
+ }
+
+ /**
+ * Get the width of this column.
+ *
+ * @return the width of the column
+ */
+ public int getWidth() {
+ return columnWidth;
+ }
+
+ /**
+ * Create a column area.
+ * This area has the background and width set.
+ * The Body manager will then set the offset of the column.
+ *
+ * @return the new column area
+ */
+ public Area createColumnArea() {
+ return new Block();
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/Row.java b/src/org/apache/fop/layoutmgr/table/Row.java
new file mode 100644
index 000000000..ebca76f59
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/Row.java
@@ -0,0 +1,277 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LayoutManager for a table-row FO.
+ * The row contains cells that are organised according to the columns.
+ * A break in a table row will contain breaks for each table cell.
+ * If there are row spanning cells then these cells belong to this row
+ * but effect the occupied columns of future rows.
+ */
+public class Row extends BlockStackingLayoutManager {
+
+ private List cellList = null;
+ private List columns = null;
+ private int rowHeight;
+ private int yoffset;
+
+ private class RowPosition extends LeafPosition {
+ protected List cellBreaks;
+ protected RowPosition(LayoutManager lm, int pos, List l) {
+ super(lm, pos);
+ cellBreaks = l;
+ }
+ }
+
+ /**
+ * Create a new row layout manager.
+ *
+ * @param fobj the table-row formatting object
+ */
+ public Row(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Set the columns from the table.
+ *
+ * @param cols the list of columns for this table
+ */
+ public void setColumns(List cols) {
+ columns = cols;
+ }
+
+ private void setupCells() {
+ cellList = new ArrayList();
+ // add cells to list
+ while (m_childLMiter.hasNext()) {
+ m_curChildLM = (LayoutManager) m_childLMiter.next();
+ m_curChildLM.setParentLM(this);
+ m_curChildLM.init();
+ cellList.add(m_curChildLM);
+ }
+ }
+
+ /**
+ * Get the layout manager for a cell.
+ *
+ * @param pos the position of the cell
+ * @return the cell layout manager
+ */
+ protected Cell getCellLM(int pos) {
+ if (cellList == null) {
+ setupCells();
+ }
+ if (pos < cellList.size()) {
+ return (Cell)cellList.get(pos);
+ }
+ return null;
+ }
+
+ /**
+ * Get the next break possibility.
+ * A row needs to get the possible breaks for each cell
+ * in the row and find a suitable break across all cells.
+ *
+ * @param context the layout context for getting breaks
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ LayoutManager curLM; // currently active LM
+
+ BreakPoss lastPos = null;
+ ArrayList breakList = new ArrayList();
+
+ int min = 0;
+ int opt = 0;
+ int max = 0;
+
+ int cellcount = 0;
+ while ((curLM = getCellLM(cellcount++)) != null) {
+
+ ArrayList childBreaks = new ArrayList();
+ MinOptMax stackSize = new MinOptMax();
+
+ // Set up a LayoutContext
+ // the ipd is from the current column
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimit(
+ MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+
+ Column col = (Column)columns.get(cellcount - 1);
+ childLC.setRefIPD(col.getWidth());
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ childBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ // the min is the maximum min of all cells
+ if (stackSize.min > min) {
+ min = stackSize.min;
+ }
+ // the optimum is the average of all optimums
+ opt += stackSize.opt;
+ // the maximum is the largest maximum
+ if (stackSize.max > max) {
+ max = stackSize.max;
+ }
+
+ breakList.add(childBreaks);
+ }
+ opt = opt / cellcount;
+ if (opt < min) {
+ opt = min;
+ }
+ rowHeight = opt;
+
+ MinOptMax rowSize = new MinOptMax(min, opt, max);
+
+ setFinished(true);
+ RowPosition rp = new RowPosition(this, breakList.size() - 1, breakList);
+ BreakPoss breakPoss = new BreakPoss(rp);
+ breakPoss.setStackingSize(rowSize);
+ return breakPoss;
+ }
+
+ /**
+ * Set the y position offset of this row.
+ * This is used to set the position of the areas returned by this row.
+ *
+ * @param off the y offset
+ */
+ public void setYOffset(int off) {
+ yoffset = off;
+ }
+
+ /**
+ * Add the areas for the break points.
+ * This sets the offset of each cell as it is added.
+ *
+ * @param parentIter the position iterator
+ * @param layoutContext the layout context for adding areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ Cell childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ while (parentIter.hasNext()) {
+ RowPosition lfp = (RowPosition) parentIter.next();
+ // Add the block areas to Area
+
+ int cellcount = 0;
+ int xoffset = 0;
+ for (Iterator iter = lfp.cellBreaks.iterator(); iter.hasNext();) {
+ List cellsbr = (List)iter.next();
+ PositionIterator breakPosIter;
+ breakPosIter = new BreakPossPosIter(cellsbr, 0, cellsbr.size());
+ iStartPos = lfp.getLeafPos() + 1;
+ Column col = (Column)columns.get(cellcount++);
+ while ((childLM = (Cell)breakPosIter.getNextChildLM()) != null) {
+ childLM.setXOffset(xoffset);
+ childLM.setYOffset(yoffset);
+ childLM.addAreas(breakPosIter, lc);
+ }
+ xoffset += col.getWidth();
+ }
+ }
+
+ flush();
+
+ }
+
+ /**
+ * Get the row height of the row after adjusting.
+ * Should only be called after adding the row areas.
+ *
+ * @return the row height of this row after adjustment
+ */
+ public int getRowHeight() {
+ return rowHeight;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area
+ * @return the parent are for the child
+ */
+ public Area getParentArea(Area childArea) {
+ return parentLM.getParentArea(childArea);
+ }
+
+ /**
+ * Add the child.
+ * Rows return the areas returned by the child elements.
+ * This simply adds the area to the parent layout manager.
+ *
+ * @param childArea the child area
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ return parentLM.addChild(childArea);
+ }
+
+ /**
+ * Reset the position of this layout manager.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
new file mode 100644
index 000000000..dc7ffe21c
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
@@ -0,0 +1,192 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.ArrayList;
+
+/**
+ * LayoutManager for a table-and-caption FO.
+ * A table and caption consists of a table and a caption.
+ * The caption contains blocks that are positioned next to the
+ * table on the caption side.
+ * The caption blocks have an implicit keep with the table.
+ */
+public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager {
+
+ private Block curBlockArea;
+
+ private ArrayList childBreaks = new ArrayList();
+
+ /**
+ * Create a new table and caption layout manager.
+ *
+ * @param fobj the table-and-caption formatting object
+ */
+ public TableAndCaptionLayoutManager(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Get the next break possibility.
+ *
+ * @param context the layout context for getting breaks
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ LayoutManager curLM; // currently active LM
+
+ MinOptMax stackSize = new MinOptMax();
+ // if starting add space before
+ // stackSize.add(spaceBefore);
+ BreakPoss lastPos = null;
+
+ // if there is a caption then get the side and work out when
+ // to handle it
+
+ while ((curLM = getChildLM()) != null) {
+ // Make break positions and return blocks!
+ // Set up a LayoutContext
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ // if line layout manager then set stack limit to ipd
+ // line LM actually generates a LineArea which is a block
+ childLC.setStackLimit(
+ MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+ childLC.setRefIPD(ipd);
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ childBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new LeafPosition(this, childBreaks.size() - 1));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+ }
+ setFinished(true);
+ return null;
+ }
+
+ /**
+ * Add the areas.
+ *
+ * @param parentIter the position iterator
+ * @param layoutContext the layout context for adding areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ LayoutManager childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ while (parentIter.hasNext()) {
+ LeafPosition lfp = (LeafPosition) parentIter.next();
+ // Add the block areas to Area
+ PositionIterator breakPosIter =
+ new BreakPossPosIter(childBreaks, iStartPos,
+ lfp.getLeafPos() + 1);
+ iStartPos = lfp.getLeafPos() + 1;
+ while ((childLM = breakPosIter.getNextChildLM()) != null) {
+ childLM.addAreas(breakPosIter, lc);
+ }
+ }
+
+ flush();
+
+ childBreaks.clear();
+ curBlockArea = null;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area to locate the parent
+ * @return the area for this table and caption
+ */
+ public Area getParentArea(Area childArea) {
+ if (curBlockArea == null) {
+ curBlockArea = new Block();
+ // Set up dimensions
+ // Must get dimensions from parent area
+ Area parentArea = parentLM.getParentArea(curBlockArea);
+ int referenceIPD = parentArea.getIPD();
+ curBlockArea.setIPD(referenceIPD);
+ // Get reference IPD from parentArea
+ setCurrentArea(curBlockArea); // ??? for generic operations
+ }
+ return curBlockArea;
+ }
+
+ /**
+ * Add the child to the current area.
+ *
+ * @param childArea the area to add
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ if (curBlockArea != null) {
+ curBlockArea.addBlock((Block) childArea);
+ //return super.addChild(childArea);
+
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Reset the position of this layout manager.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java
new file mode 100644
index 000000000..9dda28697
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -0,0 +1,291 @@
+/*
+ * $Id$
+ * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr.table;
+
+import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.BreakPoss;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.BreakPossPosIter;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LayoutManager for a table FO.
+ * A table consists of columns, table header, table footer and multiple
+ * table bodies.
+ * The header, footer and body add the areas created from the table cells.
+ * The table then creates areas for the columns, bodies and rows
+ * the render background.
+ */
+public class TableLayoutManager extends BlockStackingLayoutManager {
+ private List columns = null;
+ private Body tableHeader = null;
+ private Body tableFooter = null;
+
+ private Block curBlockArea;
+
+ private ArrayList bodyBreaks = new ArrayList();
+ private BreakPoss headerBreak;
+ private BreakPoss footerBreak;
+
+ private class SectionPosition extends LeafPosition {
+ protected List list;
+ protected SectionPosition(LayoutManager lm, int pos, List l) {
+ super(lm, pos);
+ list = l;
+ }
+ }
+
+ /**
+ * Create a new table layout manager.
+ *
+ * @param fobj the table formatting object
+ */
+ public TableLayoutManager(FObj fobj) {
+ super(fobj);
+ }
+
+ /**
+ * Set the columns for this table.
+ *
+ * @param cols the list of column layout managers
+ */
+ public void setColumns(List cols) {
+ columns = cols;
+ }
+
+ /**
+ * Set the table header.
+ *
+ * @param th the table header layout manager
+ */
+ public void setTableHeader(Body th) {
+ tableHeader = th;
+ }
+
+ /**
+ * Set the table footer.
+ *
+ * @param tf the table footer layout manager
+ */
+ public void setTableFooter(Body tf) {
+ tableFooter = tf;
+ }
+
+ /**
+ * Get the next break possibility.
+ * The break possibility depends on the height of the header and footer
+ * and possible breaks inside the table body.
+ *
+ * @param context the layout context for finding breaks
+ * @return the next break possibility
+ */
+ public BreakPoss getNextBreakPoss(LayoutContext context) {
+ Body curLM; // currently active LM
+
+ MinOptMax stackSize = new MinOptMax();
+ // if starting add space before
+ // stackSize.add(spaceBefore);
+ BreakPoss lastPos = null;
+
+ MinOptMax headerSize = null;
+ if (tableHeader != null) {
+ headerBreak = getHeight(tableHeader, context);
+ headerSize = headerBreak.getStackingSize();
+ }
+
+ MinOptMax footerSize = null;
+ if (tableFooter != null) {
+ footerBreak = getHeight(tableFooter, context);
+ footerSize = footerBreak.getStackingSize();
+ }
+
+ while ((curLM = (Body)getChildLM()) != null) {
+ // Make break positions
+ // Set up a LayoutContext
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimit(
+ MinOptMax.subtract(context.getStackLimit(),
+ stackSize));
+ childLC.setRefIPD(ipd);
+
+ curLM.setColumns(columns);
+
+ while (!curLM.isFinished()) {
+ if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ if (stackSize.min > context.getStackLimit().max) {
+ // reset to last break
+ if (lastPos != null) {
+ reset(lastPos.getPosition());
+ } else {
+ curLM.resetPosition(null);
+ }
+ break;
+ }
+ lastPos = bp;
+ bodyBreaks.add(bp);
+
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new LeafPosition(this, bodyBreaks.size() - 1));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+ }
+ setFinished(true);
+ return null;
+ }
+
+ /**
+ * Get the break possibility and height of the table header or footer.
+ *
+ * @param lm the header or footer layout manager
+ * @param context the parent layout context
+ * @return the break possibility containing the stacking size
+ */
+ protected BreakPoss getHeight(Body lm, LayoutContext context) {
+ int ipd = context.getRefIPD();
+ BreakPoss bp;
+
+ MinOptMax stackSize = new MinOptMax();
+
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimit(context.getStackLimit());
+ childLC.setRefIPD(ipd);
+
+ lm.setColumns(columns);
+
+ ArrayList breaks = new ArrayList();
+ while (!lm.isFinished()) {
+ if ((bp = lm.getNextBreakPoss(childLC)) != null) {
+ stackSize.add(bp.getStackingSize());
+ breaks.add(bp);
+ childLC.setStackLimit(MinOptMax.subtract(
+ context.getStackLimit(), stackSize));
+ }
+ }
+ BreakPoss breakPoss = new BreakPoss(
+ new SectionPosition(this, breaks.size() - 1, breaks));
+ breakPoss.setStackingSize(stackSize);
+ return breakPoss;
+
+ }
+
+ /**
+ * The table area is a reference area that contains areas for
+ * columns, bodies, rows and the contents are in cells.
+ *
+ * @param parentIter the position iterator
+ * @param layoutContext the layout context for adding areas
+ */
+ public void addAreas(PositionIterator parentIter,
+ LayoutContext layoutContext) {
+ getParentArea(null);
+ addID();
+
+ // add column, body then row areas
+
+ // add table header areas
+
+ int tableHeight = 0;
+
+ Body childLM;
+ int iStartPos = 0;
+ LayoutContext lc = new LayoutContext(0);
+ while (parentIter.hasNext()) {
+ LeafPosition lfp = (LeafPosition) parentIter.next();
+ // Add the block areas to Area
+ PositionIterator breakPosIter =
+ new BreakPossPosIter(bodyBreaks, iStartPos,
+ lfp.getLeafPos() + 1);
+ iStartPos = lfp.getLeafPos() + 1;
+ while ((childLM = (Body)breakPosIter.getNextChildLM()) != null) {
+ childLM.addAreas(breakPosIter, lc);
+ tableHeight += childLM.getBodyHeight();
+ }
+ }
+
+ // add footer areas
+
+ curBlockArea.setHeight(tableHeight);
+
+ flush();
+
+ bodyBreaks.clear();
+ curBlockArea = null;
+ }
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ *
+ * @param childArea the child area
+ * @return the parent area of the child
+ */
+ public Area getParentArea(Area childArea) {
+ if (curBlockArea == null) {
+ curBlockArea = new Block();
+ // Set up dimensions
+ // Must get dimensions from parent area
+ Area parentArea = parentLM.getParentArea(curBlockArea);
+ int referenceIPD = parentArea.getIPD();
+ curBlockArea.setIPD(referenceIPD);
+ // Get reference IPD from parentArea
+ setCurrentArea(curBlockArea); // ??? for generic operations
+ }
+ return curBlockArea;
+ }
+
+ /**
+ * Add the child area to this layout manager.
+ *
+ * @param childArea the child area to add
+ * @return unused
+ */
+ public boolean addChild(Area childArea) {
+ if (curBlockArea != null) {
+ curBlockArea.addBlock((Block) childArea);
+
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Reset the position of this layout manager.
+ *
+ * @param resetPos the position to reset to
+ */
+ public void resetPosition(Position resetPos) {
+ if (resetPos == null) {
+ reset(null);
+ }
+ }
+}
+