KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layoutmgr > list > ListBlockLayoutManager


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

17
18 /* $Id: ListBlockLayoutManager.java 453310 2006-10-05 18:44:15Z spepping $ */
19  
20 package org.apache.fop.layoutmgr.list;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.fop.fo.flow.ListBlock;
25 import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
26 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
27 import org.apache.fop.layoutmgr.ConditionalElementListener;
28 import org.apache.fop.layoutmgr.ElementListUtils;
29 import org.apache.fop.layoutmgr.LayoutManager;
30 import org.apache.fop.layoutmgr.LayoutContext;
31 import org.apache.fop.layoutmgr.PositionIterator;
32 import org.apache.fop.layoutmgr.Position;
33 import org.apache.fop.layoutmgr.NonLeafPosition;
34 import org.apache.fop.layoutmgr.RelSide;
35 import org.apache.fop.layoutmgr.TraitSetter;
36 import org.apache.fop.area.Area;
37 import org.apache.fop.area.Block;
38 import org.apache.fop.traits.MinOptMax;
39 import org.apache.fop.traits.SpaceVal;
40
41 import java.util.Iterator JavaDoc;
42 import java.util.LinkedList JavaDoc;
43 import java.util.List JavaDoc;
44
45 /**
46  * LayoutManager for a list-block FO.
47  * A list block contains list items which are stacked within
48  * the list block area..
49  */

50 public class ListBlockLayoutManager extends BlockStackingLayoutManager
51                 implements ConditionalElementListener {
52
53     /**
54      * logging instance
55      */

56     private static Log log = LogFactory.getLog(ListBlockLayoutManager.class);
57
58     private Block curBlockArea;
59
60     private boolean discardBorderBefore;
61     private boolean discardBorderAfter;
62     private boolean discardPaddingBefore;
63     private boolean discardPaddingAfter;
64     private MinOptMax effSpaceBefore;
65     private MinOptMax effSpaceAfter;
66
67     private static class StackingIter extends PositionIterator {
68         StackingIter(Iterator parentIter) {
69             super(parentIter);
70         }
71
72         protected LayoutManager getLM(Object JavaDoc nextObj) {
73             return ((Position) nextObj).getLM();
74         }
75
76         protected Position getPos(Object JavaDoc nextObj) {
77             return ((Position) nextObj);
78         }
79     }
80
81     /**
82      * Create a new list block layout manager.
83      * @param node list-block to create the layout manager for
84      */

85     public ListBlockLayoutManager(ListBlock node) {
86         super(node);
87     }
88
89     /**
90      * Convenience method.
91      * @return the ListBlock node
92      */

93     protected ListBlock getListBlockFO() {
94         return (ListBlock)fobj;
95     }
96
97     /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */
98     public void initialize() {
99         foSpaceBefore = new SpaceVal(
100                 getListBlockFO().getCommonMarginBlock().spaceBefore, this).getSpace();
101         foSpaceAfter = new SpaceVal(
102                 getListBlockFO().getCommonMarginBlock().spaceAfter, this).getSpace();
103         startIndent = getListBlockFO().getCommonMarginBlock().startIndent.getValue(this);
104         endIndent = getListBlockFO().getCommonMarginBlock().endIndent.getValue(this);
105     }
106
107     private void resetSpaces() {
108         this.discardBorderBefore = false;
109         this.discardBorderAfter = false;
110         this.discardPaddingBefore = false;
111         this.discardPaddingAfter = false;
112         this.effSpaceBefore = null;
113         this.effSpaceAfter = null;
114     }
115     
116     /** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager */
117     public LinkedList JavaDoc getNextKnuthElements(LayoutContext context, int alignment) {
118         resetSpaces();
119         LinkedList JavaDoc returnList = super.getNextKnuthElements(context, alignment);
120
121         //fox:widow-content-limit
122
int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue();
123         if (widowRowLimit != 0) {
124             ElementListUtils.removeLegalBreaks(returnList, widowRowLimit);
125         }
126
127         //fox:orphan-content-limit
128
int orphanRowLimit = getListBlockFO().getOrphanContentLimit().getValue();
129         if (orphanRowLimit != 0) {
130             ElementListUtils.removeLegalBreaksFromEnd(returnList, orphanRowLimit);
131         }
132
133         return returnList;
134     }
135    
136     /** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) */
137     public LinkedList JavaDoc getChangedKnuthElements(List JavaDoc oldList, int alignment) {
138         //log.debug("LBLM.getChangedKnuthElements>");
139
return super.getChangedKnuthElements(oldList, alignment);
140     }
141
142     /**
143      * The table area is a reference area that contains areas for
144      * columns, bodies, rows and the contents are in cells.
145      *
146      * @param parentIter the position iterator
147      * @param layoutContext the layout context for adding areas
148      */

149     public void addAreas(PositionIterator parentIter,
150                          LayoutContext layoutContext) {
151         getParentArea(null);
152
153         // if this will create the first block area in a page
154
// and display-align is after or center, add space before
155
if (layoutContext.getSpaceBefore() > 0) {
156             addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore()));
157         }
158
159         getPSLM().addIDToPage(getListBlockFO().getId());
160
161         // the list block contains areas stacked from each list item
162

