/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id: ListBlockLayoutManager.java 1642793 2014-12-02 00:29:57Z lbernardo $ */

package org.apache.fop.layoutmgr.list;

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.ListBlock;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;

LayoutManager for a list-block FO. A list block contains list items which are stacked within the list block area..
/** * LayoutManager for a list-block FO. * A list block contains list items which are stacked within * the list block area.. */
public class ListBlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager {
logging instance
/** logging instance */
private static Log log = LogFactory.getLog(ListBlockLayoutManager.class); private Block curBlockArea;
Create a new list block layout manager.
Params:
  • node – list-block to create the layout manager for
/** * Create a new list block layout manager. * @param node list-block to create the layout manager for */
public ListBlockLayoutManager(ListBlock node) { super(node); } @Override protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return getListBlockFO().getCommonBorderPaddingBackground(); }
Convenience method.
Returns:the ListBlock node
/** * Convenience method. * @return the ListBlock node */
protected ListBlock getListBlockFO() { return (ListBlock)fobj; }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void initialize() { foSpaceBefore = new SpaceVal( getListBlockFO().getCommonMarginBlock().spaceBefore, this).getSpace(); foSpaceAfter = new SpaceVal( getListBlockFO().getCommonMarginBlock().spaceAfter, this).getSpace(); startIndent = getListBlockFO().getCommonMarginBlock().startIndent.getValue(this); endIndent = getListBlockFO().getCommonMarginBlock().endIndent.getValue(this); } private void resetSpaces() { this.discardBorderBefore = false; this.discardBorderAfter = false; this.discardPaddingBefore = false; this.discardPaddingAfter = false; this.effSpaceBefore = null; this.effSpaceAfter = null; }
{@inheritDoc}
/** {@inheritDoc} */
public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, Position restartPosition, LayoutManager restartAtLM) { resetSpaces(); List returnList; returnList = super.getNextKnuthElements(context, alignment, lmStack, restartPosition, restartAtLM); //fox:widow-content-limit int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue(); if (widowRowLimit != 0) { ElementListUtils.removeLegalBreaks(returnList, widowRowLimit); } //fox:orphan-content-limit int orphanRowLimit = getListBlockFO().getOrphanContentLimit().getValue(); if (orphanRowLimit != 0) { ElementListUtils.removeLegalBreaksFromEnd(returnList, orphanRowLimit); } return returnList; }
A list block generates one or more normal block areas whose child areas are normal block areas returned by the children of fo:list-block. See XSL-FO 1.1 6.8.2.
Params:
  • parentIter – the position iterator
  • layoutContext – the layout context for adding areas
/** * A list block generates one or more normal block areas whose child areas are * normal block areas returned by the children of fo:list-block. See XSL-FO 1.1 6.8.2. * * @param parentIter the position iterator * @param layoutContext the layout context for adding areas */
@Override public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); // if this will create the first block area in a page // and display-align is after or center, add space before if (layoutContext.getSpaceBefore() > 0) { addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); } addId(); // the list block contains areas stacked from each list item LayoutManager childLM; LayoutContext lc = LayoutContext.offspringOf(layoutContext); LayoutManager firstLM = null; LayoutManager lastLM = null; Position firstPos = null; Position lastPos = null; // "unwrap" the NonLeafPositions stored in parentIter // and put them in a new list; LinkedList<Position> positionList = new LinkedList<Position>(); Position pos; while (parentIter.hasNext()) { pos = parentIter.next(); if (pos.getIndex() >= 0) { if (firstPos == null) { firstPos = pos; } lastPos = pos; } if (pos instanceof NonLeafPosition && (pos.getPosition() != null) && pos.getPosition().getLM() != this) { // pos was created by a child of this ListBlockLM positionList.add(pos.getPosition()); lastLM = pos.getPosition().getLM(); if (firstLM == null) { firstLM = lastLM; } } } registerMarkers(true, isFirst(firstPos), isLast(lastPos)); PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); while ((childLM = childPosIter.getNextChildLM()) != null) { // Add the block areas to Area // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM); lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM); lc.setStackLimitBP(layoutContext.getStackLimitBP()); childLM.addAreas(childPosIter, lc); } registerMarkers(false, isFirst(firstPos), isLast(lastPos)); // We are done with this area add the background TraitSetter.addBackground(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), this); TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), effSpaceBefore, effSpaceAfter); flush(); curBlockArea = null; resetSpaces(); checkEndOfLayout(lastPos); }
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.
Params:
  • childArea – the child area
Returns:the parent area of the child
/** * 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 */
@Override public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); // Set up dimensions // Must get dimensions from parent area /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // set traits TraitSetter.setProducerID(curBlockArea, getListBlockFO().getId()); TraitSetter.addBorders(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), discardBorderBefore, discardBorderAfter, false, false, this); TraitSetter.addPadding(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), discardPaddingBefore, discardPaddingAfter, false, false, this); TraitSetter.addMargins(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), getListBlockFO().getCommonMarginBlock(), this); TraitSetter.addBreaks(curBlockArea, getListBlockFO().getBreakBefore(), getListBlockFO().getBreakAfter()); int contentIPD = referenceIPD - getIPIndents(); curBlockArea.setIPD(contentIPD); curBlockArea.setBidiLevel(getListBlockFO().getBidiLevel()); setCurrentArea(curBlockArea); } return curBlockArea; }
Add the child area to this layout manager.
Params:
  • childArea – the child area to add
/** * Add the child area to this layout manager. * * @param childArea the child area to add */
@Override public void addChildArea(Area childArea) { if (curBlockArea != null) { curBlockArea.addBlock((Block) childArea); } }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepTogetherProperty() { return getListBlockFO().getKeepTogether(); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepWithPreviousProperty() { return getListBlockFO().getKeepWithPrevious(); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepWithNextProperty() { return getListBlockFO().getKeepWithNext(); }
{@inheritDoc}
/** {@inheritDoc} */
public boolean isRestartable() { return true; } }