/*
 * 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: ListItemLayoutManager.java 1826976 2018-03-16 11:42:38Z ssteiner $ */

package org.apache.fop.layoutmgr.list;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
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.ListItem;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.BreakOpportunityHelper;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.FloatContentLayoutManager;
import org.apache.fop.layoutmgr.FootenoteUtil;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.KnuthBlockBox;
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;
import org.apache.fop.layoutmgr.LeafPosition;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpaceResolver;
import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.SpaceVal;
import org.apache.fop.util.BreakUtil;

LayoutManager for a list-item FO. The list item contains a list item label and a list item body.
/** * LayoutManager for a list-item FO. * The list item contains a list item label and a list item body. */
public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManager implements BreakOpportunity {
logging instance
/** logging instance */
private static Log log = LogFactory.getLog(ListItemLayoutManager.class); private ListItemContentLayoutManager label; private ListItemContentLayoutManager body; private Block curBlockArea; private List<ListElement> labelList; private List<ListElement> bodyList; private Keep keepWithNextPendingOnLabel; private Keep keepWithNextPendingOnBody; public class ListItemPosition extends Position { private int labelFirstIndex; private int labelLastIndex; private int bodyFirstIndex; private int bodyLastIndex; private Position originalLabelPosition; private Position originalBodyPosition; public ListItemPosition(LayoutManager lm, int labelFirst, int labelLast, int bodyFirst, int bodyLast) { super(lm); labelFirstIndex = labelFirst; labelLastIndex = labelLast; bodyFirstIndex = bodyFirst; bodyLastIndex = bodyLast; } public int getLabelFirstIndex() { return labelFirstIndex; } public int getLabelLastIndex() { return labelLastIndex; } public int getBodyFirstIndex() { return bodyFirstIndex; } public int getBodyLastIndex() { return bodyLastIndex; }
{@inheritDoc}
/** {@inheritDoc} */
public boolean generatesAreas() { return true; }
{@inheritDoc}
/** {@inheritDoc} */
public String toString() { StringBuffer sb = new StringBuffer("ListItemPosition:"); sb.append(getIndex()).append("("); sb.append("label:").append(labelFirstIndex).append("-").append(labelLastIndex); sb.append(" body:").append(bodyFirstIndex).append("-").append(bodyLastIndex); sb.append(")"); return sb.toString(); } public Position getOriginalLabelPosition() { return originalLabelPosition; } public void setOriginalLabelPosition(Position originalLabelPosition) { this.originalLabelPosition = originalLabelPosition; } public Position getOriginalBodyPosition() { return originalBodyPosition; } public void setOriginalBodyPosition(Position originalBodyPosition) { this.originalBodyPosition = originalBodyPosition; } }
Create a new list item layout manager.
Params:
  • node – list-item to create the layout manager for
/** * Create a new list item layout manager. * @param node list-item to create the layout manager for */
public ListItemLayoutManager(ListItem node) { super(node); setLabel(node.getLabel()); setBody(node.getBody()); } @Override protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return getListItemFO().getCommonBorderPaddingBackground(); }
Convenience method.
Returns:the ListBlock node
/** * Convenience method. * @return the ListBlock node */
protected ListItem getListItemFO() { return (ListItem)fobj; }
Create a LM for the fo:list-item-label object
Params:
  • node – the fo:list-item-label FO
/** * Create a LM for the fo:list-item-label object * @param node the fo:list-item-label FO */
public void setLabel(ListItemLabel node) { label = new ListItemContentLayoutManager(node); label.setParent(this); }
Create a LM for the fo:list-item-body object
Params:
  • node – the fo:list-item-body FO
