/* * $Id: Caption.java,v 1.9 2003/03/07 07:58:51 jeremias Exp $ * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "FOP" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ============================================================================ * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation and was originally created by * James Tauber . For more information on the Apache * Software Foundation, please see . */ package org.apache.fop.layoutmgr.table; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutProcessor; 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.area.Area; import org.apache.fop.area.Block; import org.apache.fop.traits.MinOptMax; import java.util.ArrayList; import java.util.List; /** * 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 List childBreaks = new ArrayList(); /** * Create a new Caption layout manager. * */ public Caption() { } /** * 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) { LayoutProcessor 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); boolean over = false; while (!curLM.isFinished()) { if ((bp = curLM.getNextBreakPoss(childLC)) != null) { if (stackSize.opt + bp.getStackingSize().opt > context.getStackLimit().max) { // reset to last break if (lastPos != null) { LayoutProcessor lm = lastPos.getLayoutManager(); lm.resetPosition(lastPos.getPosition()); if (lm != curLM) { curLM.resetPosition(null); } } else { curLM.resetPosition(null); } over = true; break; } stackSize.add(bp.getStackingSize()); lastPos = bp; childBreaks.add(bp); if (bp.nextBreakOverflows()) { over = true; break; } childLC.setStackLimit(MinOptMax.subtract( context.getStackLimit(), stackSize)); } } BreakPoss breakPoss = new BreakPoss( new LeafPosition(this, childBreaks.size() - 1)); if (over) { breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true); } 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(); LayoutProcessor 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 */ public void addChild(Area childArea) { if (curBlockArea != null) { curBlockArea.addBlock((Block) childArea); } } /** * Reset the layout position. * * @param resetPos the position to reset to */ public void resetPosition(Position resetPos) { if (resetPos == null) { reset(null); } } }