]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Modify keep-with-next and keep-with-previous handling to support "level-hopping"...
authorJeremias Maerki <jeremias@apache.org>
Tue, 24 May 2005 09:41:32 +0000 (09:41 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 24 May 2005 09:41:32 +0000 (09:41 +0000)
Full keep handling for tables (there's a remaning problem with keep-with-previous)
keep-together support for lists.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198683 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/Item.java
src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/Cell.java
src/java/org/apache/fop/layoutmgr/table/GridUnit.java
src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableStepper.java

index 550099cd0b00b65dd6c1c5d4fab7b017bd6bcb67..23a5a02bd476a5832b76f05e31364467f3b8359a 100644 (file)
@@ -234,6 +234,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
 
             // get elements from curLM
             returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) {
+                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
+            }
             if (returnedList != null
                     && returnedList.size() == 1
                     && ((KnuthElement) returnedList.getFirst()).isPenalty()
@@ -267,8 +271,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
                     // there is a block handled by prevLM
                     // before the one handled by curLM
                     if (mustKeepTogether() 
-                            || prevLM.mustKeepWithNext()
-                            || curLM.mustKeepWithPrevious()) {
+                            || context.isKeepWithNextPending()
+                            || childLC.isKeepWithPreviousPending()) {
+                        //Clear keep pending flag
+                        context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                        childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
                         // add an infinite penalty to forbid a break between
                         // blocks
                         contentList.add(new KnuthPenalty(0,
@@ -317,6 +324,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
                     return returnList;
                 }*/
             }
+            if (childLC.isKeepWithNextPending()) {
+                //Clear and propagate
+                childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+            }
             prevLM = curLM;
         }
 
@@ -339,6 +351,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
         addKnuthElementsForSpaceAfter(returnList, returnPosition, alignment);
         addKnuthElementsForBreakAfter(returnList, returnPosition);
 
+        if (mustKeepWithNext()) {
+            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+        }
+        if (mustKeepWithPrevious()) {
+            context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+        }
+        
         setFinished(true);
 
         return returnList;
index 3399d05e6daa87420c0306472b5125cfd91bbf93..5a69104f31a1548bb190922abfc9019eae719d28 100644 (file)
@@ -106,6 +106,10 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
             // get elements from curLM
             returnedList = curLM.getNextKnuthElements(childLC, alignment);
             //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + returnedList.size());
+            if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) {
+                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
+            }
 
             // "wrap" the Position inside each element
             LinkedList tempList = returnedList;
@@ -121,8 +125,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
             } else {
                 if (returnList.size() > 0) {
                     // there is a block before this one
-                    if (prevLM.mustKeepWithNext()
-                        || curLM.mustKeepWithPrevious()) {
+                    if (context.isKeepWithNextPending()
+                            || childLC.isKeepWithPreviousPending()) {
+                        //Clear pending keep flag
+                        context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                        childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
                         // add an infinite penalty to forbid a break between blocks
                         returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, 
                                 new Position(this), false));
@@ -142,6 +149,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
                     }
                 }
             }
+            if (childLC.isKeepWithNextPending()) {
+                //Clear and propagate
+                childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+            }
             prevLM = curLM;
         }
 
index a7dd3799e29f92d1377c31d62063e249e2b84b43..16a9ab3f31ece3aa9efefec408b0c995536d648b 100644 (file)
  
 package org.apache.fop.layoutmgr.list;
 
-import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.flow.AbstractListItemPart;
 import org.apache.fop.fo.flow.ListItemBody;
 import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
 import org.apache.fop.layoutmgr.LayoutManager;
 import org.apache.fop.layoutmgr.LayoutContext;