163         LayoutManager childLM = null;
164         LayoutContext lc = new LayoutContext(0);
165         LayoutManager firstLM = null;
166         LayoutManager lastLM = null;
167         Position firstPos = null;
168         Position lastPos = null;
169
170         // "unwrap" the NonLeafPositions stored in parentIter
171
// and put them in a new list;
172
LinkedList JavaDoc positionList = new LinkedList JavaDoc();
173         Position pos;
174         while (parentIter.hasNext()) {
175             pos = (Position)parentIter.next();
176             if (pos.getIndex() >= 0) {
177                 if (firstPos == null) {
178                     firstPos = pos;
179                 }
180                 lastPos = pos;
181             }
182             if (pos instanceof NonLeafPosition
183                     && (pos.getPosition() != null)
184                     && ((NonLeafPosition) pos).getPosition().getLM() != this) {
185                 // pos was created by a child of this ListBlockLM
186
positionList.add(((NonLeafPosition) pos).getPosition());
187                 lastLM = ((NonLeafPosition) pos).getPosition().getLM();
188                 if (firstLM == null) {
189                     firstLM = lastLM;
190                 }
191             }
192         }
193
194         if (markers != null) {
195             getCurrentPV().addMarkers(markers, true, isFirst(firstPos), isLast(lastPos));
196         }
197
198         StackingIter childPosIter = new StackingIter(positionList.listIterator());
199         while ((childLM = childPosIter.getNextChildLM()) != null) {
200             // Add the block areas to Area
201
// set the space adjustment ratio
202
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
203             lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
204             lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
205             lc.setStackLimit(layoutContext.getStackLimit());
206             childLM.addAreas(childPosIter, lc);
207         }
208
209         if (markers != null) {
210             getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos));
211         }
212
213         // We are done with this area add the background
214
TraitSetter.addBackground(curBlockArea,
215                 getListBlockFO().getCommonBorderPaddingBackground(),
216                 this);
217         TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
218                 effSpaceBefore, effSpaceAfter);
219
220         flush();
221
222         curBlockArea = null;
223         resetSpaces();
224         
225         getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId());
226     }
227
228     /**
229      * Return an Area which can contain the passed childArea. The childArea
230      * may not yet have any content, but it has essential traits set.
231      * In general, if the LayoutManager already has an Area it simply returns
232      * it. Otherwise, it makes a new Area of the appropriate class.
233      * It gets a parent area for its area by calling its parent LM.
234      * Finally, based on the dimensions of the parent area, it initializes
235      * its own area. This includes setting the content IPD and the maximum
236      * BPD.
237      *
238      * @param childArea the child area
239      * @return the parent area of the child
240      */

