blob: b16c9dfc47fc02b83bf52dc9e7fbdf14b9feea6c [file] [log] [blame]
/*
* 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$ */
package org.apache.fop.layoutmgr.list;
import java.util.LinkedList;
import java.util.List;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
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.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
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.SpaceHandlingBreakPosition;
import org.apache.fop.layoutmgr.TraitSetter;
/**
* LayoutManager for a list-item-label or list-item-body FO.
*/
public class ListItemContentLayoutManager extends BlockStackingLayoutManager implements BreakOpportunity {
private Block curBlockArea;
private int xOffset;
private int itemIPD;
/**
* Create a new Cell layout manager.
* @param node list-item-label node
*/
public ListItemContentLayoutManager(ListItemLabel node) {
super(node);
}
/**
* Create a new Cell layout manager.
* @param node list-item-body node
*/
public ListItemContentLayoutManager(ListItemBody node) {
super(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
* of the list item within the parent block area.
*
* @param off the x offset
*/
public void setXOffset(int off) {
xOffset = off;
}
/**
* Add the areas for the break points.
* The list item contains block stacking layout managers
* that add block areas.
*
* @param parentIter the iterator of the break positions
* @param layoutContext the layout context for adding the areas
*/
@Override
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext) {
getParentArea(null);
addId();
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 == null) {
continue;
}
if (pos.getIndex() >= 0) {
if (firstPos == null) {
firstPos = pos;
}
lastPos = pos;
}
if (pos instanceof NonLeafPosition) {
// pos was created by a child of this ListBlockLM
positionList.add(pos.getPosition());
lastLM = pos.getPosition().getLM();
if (firstLM == null) {
firstLM = lastLM;
}
} else if (pos instanceof SpaceHandlingBreakPosition) {
positionList.add(pos);
} else {
// pos was created by this ListBlockLM, so it must be ignored
}
}
registerMarkers(true, isFirst(firstPos), isLast(lastPos));
PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
while ((childLM = childPosIter.getNextChildLM()) != null) {
// Add the block areas to Area
lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
// set the space adjustment ratio
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
lc.setStackLimitBP(layoutContext.getStackLimitBP());
childLM.addAreas(childPosIter, lc);
}
registerMarkers(false, isFirst(firstPos), isLast(lastPos));
flush();
curBlockArea = null;
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.
*
* @param childArea the child area to get the parent for
* @return the parent area
*/
@Override
public Area getParentArea(Area childArea) {
if (curBlockArea == null) {
curBlockArea = new Block();
curBlockArea.setPositioning(Block.ABSOLUTE);
// set position
curBlockArea.setXOffset(xOffset);
//TODO: Check - itemIPD never set?
curBlockArea.setIPD(itemIPD);
//curBlockArea.setHeight();
curBlockArea.setBidiLevel(getPartFO().getBidiLevel());
TraitSetter.setProducerID(curBlockArea, getPartFO().getId());
// Set up dimensions
Area parentArea = parentLayoutManager.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 list item area.
*
* @param childArea the child to add to the cell
*/
@Override
public void addChildArea(Area childArea) {
if (curBlockArea != null) {
curBlockArea.addBlock((Block) childArea);
}
}
/** {@inheritDoc} */
@Override
public KeepProperty getKeepTogetherProperty() {
return getPartFO().getKeepTogether();
}
/** {@inheritDoc} */
@Override
public Keep getKeepWithNext() {
return Keep.KEEP_AUTO;
}
/** {@inheritDoc} */
@Override
public Keep getKeepWithPrevious() {
return Keep.KEEP_AUTO;
}
@SuppressWarnings("unchecked")
@Override
public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
List<ListElement> elements = new LinkedList<ListElement>();
do {
elements.addAll(super.getNextKnuthElements(context, alignment));
} while (!isFinished());
return elements;
}
}