@@ -30,17 +31,14 @@ import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
 
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.LinkedList;
 
 /**
- * LayoutManager for a table-cell FO.
- * A cell contains blocks. These blocks fill the cell.
+ * LayoutManager for a list-item-label or list-item-body FO.
  */
 public class Item extends BlockStackingLayoutManager {
-    private FObj fobj;
 
     private Block curBlockArea;
 
@@ -63,20 +61,28 @@ public class Item extends BlockStackingLayoutManager {
 
     /**
      * Create a new Cell layout manager.
+     * @param node list-item-label node
      */
     public Item(ListItemLabel node) {
         super(node);
-        fobj = node;
     }
 
     /**
      * Create a new Cell layout manager.
+     * @param node list-item-body node
      */
     public Item(ListItemBody node) {
         super(node);
-        fobj = node;
     }
 
+    /**
+     * Convenience method.
+     * @return the ListBlock node
+     */
+    protected AbstractListItemPart getPartFO() {
+        return (AbstractListItemPart)fobj;
+    }
+    
     /**
      * Set the x offset of this list item.
      * This offset is used to set the absolute position
@@ -88,6 +94,7 @@ public class Item extends BlockStackingLayoutManager {
         xoffset = off;
     }
 
+    /** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) */
     public LinkedList getChangedKnuthElements(List oldList, int alignment) {
         //log.debug("  Item.getChanged>");
         return super.getChangedKnuthElements(oldList, alignment);
@@ -105,12 +112,7 @@ public class Item extends BlockStackingLayoutManager {
                          LayoutContext layoutContext) {
         getParentArea(null);
         
-        int nameId = fobj.getNameId();
-        if (nameId == FO_LIST_ITEM_LABEL) {
-            getPSLM().addIDToPage(((ListItemLabel) fobj).getId());
-        } else if (nameId == FO_LIST_ITEM_BODY) {
-            getPSLM().addIDToPage(((ListItemBody) fobj).getId());
-        }
+        getPSLM().addIDToPage(getPartFO().getId());
 
         LayoutManager childLM = null;
         LayoutContext lc = new LayoutContext(0);
@@ -144,15 +146,6 @@ public class Item extends BlockStackingLayoutManager {
             childLM.addAreas(childPosIter, lc);
         }
 
-        /*
-        if (borderProps != null) {
-            TraitSetter.addBorders(curBlockArea, borderProps);
-        }
-        if (backgroundProps != null) {
-            TraitSetter.addBackground(curBlockArea, backgroundProps);
-        }
-        */
-
         flush();
 
         curBlockArea = null;
@@ -214,5 +207,14 @@ public class Item extends BlockStackingLayoutManager {
             //reset(resetPos);
         }
     }
+    
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */
+    public boolean mustKeepTogether() {
+        //TODO Keeps will have to be more sophisticated sooner or later
+        return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() 
+                || !getPartFO().getKeepTogether().getWithinPage().isAuto()
+                || !getPartFO().getKeepTogether().getWithinColumn().isAuto();
+    }
+
 }
 
index 8a2655954dea8ba3c79c86100e8ee6c42dc0d45d..af58646b49ee2f7215724386b706cd97d3d3b9de 100644 (file)
@@ -19,6 +19,7 @@
 package org.apache.fop.layoutmgr.list;
 
 import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
 import org.apache.fop.layoutmgr.LayoutManager;
 import org.apache.fop.layoutmgr.LayoutContext;
@@ -41,8 +42,6 @@ import java.util.List;
  * the list block area..
  */
 public class ListBlockLayoutManager extends BlockStackingLayoutManager {
-    private ListBlock fobj;
-    
     private Block curBlockArea;
 
     //TODO space-before|after: handle space-resolution rules
@@ -78,20 +77,27 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager {
      */
     public ListBlockLayoutManager(ListBlock node) {
         super(node);
-        fobj = node;
+    }
+
+    /**
+     * Convenience method.
+     * @return the ListBlock node
+     */
+    protected ListBlock getListBlockFO() {
+        return (ListBlock)fobj;
     }
 
     /** @see org.apache.fop.layoutmgr.AbstractLayoutManager#initProperties() */
     protected void initProperties() {
         super.initProperties();
-        spaceBefore = new SpaceVal(fobj.getCommonMarginBlock().spaceBefore).getSpace();
-        spaceAfter = new SpaceVal(fobj.getCommonMarginBlock().spaceAfter).getSpace();
+        spaceBefore = new SpaceVal(getListBlockFO().getCommonMarginBlock().spaceBefore).getSpace();
+        spaceAfter = new SpaceVal(getListBlockFO().getCommonMarginBlock().spaceAfter).getSpace();
     }
 
     private int getIPIndents() {
         int iIndents = 0;
-        iIndents += fobj.getCommonMarginBlock().startIndent.getValue();
-        iIndents += fobj.getCommonMarginBlock().endIndent.getValue();
+        iIndents += getListBlockFO().getCommonMarginBlock().startIndent.getValue();
+        iIndents += getListBlockFO().getCommonMarginBlock().endIndent.getValue();
         return iIndents;
     }
     
@@ -116,7 +122,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager {
         addBlockSpacing(adjust, spaceBefore);
         spaceBefore = null;
         
-        getPSLM().addIDToPage(fobj.getId());
+        getPSLM().addIDToPage(getListBlockFO().getId());
 
         // the list block contains areas stacked from each list item
 
@@ -181,13 +187,16 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager {
             /*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
 
             // set traits
-            TraitSetter.addBorders(curBlockArea, fobj.getCommonBorderPaddingBackground());
-            TraitSetter.addBackground(curBlockArea, fobj.getCommonBorderPaddingBackground());
+            TraitSetter.addBorders(curBlockArea, 
+                    getListBlockFO().getCommonBorderPaddingBackground());
+            TraitSetter.addBackground(curBlockArea, 
+                    getListBlockFO().getCommonBorderPaddingBackground());
             TraitSetter.addMargins(curBlockArea,
-                    fobj.getCommonBorderPaddingBackground(), 
-                    fobj.getCommonMarginBlock());
+                    getListBlockFO().getCommonBorderPaddingBackground(), 
+                    getListBlockFO().getCommonMarginBlock());
             TraitSetter.addBreaks(curBlockArea, 
-                    fobj.getBreakBefore(), fobj.getBreakAfter());
+                    getListBlockFO().getBreakBefore(), 
+                    getListBlockFO().getBreakAfter());
             
             int contentIPD = referenceIPD - getIPIndents();
             curBlockArea.setIPD(contentIPD);
@@ -220,5 +229,26 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager {
             //TODO Something to put here?
         }
     }
+    
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */
+    public boolean mustKeepTogether() {
+        //TODO Keeps will have to be more sophisticated sooner or later
+        return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() 
+                || !getListBlockFO().getKeepTogether().getWithinPage().isAuto()
+                || !getListBlockFO().getKeepTogether().getWithinColumn().isAuto();
+    }
+
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious() */
+    public boolean mustKeepWithPrevious() {
+        return !getListBlockFO().getKeepWithPrevious().getWithinPage().isAuto()
+            || !getListBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
+    }
+
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext() */
+    public boolean mustKeepWithNext() {
+        return !getListBlockFO().getKeepWithNext().getWithinPage().isAuto()
+                || !getListBlockFO().getKeepWithNext().getWithinColumn().isAuto();
+    }
+
 }
 
index 1471947183a72e5b6abb453809781871f0fa7a74..e2d8712a9e5d52e262cb333d3c6bd374d662fd20 100644 (file)
@@ -21,9 +21,9 @@ package org.apache.fop.layoutmgr.list;
 import org.apache.fop.fo.flow.ListItem;
 import org.apache.fop.fo.flow.ListItemBody;
 import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
 import org.apache.fop.layoutmgr.LayoutManager;
-import org.apache.fop.layoutmgr.LeafPosition;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.PositionIterator;
 import org.apache.fop.layoutmgr.Position;
@@ -48,8 +48,6 @@ import java.util.ListIterator;
  * The list item contains a list item label and a list item body.
  */
 public class ListItemLayoutManager extends BlockStackingLayoutManager {
-    private ListItem fobj;
-    
     private Item label;
     private Item body;
 
@@ -64,13 +62,14 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
     private MinOptMax spaceBefore;
     private MinOptMax spaceAfter;
     
+    /*
     private class ItemPosition extends LeafPosition {
         protected List cellBreaks;
         protected ItemPosition(LayoutManager lm, int pos, List l) {
             super(lm, pos);
             cellBreaks = l;
         }
-    }
+    }*/
 
     private class ListItemPosition extends Position {
         private int iLabelFirstIndex;
@@ -110,11 +109,18 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
      */
     public ListItemLayoutManager(ListItem node) {
         super(node);
-        fobj = node;
         setLabel(node.getLabel());
         setBody(node.getBody());
     }
 
+    /**
+     * Convenience method.
+     * @return the ListBlock node
+     */
+    protected ListItem getListItemFO() {
+        return (ListItem)fobj;
+    }
+
     /**
      * Create a LM for the fo:list-item-label object
      * @param node the fo:list-item-label FO
@@ -136,20 +142,18 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
     /** @see org.apache.fop.layoutmgr.AbstractLayoutManager#initProperties() */
     protected void initProperties() {
         super.initProperties();
-        spaceBefore = new SpaceVal(fobj.getCommonMarginBlock().spaceBefore).getSpace();
-        spaceAfter = new SpaceVal(fobj.getCommonMarginBlock().spaceAfter).getSpace();
+        spaceBefore = new SpaceVal(getListItemFO().getCommonMarginBlock().spaceBefore).getSpace();
+        spaceAfter = new SpaceVal(getListItemFO().getCommonMarginBlock().spaceAfter).getSpace();
     }
 
     private int getIPIndents() {
         int iIndents = 0;
-        iIndents += fobj.getCommonMarginBlock().startIndent.getValue();
-        iIndents += fobj.getCommonMarginBlock().endIndent.getValue();
+        iIndents += getListItemFO().getCommonMarginBlock().startIndent.getValue();
+        iIndents += getListItemFO().getCommonMarginBlock().endIndent.getValue();
         return iIndents;
     }
     
-    /**
-     * @see org.apache.fop.layoutmgr.LayoutManager#getNextKnuthElements(org.apache.fop.layoutmgr.LayoutContext, int)
-     */
+    /** @see org.apache.fop.layoutmgr.LayoutManager */
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
         referenceIPD = context.getRefIPD();
 
@@ -207,7 +211,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
                     start[0], end[0], start[1], end[1]);
             returnList.add(new KnuthBox(boxHeight, stepPosition, false));
             if (addedBoxHeight < totalHeight) {
-                returnList.add(new KnuthPenalty(penaltyHeight, 0, false, stepPosition, false));
+                int p = 0;
+                if (mustKeepTogether()) {
+                    p = KnuthPenalty.INFINITE;
+                }
+                returnList.add(new KnuthPenalty(penaltyHeight, p, false, stepPosition, false));
             }
         }
 
@@ -373,7 +381,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
         addBlockSpacing(adjust, spaceBefore);
         spaceBefore = null;
 
-        getPSLM().addIDToPage(fobj.getId());
+        getPSLM().addIDToPage(getListItemFO().getId());
 
         LayoutContext lc = new LayoutContext(0);
 
@@ -469,13 +477,16 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
             /*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
             
             // set traits
-            TraitSetter.addBorders(curBlockArea, fobj.getCommonBorderPaddingBackground());
-            TraitSetter.addBackground(curBlockArea, fobj.getCommonBorderPaddingBackground());
+            TraitSetter.addBorders(curBlockArea, 
+                    getListItemFO().getCommonBorderPaddingBackground());
+            TraitSetter.addBackground(curBlockArea, 
+                    getListItemFO().getCommonBorderPaddingBackground());
             TraitSetter.addMargins(curBlockArea,
-                    fobj.getCommonBorderPaddingBackground(), 
-                    fobj.getCommonMarginBlock());
+                    getListItemFO().getCommonBorderPaddingBackground(), 
+                    getListItemFO().getCommonMarginBlock());
             TraitSetter.addBreaks(curBlockArea, 
-                    fobj.getBreakBefore(), fobj.getBreakAfter());
+                    getListItemFO().getBreakBefore(), 
+                    getListItemFO().getBreakAfter());
             
             int contentIPD = referenceIPD - getIPIndents();
             curBlockArea.setIPD(contentIPD);
@@ -508,5 +519,26 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager {
             reset(null);
         }
     }
+    
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */
+    public boolean mustKeepTogether() {
+        //TODO Keeps will have to be more sophisticated sooner or later
+        return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() 
+                || !getListItemFO().getKeepTogether().getWithinPage().isAuto()
+                || !getListItemFO().getKeepTogether().getWithinColumn().isAuto();
+    }
+
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious() */
+    public boolean mustKeepWithPrevious() {
+        return !getListItemFO().getKeepWithPrevious().getWithinPage().isAuto()
+            || !getListItemFO().getKeepWithPrevious().getWithinColumn().isAuto();
+    }
+
+    /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext() */
+    public boolean mustKeepWithNext() {
+        return !getListItemFO().getKeepWithNext().getWithinPage().isAuto()
+                || !getListItemFO().getKeepWithNext().getWithinColumn().isAuto();
+    }
+
 }
 
index e64cb53f61ce84d63bae3c94f6cb69075d5efe9f..d2b86c157573cd82cccf92fac683aec100ee6c20 100644 (file)
@@ -168,6 +168,14 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
 
             // get elements from curLM
             returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            if (childLC.isKeepWithNextPending()) {
+                log.debug("child LM signals pending keep with next");
+            }
+            if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) {
+                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
+            }
+            
             if (returnedList.size() == 1
                     && ((KnuthElement) returnedList.getFirst()).isPenalty()
                     && ((KnuthPenalty) returnedList.getFirst()).getP() == -KnuthElement.INFINITE) {
@@ -192,8 +200,11 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
                     // there is a block handled by prevLM
                     // before the one handled by curLM
                     if (mustKeepTogether() 
-                            || prevLM.mustKeepWithNext()
-                            || curLM.mustKeepWithPrevious()) {
+                            || context.isKeepWithNextPending()
+                            || childLC.isKeepWithPreviousPending()) {
+                        //Clear keep pending flag
+                        context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                        childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
                         // add an infinite penalty to forbid a break between
                         // blocks
                         contentList.add(new KnuthPenalty(0,
@@ -230,6 +241,11 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
                     return returnList;
                 }
             }
+            if (childLC.isKeepWithNextPending()) {
+                //Clear and propagate
+                childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+            }
             prevLM = curLM;
         }
 
index 5b1d85d2b7f8cd9810e4861b0fb72fc5101565be..d51681c3b7efe9d0109c8ac630426cac64a815e8 100644 (file)
@@ -44,6 +44,10 @@ public class GridUnit {
     public static final int LAST_IN_BODY = 4;
     /** Indicates that the grid unit is in the last row (context: table). */
     public static final int LAST_IN_TABLE = 5;
+    /** Indicates that the primary grid unit has a pending keep-with-next. */
+    public static final int KEEP_WITH_NEXT_PENDING = 6;
+    /** Indicates that the primary grid unit has a pending keep-with-previous. */
+    public static final int KEEP_WITH_PREVIOUS_PENDING = 7;
     
     /** Primary grid unit */
     private PrimaryGridUnit primary;
index 20d3e70e265dfea85dfbdb3cf77589dbdfc5db62..d804904570416a0c3c8e273c2f0a720779a1439f 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.fop.layoutmgr.ElementListObserver;
 import org.apache.fop.layoutmgr.ElementListUtils;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.KnuthPossPosIter;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.LayoutManager;
@@ -193,6 +194,20 @@ public class TableContentLayoutManager {
             }
             createElementsForRowGroup(context, alignment, bodyType, 
                         returnList, rowGroup);
+            if (context.isKeepWithNextPending()) {
+                log.debug("child LM (row group) signals pending keep-with-next");
+            }
+            if (context.isKeepWithPreviousPending()) {
+                log.debug("child LM (row group) signals pending keep-with-previous");
+                if (returnList.size() > 0) {
+                    //Modify last penalty
+                    KnuthElement last = (KnuthElement)returnList.getLast();
+                    if (last.isPenalty()) {
+                        KnuthPenalty pen = (KnuthPenalty)last;
+                        pen.setP(KnuthPenalty.INFINITE);
+                    }
+                }
+            }
         }
         
         if (returnList.size() > 0) {
@@ -381,6 +396,15 @@ public class TableContentLayoutManager {
                                                 childLC, alignment);
                         primary.setElements(elems);
                         ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
+                        
+                        if (childLC.isKeepWithNextPending()) {
+                            log.debug("child LM signals pending keep-with-next");
+                            primary.setFlag(GridUnit.KEEP_WITH_NEXT_PENDING, true);
+                        }
+                        if (childLC.isKeepWithPreviousPending()) {
+                            log.debug("child LM signals pending keep-with-previous");
+                            primary.setFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING, true);
+                        }
                     }
 
                     
@@ -446,9 +470,10 @@ public class TableContentLayoutManager {
                 log.debug("  height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
             }
         }
+        //TODO It may make sense to reuse the stepper since it allocates quite some space
         TableStepper stepper = new TableStepper(this);
         LinkedList returnedList = stepper.getCombinedKnuthElementsForRowGroup(
-                rowGroup, maxColumnCount, bodyType);
+                context, rowGroup, maxColumnCount, bodyType);
         if (returnedList != null) {
             returnList.addAll(returnedList);
         }
index 533a5f8099e5c2895cf94c5d107bffce3113798b..d9bcfc81e0d25f211baa8623edd3460786a7a5e7 100644 (file)
@@ -182,6 +182,14 @@ public class TableLayoutManager extends BlockStackingLayoutManager
 
         contentLM = new TableContentLayoutManager(this);
         returnedList = contentLM.getNextKnuthElements(childLC, alignment);
+        if (childLC.isKeepWithNextPending()) {
+            log.debug("TableContentLM signals pending keep-with-next");
+            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+        }
+        if (childLC.isKeepWithPreviousPending()) {
+            log.debug("TableContentLM signals pending keep-with-previous");
+            context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+        }
         log.debug(returnedList);
         
         if (returnedList.size() == 1
index 21b0d44ba7927b5d7890fa80f59d9cee079f1382..391595795eb807e890e49120e0fba170c3c00276 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.fop.layoutmgr.ElementListUtils;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.table.TableContentLayoutManager.GridUnitPart;
 import org.apache.fop.layoutmgr.table.TableContentLayoutManager.TableContentPosition;
 import org.apache.fop.layoutmgr.table.TableContentLayoutManager.TableHFPenaltyPosition;
@@ -55,6 +56,7 @@ public class TableStepper {
     private int[] borderBefore;
     private int[] borderAfter;
     private boolean rowBacktrackForLastStep;
+    private boolean[] keepWithNextSignals;
     
     /**
      * Main constructor
@@ -74,6 +76,7 @@ public class TableStepper {
         baseWidth = new int[columnCount];
         borderBefore = new int[columnCount];
         borderAfter = new int[columnCount];
+        keepWithNextSignals = new boolean[columnCount];
         Arrays.fill(end, -1);
     }
     
@@ -165,6 +168,7 @@ public class TableStepper {
             end[column] = -1;
             widths[column] = 0;
             startRow[column] = activeRow;
+            keepWithNextSignals[column] = false;
         }
     }
     
@@ -176,18 +180,21 @@ public class TableStepper {
 
     /**
      * Creates the combined element list for a row group.
+     * @param context Active LayoutContext
      * @param rowGroup the row group
      * @param maxColumnCount the maximum number of columns to expect
      * @param bodyType Indicates what type of body is processed (boder, header or footer)
      * @return the combined element list
      */
-    public LinkedList getCombinedKnuthElementsForRowGroup( 
+    public LinkedList getCombinedKnuthElementsForRowGroup(
+            LayoutContext context,
             EffRow[] rowGroup, int maxColumnCount, int bodyType) {
         this.rowGroup = rowGroup;
         setup(maxColumnCount);
         initializeElementLists();
         calcTotalHeight();
         
+        boolean signalKeepWithNext = false;
         int laststep = 0;
         int step;
         int addedBoxLen = 0;
@@ -217,6 +224,30 @@ public class TableStepper {
                     } else {
                         gridUnitParts.add(new GridUnitPart(pgu, start[i], end[i]));
                     }
+                    if (end[i] + 1 == elementLists[i].size()) {
+                        if (pgu.getFlag(GridUnit.KEEP_WITH_NEXT_PENDING)) {
+                            log.debug("PGU has pending keep-with-next");
+                            keepWithNextSignals[i] = true;
+                        }
+                        if (pgu.getRow() != null && pgu.getRow().mustKeepWithNext()) {
+                            log.debug("table-row causes keep-with-next");
+                            keepWithNextSignals[i] = true;
+                        }
+                    }
+                    if (start[i] == 0 && end[i] >= 0) {
+                        if (pgu.getFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING)) {
+                            log.debug("PGU has pending keep-with-previous");
+                            if (returnList.size() == 0) {
+                                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                            }
+                        }
+                        if (pgu.getRow() != null && pgu.getRow().mustKeepWithPrevious()) {
+                            log.debug("table-row causes keep-with-previous");
+                            if (returnList.size() == 0) {
+                                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                            }
+                        }
+                    }
                 }
             }
             //log.debug(">>> guPARTS: " + gridUnitParts);
@@ -245,7 +276,11 @@ public class TableStepper {
                 }
             }
             int p = 0;
-            if (getTableLM().mustKeepTogether()) {
+            signalKeepWithNext = false;
+            for (int i = 0; i < start.length; i++) {
+                signalKeepWithNext |= keepWithNextSignals[i];
+            }
+            if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
                 p = KnuthPenalty.INFINITE;
             }
             returnList.add(new KnuthPenalty(effPenaltyLen, p, false, penaltyPos, false));
@@ -261,6 +296,11 @@ public class TableStepper {
                 activeRow++;
             }
         }
+        if (signalKeepWithNext) {
+            //Last step signalled a keep-with-next. Since the last penalty will be removed,
+            //we have to signal the still pending last keep-with-next using the LayoutContext.
+            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+        }
         return returnList;
     }