/** * Create a LM for the fo:list-item-body object * @param node the fo:list-item-body FO */
public void setBody(ListItemBody node) { body = new ListItemContentLayoutManager(node); body.setParent(this); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void initialize() { foSpaceBefore = new SpaceVal( getListItemFO().getCommonMarginBlock().spaceBefore, this).getSpace(); foSpaceAfter = new SpaceVal( getListItemFO().getCommonMarginBlock().spaceAfter, this).getSpace(); startIndent = getListItemFO().getCommonMarginBlock().startIndent.getValue(this); endIndent = getListItemFO().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) { referenceIPD = context.getRefIPD(); LayoutContext childLC; List<ListElement> returnList = new LinkedList<ListElement>(); if (!breakBeforeServed(context, returnList)) { return returnList; } addFirstVisibleMarks(returnList, context, alignment); // label childLC = makeChildLayoutContext(context); childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); label.initialize(); boolean labelDone = false; Stack labelLMStack = null; Position labelRestartPosition = null; LayoutManager labelRestartLM = null; if (restartPosition != null && restartPosition instanceof ListItemPosition) { ListItemPosition lip = (ListItemPosition) restartPosition; if (lip.labelLastIndex <= lip.labelFirstIndex) { labelDone = true; } else { labelRestartPosition = lip.getOriginalLabelPosition(); labelRestartLM = labelRestartPosition.getLM(); LayoutManager lm = labelRestartLM; labelLMStack = new Stack(); while (lm != this) { labelLMStack.push(lm); lm = lm.getParent(); if (lm instanceof ListItemContentLayoutManager) { lm = lm.getParent(); } } } } labelList = !labelDone ? label.getNextKnuthElements(childLC, alignment, labelLMStack, labelRestartPosition, labelRestartLM) : (List) new LinkedList<KnuthElement>(); //Space resolution as if the contents were placed in a new reference area //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph) SpaceResolver.resolveElementList(labelList); ElementListObserver.observe(labelList, "list-item-label", label.getPartFO().getId()); context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); this.keepWithNextPendingOnLabel = childLC.getKeepWithNextPending(); // body childLC = makeChildLayoutContext(context); childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); body.initialize(); boolean bodyDone = false; Stack bodyLMStack = null; Position bodyRestartPosition = null; LayoutManager bodyRestartLM = null; if (restartPosition != null && restartPosition instanceof ListItemPosition) { ListItemPosition lip = (ListItemPosition) restartPosition; if (lip.bodyLastIndex <= lip.bodyFirstIndex) { bodyDone = true; } else { bodyRestartPosition = lip.getOriginalBodyPosition(); bodyRestartLM = bodyRestartPosition.getLM(); LayoutManager lm = bodyRestartLM; bodyLMStack = new Stack(); while (lm != this) { bodyLMStack.push(lm); lm = lm.getParent(); if (lm instanceof ListItemContentLayoutManager) { lm = lm.getParent(); } } } } bodyList = !bodyDone ? body.getNextKnuthElements(childLC, alignment, bodyLMStack, bodyRestartPosition, bodyRestartLM) : (List) new LinkedList<KnuthElement>(); //Space resolution as if the contents were placed in a new reference area //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph) SpaceResolver.resolveElementList(bodyList); ElementListObserver.observe(bodyList, "list-item-body", body.getPartFO().getId()); context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending(); List<ListElement> returnedList = new LinkedList<ListElement>(); if (!labelList.isEmpty() && labelList.get(0) instanceof KnuthBlockBox) { KnuthBlockBox kbb = (KnuthBlockBox) labelList.get(0); if (kbb.getWidth() == 0 && kbb.hasFloatAnchors()) { List<FloatContentLayoutManager> floats = kbb.getFloatContentLMs(); returnedList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats)); Keep keep = getKeepTogether(); returnedList.add(new BreakElement(new LeafPosition(this, 0), keep.getPenalty(), keep .getContext(), context)); labelList.remove(0); labelList.remove(0); } } if (!bodyList.isEmpty() && bodyList.get(0) instanceof KnuthBlockBox) { KnuthBlockBox kbb = (KnuthBlockBox) bodyList.get(0); if (kbb.getWidth() == 0 && kbb.hasFloatAnchors()) { List<FloatContentLayoutManager> floats = kbb.getFloatContentLMs(); returnedList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats)); Keep keep = getKeepTogether(); returnedList.add(new BreakElement(new LeafPosition(this, 0), keep.getPenalty(), keep .getContext(), context)); bodyList.remove(0); bodyList.remove(0); } } // create a combined list returnedList.addAll(getCombinedKnuthElementsForListItem(labelList, bodyList, context)); // "wrap" the Position inside each element wrapPositionElements(returnedList, returnList, true); addLastVisibleMarks(returnList, context, alignment); addKnuthElementsForBreakAfter(returnList, context); context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); context.updateKeepWithNextPending(getKeepWithNext()); context.updateKeepWithPreviousPending(getKeepWithPrevious()); setFinished(true); resetSpaces(); return returnList; }
Overridden to unconditionally add elements for space-before. {@inheritDoc}
/** * Overridden to unconditionally add elements for space-before. * {@inheritDoc} */
@Override protected void addFirstVisibleMarks(List<ListElement> elements, LayoutContext context, int alignment) { addKnuthElementsForSpaceBefore(elements, alignment); addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); firstVisibleMarkServed = true; //Spaces, border and padding to be repeated at each break addPendingMarks(context); } private List getCombinedKnuthElementsForListItem(List<ListElement> labelElements, List<ListElement> bodyElements, LayoutContext context) { // Copy elements to array lists to improve element access performance List[] elementLists = {new ArrayList<ListElement>(labelElements), new ArrayList<ListElement>(bodyElements)}; int[] fullHeights = {ElementListUtils.calcContentLength(elementLists[0]), ElementListUtils.calcContentLength(elementLists[1])}; int[] partialHeights = {0, 0}; int[] start = {-1, -1}; int[] end = {-1, -1}; int totalHeight = Math.max(fullHeights[0], fullHeights[1]); int step; int addedBoxHeight = 0; Keep keepWithNextActive = Keep.KEEP_AUTO; LinkedList<ListElement> returnList = new LinkedList<ListElement>(); while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { if (end[0] + 1 == elementLists[0].size()) { keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnLabel); } if (end[1] + 1 == elementLists[1].size()) { keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnBody); } // compute penalty height and box height int penaltyHeight = step + getMaxRemainingHeight(fullHeights, partialHeights) - totalHeight; //Additional penalty height from penalties in the source lists int additionalPenaltyHeight = 0; int stepPenalty = 0; int breakClass = EN_AUTO; KnuthElement endEl = elementLists[0].size() > 0 ? (KnuthElement) elementLists[0].get(end[0]) : null; Position originalLabelPosition = (endEl != null && endEl.getPosition() != null) ? endEl.getPosition().getPosition() : null; if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = endEl.getWidth(); stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math .max(stepPenalty, endEl.getPenalty()); breakClass = BreakUtil.compareBreakClasses(breakClass, ((KnuthPenalty) endEl).getBreakClass()); } endEl = elementLists[1].size() > 0 ? (KnuthElement) elementLists[1].get(end[1]) : null; Position originalBodyPosition = (endEl != null && endEl.getPosition() != null) ? endEl.getPosition().getPosition() : null; if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = Math.max( additionalPenaltyHeight, endEl.getWidth()); stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math .max(stepPenalty, endEl.getPenalty()); breakClass = BreakUtil.compareBreakClasses(breakClass, ((KnuthPenalty) endEl).getBreakClass()); } int boxHeight = step - addedBoxHeight - penaltyHeight; penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight! // collect footnote information // TODO this should really not be done like this. ListItemLM should remain as // footnote-agnostic as possible LinkedList<LayoutManager> footnoteList = new LinkedList<LayoutManager>(); for (int i = 0; i < elementLists.length; i++) { footnoteList.addAll(FootenoteUtil.getFootnotes(elementLists[i], start[i], end[i])); } LinkedList<FloatContentLayoutManager> floats = new LinkedList<FloatContentLayoutManager>(); for (int i = 0; i < elementLists.length; i++) { floats.addAll(FloatContentLayoutManager.checkForFloats(elementLists[i], start[i], end[i])); } // add the new elements addedBoxHeight += boxHeight; ListItemPosition stepPosition = new ListItemPosition(this, start[0], end[0], start[1], end[1]); stepPosition.setOriginalLabelPosition(originalLabelPosition); stepPosition.setOriginalBodyPosition(originalBodyPosition); if (floats.isEmpty()) { returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); } else { // add a line with height zero and no content and attach float to it returnList.add(new KnuthBlockBox(0, Collections.emptyList(), stepPosition, false, floats)); // add a break element to signal that we should restart LB at this break Keep keep = getKeepTogether(); returnList.add(new BreakElement(stepPosition, keep.getPenalty(), keep.getContext(), context)); // add the original line where the float was but without the float now returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); } if (originalBodyPosition != null) { LayoutManager lm = originalBodyPosition.getLM(); if ((lm instanceof ListBlockLayoutManager || lm instanceof BlockLayoutManager) && getKeepWithPrevious().isAuto()) { stepPenalty++; } } if (addedBoxHeight < totalHeight) { Keep keep = keepWithNextActive.compare(getKeepTogether()); int p = stepPenalty; if (p > -KnuthElement.INFINITE) { p = Math.max(p, keep.getPenalty()); breakClass = keep.getContext(); } returnList.add(new BreakElement(stepPosition, penaltyHeight, p, breakClass, context)); } } return returnList; } private int getNextStep(List[] elementLists, int[] start, int[] end, int[] partialHeights) { // backup of partial heights int[] backupHeights = {partialHeights[0], partialHeights[1]}; // set starting points start[0] = end[0] + 1; start[1] = end[1] + 1; // get next possible sequence for label and body int seqCount = 0; for (int i = 0; i < start.length; i++) { while (end[i] + 1 < elementLists[i].size()) { end[i]++; KnuthElement el = (KnuthElement)elementLists[i].get(end[i]); if (el.isPenalty()) { if (el.getPenalty() < KnuthElement.INFINITE) { //First legal break point break; } } else if (el.isGlue()) { if (end[i] > 0) { KnuthElement prev = (KnuthElement)elementLists[i].get(end[i] - 1); if (prev.isBox()) { //Second legal break point break; } } partialHeights[i] += el.getWidth(); } else { partialHeights[i] += el.getWidth(); } } if (end[i] < start[i]) { partialHeights[i] = backupHeights[i]; } else { seqCount++; } } if (seqCount == 0) { return 0; } // determine next step int step; if (backupHeights[0] == 0 && backupHeights[1] == 0) { // this is the first step: choose the maximum increase, so that // the smallest area in the first page will contain at least // a label area and a body area step = Math.max((end[0] >= start[0] ? partialHeights[0] : Integer.MIN_VALUE), (end[1] >= start[1] ? partialHeights[1] : Integer.MIN_VALUE)); } else { // this is not the first step: choose the minimum increase step = Math.min((end[0] >= start[0] ? partialHeights[0] : Integer.MAX_VALUE), (end[1] >= start[1] ? partialHeights[1] : Integer.MAX_VALUE)); } // reset bigger-than-step sequences for (int i = 0; i < partialHeights.length; i++) { if (partialHeights[i] > step) { partialHeights[i] = backupHeights[i]; end[i] = start[i] - 1; } } return step; } private int getMaxRemainingHeight(int[] fullHeights, int[] partialHeights) { return Math.max(fullHeights[0] - partialHeights[0], fullHeights[1] - partialHeights[1]); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public List getChangedKnuthElements(List oldList, int alignment) { // label labelList = label.getChangedKnuthElements(labelList, alignment); // body // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); KnuthElement oldElement; while (oldListIterator.hasNext()) { oldElement = (KnuthElement)oldListIterator.next(); Position innerPosition = oldElement.getPosition().getPosition(); if (innerPosition != null) { // oldElement was created by a descendant of this BlockLM oldElement.setPosition(innerPosition); } else { // thisElement was created by this BlockLM // modify its position in order to recognize it was not created // by a child oldElement.setPosition(new Position(this)); } } List returnedList = body.getChangedKnuthElements(oldList, alignment); // "wrap" the Position inside each element List tempList = returnedList; KnuthElement tempElement; returnedList = new LinkedList(); for (Object aTempList : tempList) { tempElement = (KnuthElement) aTempList; tempElement.setPosition(new NonLeafPosition(this, tempElement.getPosition())); returnedList.add(tempElement); } return returnedList; } @Override public boolean hasLineAreaDescendant() { return label.hasLineAreaDescendant() || body.hasLineAreaDescendant(); } @Override public int getBaselineOffset() { if (label.hasLineAreaDescendant()) { return label.getBaselineOffset(); } else if (body.hasLineAreaDescendant()) { return body.getBaselineOffset(); } else { throw newNoLineAreaDescendantException(); } }
Add the areas for the break points.
Params:
  • parentIter – the position iterator
  • layoutContext – the layout context for adding areas
/** * Add the areas for the break points. * * @param parentIter the position iterator * @param layoutContext the layout context for adding areas */
@Override public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); addId(); LayoutContext lc = LayoutContext.offspringOf(layoutContext); Position firstPos = null; Position lastPos = null; // "unwrap" the NonLeafPositions stored in parentIter 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 contains a ListItemPosition created by this ListBlockLM positionList.add(pos.getPosition()); } } if (positionList.isEmpty()) { reset(); return; } registerMarkers(true, isFirst(firstPos), isLast(lastPos)); // use the first and the last ListItemPosition to determine the // corresponding indexes in the original labelList and bodyList int labelFirstIndex = ((ListItemPosition) positionList.getFirst()).getLabelFirstIndex(); int labelLastIndex = ((ListItemPosition) positionList.getLast()).getLabelLastIndex(); int bodyFirstIndex = ((ListItemPosition) positionList.getFirst()).getBodyFirstIndex(); int bodyLastIndex = ((ListItemPosition) positionList.getLast()).getBodyLastIndex(); //Determine previous break if any (in item label list) int previousBreak = ElementListUtils.determinePreviousBreak(labelList, labelFirstIndex); SpaceResolver.performConditionalsNotification(labelList, labelFirstIndex, labelLastIndex, previousBreak); //Determine previous break if any (in item body list) previousBreak = ElementListUtils.determinePreviousBreak(bodyList, bodyFirstIndex); SpaceResolver.performConditionalsNotification(bodyList, bodyFirstIndex, bodyLastIndex, previousBreak); // add label areas if (labelFirstIndex <= labelLastIndex) { KnuthPossPosIter labelIter = new KnuthPossPosIter(labelList, labelFirstIndex, labelLastIndex + 1); lc.setFlags(LayoutContext.FIRST_AREA, layoutContext.isFirstArea()); lc.setFlags(LayoutContext.LAST_AREA, layoutContext.isLastArea()); // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the label lc.setStackLimitBP(layoutContext.getStackLimitBP()); label.addAreas(labelIter, lc); } // add body areas if (bodyFirstIndex <= bodyLastIndex) { KnuthPossPosIter bodyIter = new KnuthPossPosIter(bodyList, bodyFirstIndex, bodyLastIndex + 1); lc.setFlags(LayoutContext.FIRST_AREA, layoutContext.isFirstArea()); lc.setFlags(LayoutContext.LAST_AREA, layoutContext.isLastArea()); // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the body lc.setStackLimitBP(layoutContext.getStackLimitBP()); body.addAreas(bodyIter, lc); } // after adding body areas, set the maximum area bpd int childCount = curBlockArea.getChildAreas().size(); assert childCount >= 1 && childCount <= 2; int itemBPD = ((Block)curBlockArea.getChildAreas().get(0)).getAllocBPD(); if (childCount == 2) { itemBPD = Math.max(itemBPD, ((Block)curBlockArea.getChildAreas().get(1)).getAllocBPD()); } curBlockArea.setBPD(itemBPD); registerMarkers(false, isFirst(firstPos), isLast(lastPos)); // We are done with this area add the background TraitSetter.addBackground(curBlockArea, getListItemFO().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 are for 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 are for the child */
@Override public Area getParentArea(Area childArea) { if (curBlockArea == null) { curBlockArea = new Block(); // Set up dimensions /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // set traits ListItem fo = getListItemFO(); TraitSetter.setProducerID(curBlockArea, fo.getId()); TraitSetter.addBorders(curBlockArea, fo.getCommonBorderPaddingBackground(), discardBorderBefore, discardBorderAfter, false, false, this); TraitSetter.addPadding(curBlockArea, fo.getCommonBorderPaddingBackground(), discardPaddingBefore, discardPaddingAfter, false, false, this); TraitSetter.addMargins(curBlockArea, fo.getCommonBorderPaddingBackground(), fo.getCommonMarginBlock(), this); TraitSetter.addBreaks(curBlockArea, fo.getBreakBefore(), fo.getBreakAfter()); int contentIPD = referenceIPD - getIPIndents(); curBlockArea.setIPD(contentIPD); curBlockArea.setBidiLevel(fo.getBidiLevel()); setCurrentArea(curBlockArea); } return curBlockArea; }
Add the child. Rows return the areas returned by the child elements. This simply adds the area to the parent layout manager.
Params:
  • childArea – the child area
/** * 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 */
@Override public void addChildArea(Area childArea) { if (curBlockArea != null) { curBlockArea.addBlock((Block) childArea); } }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepTogetherProperty() { return getListItemFO().getKeepTogether(); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepWithPreviousProperty() { return getListItemFO().getKeepWithPrevious(); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public KeepProperty getKeepWithNextProperty() { return getListItemFO().getKeepWithNext(); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void reset() { super.reset(); label.reset(); body.reset(); } @Override public int getBreakBefore() { int breakBefore = BreakOpportunityHelper.getBreakBefore(this); breakBefore = BreakUtil.compareBreakClasses(breakBefore, label.getBreakBefore()); breakBefore = BreakUtil.compareBreakClasses(breakBefore, body.getBreakBefore()); return breakBefore; }
{@inheritDoc}
/** {@inheritDoc} */
public boolean isRestartable() { return true; } }