| /* |
| * 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(); |
| } |
| |
| } |