241     public Area getParentArea(Area childArea) {
242         if (curBlockArea == null) {
243             curBlockArea = new Block();
244             
245             // Set up dimensions
246
// Must get dimensions from parent area
247
/*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
248
249             // set traits
250
TraitSetter.setProducerID(curBlockArea, getListBlockFO().getId());
251             TraitSetter.addBorders(curBlockArea,
252                     getListBlockFO().getCommonBorderPaddingBackground(),
253                     discardBorderBefore, discardBorderAfter, false, false, this);
254             TraitSetter.addPadding(curBlockArea,
255                     getListBlockFO().getCommonBorderPaddingBackground(),
256                     discardPaddingBefore, discardPaddingAfter, false, false, this);
257             TraitSetter.addMargins(curBlockArea,
258                     getListBlockFO().getCommonBorderPaddingBackground(),
259                     getListBlockFO().getCommonMarginBlock(),
260                     this);
261             TraitSetter.addBreaks(curBlockArea,
262                     getListBlockFO().getBreakBefore(),
263                     getListBlockFO().getBreakAfter());
264             
265             int contentIPD = referenceIPD - getIPIndents();
266             curBlockArea.setIPD(contentIPD);
267             
268             setCurrentArea(curBlockArea);
269         }
270         return curBlockArea;
271     }
272
273     /**
274      * Add the child area to this layout manager.
275      *
276      * @param childArea the child area to add
277      */

278     public void addChildArea(Area childArea) {
279         if (curBlockArea != null) {
280             curBlockArea.addBlock((Block) childArea);
281         }
282     }
283
284     /**
285      * Reset the position of this layout manager.
286      *
287      * @param resetPos the position to reset to
288      */

289     public void resetPosition(Position resetPos) {
290         if (resetPos == null) {
291             reset(null);
292         } else {
293             //TODO Something to put here?
294
}
295     }
296     
297     /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */
298     public boolean mustKeepTogether() {
299         //TODO Keeps will have to be more sophisticated sooner or later
300
return ((BlockLevelLayoutManager)getParent()).mustKeepTogether()
301                 || !getListBlockFO().getKeepTogether().getWithinPage().isAuto()
302                 || !getListBlockFO().getKeepTogether().getWithinColumn().isAuto();
303     }
304
305     /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious() */
306     public boolean mustKeepWithPrevious() {
307         return !getListBlockFO().getKeepWithPrevious().getWithinPage().isAuto()
308             || !getListBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
309     }
310
311     /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext() */
312     public boolean mustKeepWithNext() {
313         return !getListBlockFO().getKeepWithNext().getWithinPage().isAuto()
314                 || !getListBlockFO().getKeepWithNext().getWithinColumn().isAuto();
315     }
316
317     /** @see org.apache.fop.layoutmgr.ConditionalElementListener */
318     public void notifySpace(RelSide side, MinOptMax effectiveLength) {
319         if (RelSide.BEFORE == side) {
320             if (log.isDebugEnabled()) {
321                 log.debug(this + ": Space " + side + ", "
322                         + this.effSpaceBefore + "-> " + effectiveLength);
323             }
324             this.effSpaceBefore = effectiveLength;
325         } else {
326             if (log.isDebugEnabled()) {
327                 log.debug(this + ": Space " + side + ", "
328                         + this.effSpaceAfter + "-> " + effectiveLength);
329             }
330             this.effSpaceAfter = effectiveLength;
331         }
332     }
333
334     /** @see org.apache.fop.layoutmgr.ConditionalElementListener */
335     public void notifyBorder(RelSide side, MinOptMax effectiveLength) {
336         if (effectiveLength == null) {
337             if (RelSide.BEFORE == side) {
338                 this.discardBorderBefore = true;
339             } else {
340                 this.discardBorderAfter = true;
341             }
342         }
343         if (log.isDebugEnabled()) {
344             log.debug(this + ": Border " + side + " -> " + effectiveLength);
345         }
346     }
347
348     /** @see org.apache.fop.layoutmgr.ConditionalElementListener */
349     public void notifyPadding(RelSide side, MinOptMax effectiveLength) {
350         if (effectiveLength == null) {
351             if (RelSide.BEFORE == side) {
352                 this.discardPaddingBefore = true;
353             } else {
354                 this.discardPaddingAfter = true;
355             }
356         }
357         if (log.isDebugEnabled()) {
358             log.debug(this + ": Padding " + side + " -> " + effectiveLength);
359         }
360     }
361
362 }
363
364
Popular Tags