blob: 2bef1a815b77ab2c6db7e882c467c7ec92dd29d3 [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.
*/
package org.apache.fop.layoutmgr;
import java.util.LinkedList;
import java.util.List;
import org.apache.fop.area.Area;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.MultiSwitch;
public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
static class WhitespaceManagementPosition extends Position {
private List<ListElement> knuthList;
public WhitespaceManagementPosition(LayoutManager lm) {
super(lm);
}
public List<Position> getPositionList() {
List<Position> positions = new LinkedList<Position>();
if (knuthList != null && !knuthList.isEmpty()) {
SpaceResolver.performConditionalsNotification(knuthList, 0, knuthList.size() - 1, -1);
for (ListElement el : knuthList) {
if (el.getPosition() != null) {
positions.add(el.getPosition());
}
}
}
return positions;
}
public void setKnuthList(List<ListElement> knuthList) {
this.knuthList = knuthList;
}
public List<ListElement> getKnuthList() {
return knuthList;
}
}
private interface KnuthElementsGenerator {
List<ListElement> getKnuthElements(LayoutContext context, int alignment);
}
private class DefaultKnuthListGenerator implements KnuthElementsGenerator {
public List<ListElement> getKnuthElements(LayoutContext context, int alignment) {
List<ListElement> knuthList = new LinkedList<ListElement>();
LayoutManager childLM = getChildLM();
while (!childLM.isFinished()) {
LayoutContext childLC = makeChildLayoutContext(context);
List childElements = childLM.getNextKnuthElements(childLC, alignment);
if (childElements != null) {
List<ListElement> newList = new LinkedList<ListElement>();
wrapPositionElements(childElements, newList);
knuthList.addAll(newList);
}
}
return knuthList;
}
}
private class WhitespaceManagement implements KnuthElementsGenerator {
@SuppressWarnings("unchecked")
public List<ListElement> getKnuthElements(LayoutContext context, int alignment) {
MultiSwitchLayoutManager mslm = MultiSwitchLayoutManager.this;
List<ListElement> knuthList = new LinkedList<ListElement>();
WhitespaceManagementPenalty penalty = new WhitespaceManagementPenalty(
new WhitespaceManagementPosition(mslm));
LayoutManager childLM;
while ((childLM = getChildLM()) != null) {
LayoutContext childLC = makeChildLayoutContext(context);
List<ListElement> childElements = new LinkedList<ListElement>();
while (!childLM.isFinished()) {
childElements.addAll(childLM.getNextKnuthElements(childLC, alignment));
}
List<ListElement> wrappedElements = new LinkedList<ListElement>();
wrapPositionElements(childElements, wrappedElements);
// TODO Doing space resolution here is wrong.
SpaceResolver.resolveElementList(wrappedElements);
int contentLength = ElementListUtils.calcContentLength(wrappedElements);
penalty.addVariant(penalty.new Variant(wrappedElements, contentLength));
}
// Prevent the penalty from being ignored if it is at the beginning of the content
knuthList.add(new KnuthBox(0, new Position(mslm), false));
knuthList.add(penalty);
// Prevent the penalty from being ignored if it is at the end of the content
knuthList.add(new KnuthBox(0, new Position(mslm), false));
return knuthList;
}
}
private KnuthElementsGenerator knuthGen;
public MultiSwitchLayoutManager(FObj node) {
super(node);
MultiSwitch multiSwitchNode = (MultiSwitch) node;
if (multiSwitchNode.getAutoToggle() == Constants.EN_SELECT_FIRST_FITTING) {
knuthGen = new WhitespaceManagement();
} else {
knuthGen = new DefaultKnuthListGenerator();
}
}
@Override
public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
referenceIPD = context.getRefIPD();
List<ListElement> knuthList = knuthGen.getKnuthElements(context, alignment);
setFinished(true);
return knuthList;
}
@Override
public Area getParentArea(Area childArea) {
return parentLayoutManager.getParentArea(childArea);
}
@Override
public void addChildArea(Area childArea) {
parentLayoutManager.addChildArea(childArea);
}
@Override
public void addAreas(PositionIterator posIter, LayoutContext context) {
LinkedList<Position> positionList = new LinkedList<Position>();
while (posIter.hasNext()) {
Position pos = posIter.next();
if (pos instanceof WhitespaceManagementPosition) {
positionList.addAll(((WhitespaceManagementPosition) pos).getPositionList());
} else {
positionList.add(pos);
}
}
PositionIterator newPosIter = new PositionIterator(positionList.listIterator());
AreaAdditionUtil.addAreas(this, newPosIter, context);
flush();
}
}