aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
diff options
context:
space:
mode:
authorKaren Lease <klease@apache.org>2001-11-09 21:57:47 +0000
committerKaren Lease <klease@apache.org>2001-11-09 21:57:47 +0000
commit76a43e26132766467c569b7938ed27cac5354dd2 (patch)
tree0607831b535dc111fe779658ca64e2fcd6b503ab /src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
parentff410b19d4e05d70bce945efb29e496d2bd2acc4 (diff)
downloadxmlgraphics-fop-76a43e26132766467c569b7938ed27cac5354dd2.tar.gz
xmlgraphics-fop-76a43e26132766467c569b7938ed27cac5354dd2.zip
First versions of LayoutManager classes
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194539 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java')
-rw-r--r--src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
new file mode 100644
index 000000000..8a550b96c
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
@@ -0,0 +1,198 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 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.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.BlockParent;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.Iterator;
+
+/**
+ * Base LayoutManager class for all areas which stack their child
+ * areas in the block-progression direction, such as Flow, Block, ListBlock.
+ */
+public abstract class BlockStackingLayoutManager
+ extends AbstractLayoutManager {
+ /** Reference to FO whose areas it's managing or to the traits
+ * of the FO.
+ */
+ LayoutManager curChildLM = null;
+ BlockParent parentArea = null;
+
+ public BlockStackingLayoutManager(FObj fobj) {
+ super(fobj);
+ }
+
+
+
+ public boolean splitArea(Area area, SplitContext splitContext) {
+ // Divide area so that it will be within targetLength if possible
+ // If not, it can be shorter, but not longer.
+ /* Iterate over contents of the area. */
+
+ // Need to figure out if we can do this generically
+ // Logically a BlockStacking LM only handles Block-type areas
+ if (!(area instanceof BlockParent)) {
+ return false;
+ }
+ Iterator areaIter = ((BlockParent)area).getChildAreas().iterator();
+
+
+ BreakCost minBreakCost = null;
+ MinOptMax remainBPD = splitContext.targetBPD;
+ splitContext.nextArea = area;
+
+ while (areaIter.hasNext()) {
+ Area childArea = (Area)areaIter.next();
+ if (remainBPD.max < childArea.getAllocationBPD().min) {
+ // Past the end point: try to break it
+ // TODO: get a LayoutManager to do the split of the child
+ // area, either Area => LM or Area => gen FO => LM
+ LayoutManager childLM = childArea.getGeneratingFObj().
+ getLayoutManager();
+ splitContext.targetBPD = remainBPD;
+ if (childLM.splitArea(childArea, splitContext) == false) {
+ // Can't split, so must split this area before childArea
+ // Can we pass the iter?
+ // If already saw several a potential break, use it
+ if (minBreakCost != null) {
+ /* Split 'area', placing all children after
+ * minBreakCost.getArea() into a new area,
+ * which we store in the splitContext.
+ */
+ // splitContext.nextArea = area.splitAfter(minBreakCost.getArea());
+ }
+ else {
+ /* This area will be shorter than the desired minimum.
+ * Split before the current childArea (which will be
+ * the first area in the newly created Area.
+ */
+ //splitContext.nextArea = area.splitBefore(childArea);
+ }
+ }
+ else return true; // childLM has done the work for us!
+ // Set cost, dimension ???
+ break;
+ }
+ else {
+ remainBPD.subtract(childArea.getAllocationBPD());
+ if (remainBPD.min < 0) {
+ // Potential breakpoint: remember break Position and
+ // break "cost" (constraint violation)
+ BreakCost breakCost = evaluateBreakCost(area, childArea);
+ minBreakCost = breakCost.chooseLowest(minBreakCost);
+ }
+ }
+ //Note: size of area when split can depend on conditional
+ // space, border and padding of the split area!!!
+ }
+ // True if some part of area can be placed, false if none is placed
+ return (splitContext.nextArea != area);
+
+ }
+
+ private BreakCost evaluateBreakCost(Area parent, Area child) {
+ return new BreakCost(child,0);
+ }
+
+ /** return current area being filled
+ */
+ protected BlockParent getCurrentArea() {
+ return this.parentArea;
+ }
+
+
+ /**
+ * Set the current area being filled.
+ */
+ protected void setCurrentArea(BlockParent parentArea) {
+ this.parentArea = parentArea;
+ }
+
+
+
+ protected MinOptMax resolveSpaceSpecifier(Area nextArea) {
+ SpaceSpecifier spaceSpec = new SpaceSpecifier();
+// Area prevArea = getCurrentArea().getLast();
+// if (prevArea != null) {
+// spaceSpec.addSpace(prevArea.getSpaceAfter());
+// }
+// spaceSpec.addSpace(nextArea.getSpaceBefore());
+ return spaceSpec.resolve();
+ }
+
+ /**
+ * Add the childArea to the passed area.
+ * Called by child LayoutManager when it has filled one of its areas.
+ * The LM should already have an Area in which to put the child.
+ * See if the area will fit in the current area.
+ * If so, add it. Otherwise initiate breaking.
+ * @param childArea the area to add: will be some block-stacked Area.
+ * @param parentArea the area in which to add the childArea
+ */
+ protected void addChildToArea(Area childArea, BlockParent parentArea) {
+ // This should be a block-level Area (Block in the generic sense)
+ if (!(childArea instanceof Block)) {
+ System.err.println("Child not a Block in BlockStackingLM!");
+ return;
+ }
+
+ // See if the whole thing fits, including space before
+ // Calculate space between last child in curFlow and childArea
+ MinOptMax targetDim = parentArea.getAvailBPD();
+ MinOptMax spaceBefore = resolveSpaceSpecifier(childArea) ;
+ targetDim.subtract(spaceBefore);
+ if (targetDim.max >= childArea.getAllocationBPD().min) {
+ //parentArea.addBlock(new InterBlockSpace(spaceBefore));
+ parentArea.addBlock((Block)childArea);
+ return;
+ }
+ else {
+ // Probably need something like max BPD so we don't get into
+ // infinite loops with large unbreakable chunks
+ SplitContext splitContext = new SplitContext(targetDim);
+
+ LayoutManager childLM = childArea.getGeneratingFObj().
+ getLayoutManager();
+ if (childLM.splitArea(childArea, splitContext)) {
+ //parentArea.addBlock(new InterBlockSpace(spaceBefore));
+ parentArea.addBlock((Block)childArea);
+ }
+ flush(); // hand off current area to parent
+ getParentArea(splitContext.nextArea);
+ // Check that reference IPD hasn't changed!!!
+ // If it has, we must "reflow" the content
+ addChild(splitContext.nextArea);
+ }
+ }
+
+
+ /**
+ * Add the childArea to the current area.
+ * Called by child LayoutManager when it has filled one of its areas.
+ * The LM should already have an Area in which to put the child.
+ * See if the area will fit in the current area.
+ * If so, add it. Otherwise initiate breaking.
+ * @param childArea the area to add: will be some block-stacked Area.
+ */
+ public void addChild(Area childArea) {
+ addChildToArea((Block)childArea, getCurrentArea());
+ }
+
+ /**
+ * Force current area to be added to parent area.
+ */
+ protected void flush() {
+ parentLM.addChild(getCurrentArea());
+ }
+
+
+}