]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
initial implementation of lists
authorKeiron Liddle <keiron@apache.org>
Sun, 3 Nov 2002 16:29:58 +0000 (16:29 +0000)
committerKeiron Liddle <keiron@apache.org>
Sun, 3 Nov 2002 16:29:58 +0000 (16:29 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195406 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/fo/flow/ListBlock.java
src/org/apache/fop/fo/flow/ListItem.java
src/org/apache/fop/fo/flow/ListItemBody.java
src/org/apache/fop/fo/flow/ListItemLabel.java
src/org/apache/fop/layoutmgr/list/Item.java [new file with mode: 0644]
src/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java [new file with mode: 0644]
src/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java [new file with mode: 0644]
src/org/apache/fop/layoutmgr/table/Row.java

index 56fb2f49d75cfe1b8d1ad484ab6a62aa5c8ec632..5bb9e7fed34a95e9c3686558bd8558e95737cb79 100644 (file)
@@ -14,9 +14,11 @@ import org.apache.fop.datatypes.*;
 import org.apache.fop.layout.*;
 import org.apache.fop.layout.FontState;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.layoutmgr.list.ListBlockLayoutManager;
 
 // Java
 import java.util.Iterator;
+import java.util.List;
 
 public class ListBlock extends FObj {
 
@@ -36,6 +38,11 @@ public class ListBlock extends FObj {
         super(parent);
     }
 
+    public void addLayoutManager(List list) {
+        ListBlockLayoutManager blm = new ListBlockLayoutManager(this);
+        list.add(blm);
+    }       
+
     public void setup() throws FOPException {
 
             // Common Accessibility Properties
index 01304bcedb6a5bbd3d3eef32ba5c02ea8afeb140..9c258c79e63f6bd58ffaef1133386339f5c3ccb4 100644 (file)
@@ -13,11 +13,15 @@ import org.apache.fop.fo.properties.*;
 import org.apache.fop.layout.*;
 import org.apache.fop.layout.FontState;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.layoutmgr.list.ListItemLayoutManager;
 
 // Java
 import java.util.Iterator;
+import java.util.List;
 
 public class ListItem extends FObj {
+    ListItemLabel label = null;
+    ListItemBody body = null;
 
     int align;
     int alignLast;
@@ -33,43 +37,64 @@ public class ListItem extends FObj {
         super(parent);
     }
 
+    public void addLayoutManager(List list) {
+        if(label != null && body != null) {
+            ListItemLayoutManager blm = new ListItemLayoutManager(this);
+            blm.setLabel(label.getItemLayoutManager());
+            blm.setBody(body.getItemLayoutManager());
+            list.add(blm);
+        }
+    }
+
     public void setup() {
 
-            // Common Accessibility Properties
-            AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
+        // Common Accessibility Properties
+        AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
 
-            // Common Aural Properties
-            AuralProps mAurProps = propMgr.getAuralProps();
+        // Common Aural Properties
+        AuralProps mAurProps = propMgr.getAuralProps();
 
-            // Common Border, Padding, and Background Properties
-            BorderAndPadding bap = propMgr.getBorderAndPadding();
-            BackgroundProps bProps = propMgr.getBackgroundProps();
+        // Common Border, Padding, and Background Properties
+        BorderAndPadding bap = propMgr.getBorderAndPadding();
+        BackgroundProps bProps = propMgr.getBackgroundProps();
 
-            // Common Margin Properties-Block
-            MarginProps mProps = propMgr.getMarginProps();
+        // Common Margin Properties-Block
+        MarginProps mProps = propMgr.getMarginProps();
 
-            // Common Relative Position Properties
-            RelativePositionProps mRelProps = propMgr.getRelativePositionProps();
+        // Common Relative Position Properties
+        RelativePositionProps mRelProps = propMgr.getRelativePositionProps();
 
-            // this.properties.get("break-after");
-            // this.properties.get("break-before");
-            setupID();
-            // this.properties.get("keep-together");
-            // this.properties.get("keep-with-next");
-            // this.properties.get("keep-with-previous");
-            // this.properties.get("relative-align");
+        // this.properties.get("break-after");
+        // this.properties.get("break-before");
+        setupID();
+        // this.properties.get("keep-together");
+        // this.properties.get("keep-with-next");
+        // this.properties.get("keep-with-previous");
+        // this.properties.get("relative-align");
 
-            this.align = this.properties.get("text-align").getEnum();
-            this.alignLast = this.properties.get("text-align-last").getEnum();
-            this.lineHeight =
-                this.properties.get("line-height").getLength().mvalue();
-            this.spaceBefore =
-                this.properties.get("space-before.optimum").getLength().mvalue();
-            this.spaceAfter =
-                this.properties.get("space-after.optimum").getLength().mvalue();
+        this.align = this.properties.get("text-align").getEnum();
+        this.alignLast = this.properties.get("text-align-last").getEnum();
+        this.lineHeight =
+            this.properties.get("line-height").getLength().mvalue();
+        this.spaceBefore =
+            this.properties.get("space-before.optimum").getLength().mvalue();
+        this.spaceAfter =
+            this.properties.get("space-after.optimum").getLength().mvalue();
 
     }
 
+    public void addChild(FONode child) {
+        if ("fo:list-item-label".equals(child.getName())) {
+            label = (ListItemLabel)child;
+        } else if ("fo:list-item-body".equals(child.getName())) {
+            body = (ListItemBody)child;
+        } else if("fo:marker".equals(child.getName())) {
+            // marker
+        } else {
+            // error
+        }
+    } 
+
     public boolean generatesInlineAreas() {
         return false;
     }
index d27046e0bb39f057e0941b12e25e43ca6f28cb94..f201aa9b35486106aa02efe0f9af22c71e7398a3 100644 (file)
@@ -13,6 +13,7 @@ import org.apache.fop.fo.properties.*;
 import org.apache.fop.layout.*;
 import org.apache.fop.layout.FontState;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.layoutmgr.list.Item;
 
 // Java
 import java.util.Iterator;
@@ -23,6 +24,11 @@ public class ListItemBody extends FObj {
         super(parent);
     }
 
+    public Item getItemLayoutManager() {
+        Item item = new Item(this);
+        return item;
+    }
+
     public void setup() {
 
             // Common Accessibility Properties
index da2ef5d30dba96dc16e8c952518347adae8b0cf2..3115b340690ce2f14f0d5e48d568230e035d76b5 100644 (file)
@@ -13,6 +13,7 @@ import org.apache.fop.fo.properties.*;
 import org.apache.fop.layout.*;
 import org.apache.fop.layout.FontState;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.layoutmgr.list.Item;
 
 // Java
 import java.util.Enumeration;
@@ -23,7 +24,12 @@ public class ListItemLabel extends FObj {
         super(parent);
     }
 
-    public void setup() throws FOPException {
+    public Item getItemLayoutManager() {
+        Item itemLabel = new Item(this);
+        return itemLabel;
+    }
+
+    public void setup() {
 
         // Common Accessibility Properties
         AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
diff --git a/src/org/apache/fop/layoutmgr/list/Item.java b/src/org/apache/fop/layoutmgr/list/Item.java
new file mode 100644 (file)
index 0000000..4372757
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * $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.list;
+
+import org.apache.fop.fo.PropertyManager;
+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 org.apache.fop.layout.BorderAndPadding;
+import org.apache.fop.layout.BackgroundProps;
+
+import java.util.ArrayList;
+
+/**
+ * LayoutManager for a table-cell FO.
+ * A cell contains blocks. These blocks fill the cell.
+ */
+public class Item extends BlockStackingLayoutManager {
+
+    private BorderAndPadding borderProps = null;
+    private BackgroundProps backgroundProps;
+
+    private Block curBlockArea;
+
+    private ArrayList childBreaks = new ArrayList();
+
+    private int xoffset;
+    private int yoffset;
+    private int itemIPD;
+
+    /**
+     * Create a new Cell layout manager.
+     * @param fobj the formatting object for the cell
+     */
+    public Item(FObj fobj) {
+        super(fobj);
+    }
+
+    protected void initProperties(PropertyManager propMgr) {
+        borderProps = propMgr.getBorderAndPadding();
+        backgroundProps = propMgr.getBackgroundProps();
+    }
+
+    /**
+     * 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;
+
+        itemIPD = context.getRefIPD();
+
+        while ((curLM = getChildLM()) != null) {
+            if(curLM.generatesInlineAreas()) {
+                // error
+                curLM.setFinished(true);
+                continue;
+            }
+            // 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);
+            }
+        }
+
+        if(borderProps != null) {
+            addBorders(curBlockArea, borderProps);
+        }
+        if(backgroundProps != null) {
+            addBackground(curBlockArea, backgroundProps);
+        }
+
+        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(itemIPD);
+            //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/list/ListBlockLayoutManager.java b/src/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
new file mode 100644 (file)
index 0000000..fd15515
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * $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.list;
+
+import org.apache.fop.fo.PropertyManager;
+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 org.apache.fop.layout.BorderAndPadding;
+import org.apache.fop.layout.BackgroundProps;
+
+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 ListBlockLayoutManager extends BlockStackingLayoutManager {
+    private List columns = null;
+
+    private BorderAndPadding borderProps = null;
+    private BackgroundProps backgroundProps;
+
+    private Block curBlockArea;
+
+    private ArrayList bodyBreaks = new ArrayList();
+
+    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 ListBlockLayoutManager(FObj fobj) {
+        super(fobj);
+    }
+
+    protected void initProperties(PropertyManager propMgr) {
+        borderProps = propMgr.getBorderAndPadding();
+        backgroundProps = propMgr.getBackgroundProps();
+    }
+
+    /**
+     * 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) {
+        ListItemLayoutManager curLM; // currently active LM
+
+        MinOptMax stackSize = new MinOptMax();
+        // if starting add space before
+        // stackSize.add(spaceBefore);
+        BreakPoss lastPos = null;
+
+        while ((curLM = (ListItemLayoutManager)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);
+
+            while (!curLM.isFinished()) {
+                if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
+                    stackSize.add(bp.getStackingSize());
+                    if (stackSize.opt > 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;
+    }
+
+    /**
+     * 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;
+
+        ListItemLayoutManager 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 = (ListItemLayoutManager)breakPosIter.getNextChildLM()) != null) {
+                childLM.addAreas(breakPosIter, lc);
+                tableHeight += childLM.getListItemHeight();
+            }
+        }
+
+        // add footer areas
+
+        curBlockArea.setHeight(tableHeight);
+
+        if(borderProps != null) { 
+            addBorders(curBlockArea, borderProps);
+        }
+        if(backgroundProps != null) {
+            addBackground(curBlockArea, backgroundProps);
+        }
+
+        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);
+        }
+    }
+}
+
diff --git a/src/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
new file mode 100644 (file)
index 0000000..71e7f34
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * $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.list;
+
+import org.apache.fop.fo.PropertyManager;
+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 org.apache.fop.layout.BorderAndPadding;
+import org.apache.fop.layout.BackgroundProps;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LayoutManager for a list-item FO.
+ * The list item contains a list item label and a list item body.
+ */
+public class ListItemLayoutManager extends BlockStackingLayoutManager {
+    private Item label;
+    private Item body;
+
+    private Block curBlockArea;
+
+    private List cellList = null;
+    private List columns = null;
+    private int listItemHeight;
+    private int yoffset;
+    private BorderAndPadding borderProps = null;
+    private BackgroundProps backgroundProps;
+
+    private class ItemPosition extends LeafPosition {
+        protected List cellBreaks;
+        protected ItemPosition(LayoutManager lm, int pos, List l) {
+            super(lm, pos);
+            cellBreaks = l;
+        }
+    }
+
+    /**
+     * Create a new list item layout manager.
+     *
+     * @param fobj the list-item formatting object
+     */
+    public ListItemLayoutManager(FObj fobj) {
+        super(fobj);
+    }
+
+    protected void initProperties(PropertyManager propMgr) {
+        borderProps = propMgr.getBorderAndPadding();
+        backgroundProps = propMgr.getBackgroundProps();
+    }
+
+    public void setLabel(Item item) {
+        label = item;
+        label.setParentLM(this);
+    }
+
+    public void setBody(Item item) {
+        body = item;
+        body.setParentLM(this);
+    }
+
+    /**
+     * Get the next break possibility.
+     *
+     * @param context the layout context for getting breaks
+     * @return the next break possibility
+     */
+    public BreakPoss getNextBreakPoss(LayoutContext context) {
+        Item curLM; // currently active LM
+
+        BreakPoss lastPos = null;
+        ArrayList breakList = new ArrayList();
+
+        int min = 0;
+        int opt = 0;
+        int max = 0;
+
+        int stage = 0;
+        while (true) {
+            if(stage == 0) {
+                curLM = label;
+            } else if (stage == 1) {
+                curLM = body;
+            } else {
+                break;
+            }
+            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));
+            if (stage == 0) {
+                childLC.setRefIPD(24000);
+            } else if (stage == 1) {
+                childLC.setRefIPD(context.getRefIPD() - 24000);
+            }
+            stage++;
+            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) {
+                            curLM.resetPosition(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 the label and body
+            if (stackSize.min > min) {
+                min = stackSize.min;
+            }
+            // the optimum is the minimum of all optimums
+            if (stackSize.opt > opt) {
+                opt = stackSize.opt;
+            }
+            // the maximum is the largest maximum
+            if (stackSize.max > max) {
+                max = stackSize.max;
+            }
+
+            breakList.add(childBreaks);
+        }
+        listItemHeight = opt;
+
+        MinOptMax itemSize = new MinOptMax(min, opt, max);
+
+        setFinished(true);
+        ItemPosition rp = new ItemPosition(this, breakList.size() - 1, breakList);
+        BreakPoss breakPoss = new BreakPoss(rp);
+        breakPoss.setStackingSize(itemSize);
+        return breakPoss;
+    }
+
+    /**
+     * Set the y position offset of this list item.
+     * This is used to set the position of the areas returned by this list item.
+     *
+     * @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();
+
+        Item childLM;
+        int iStartPos = 0;
+        LayoutContext lc = new LayoutContext(0);
+        while (parentIter.hasNext()) {
+            ItemPosition lfp = (ItemPosition) parentIter.next();
+            // Add the block areas to Area
+
+            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;
+
+                while ((childLM = (Item)breakPosIter.getNextChildLM()) != null) {
+                    if(childLM == body) {
+                        childLM.setXOffset(24000);
+                    }
+                    childLM.addAreas(breakPosIter, lc);
+                }
+                xoffset += 100000;
+            }
+        }
+
+        curBlockArea.setHeight(listItemHeight);
+
+        flush();
+
+    }
+
+    /**
+     * Get the height of the list item after adjusting.
+     * Should only be called after adding the list item areas.
+     *
+     * @return the height of this list item after adjustment
+     */
+    public int getListItemHeight() {
+        return listItemHeight;
+    }
+
+    /**
+     * 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) {
+        if (curBlockArea == null) {
+            curBlockArea = new Block();
+
+            // Set up dimensions
+            Area parentArea = parentLM.getParentArea(curBlockArea);
+            int referenceIPD = parentArea.getIPD();
+            curBlockArea.setIPD(referenceIPD);
+            curBlockArea.setWidth(referenceIPD);
+            // Get reference IPD from parentArea
+            setCurrentArea(curBlockArea); // ??? for generic operations
+        }
+        return curBlockArea;
+    }
+
+    /**
+     * 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) {
+        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);
+        }
+    }
+}
+
index d9f2c46fdd91aba4d70645651b7d7e0ab15f36f9..3784bb984417cdb6d17307b137d89ed9fa7c2601 100644 (file)
@@ -167,8 +167,10 @@ public class Row extends BlockStackingLayoutManager {
             if (stackSize.min > min) {
                 min = stackSize.min;
             }
-            // the optimum is the average of all optimums
-            opt += stackSize.opt;
+            // the optimum is the minimum of all optimums
+            if (stackSize.opt > opt) {
+                opt = stackSize.opt;
+            }   
             // the maximum is the largest maximum
             if (stackSize.max > max) {
                 max = stackSize.max;
@@ -176,10 +178,6 @@ public class Row extends BlockStackingLayoutManager {
 
             breakList.add(childBreaks);
         }
-        opt = opt / cellcount;
-        if (opt < min) {
-            opt = min;
-        }
         rowHeight = opt;
 
         MinOptMax rowSize = new MinOptMax(min, opt, max);