KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layoutmgr > StaticContentLayoutManager


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: StaticContentLayoutManager.java 453310 2006-10-05 18:44:15Z spepping $ */
19  
20 package org.apache.fop.layoutmgr;
21
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.fop.area.RegionReference;
29 import org.apache.fop.area.Area;
30 import org.apache.fop.area.Block;
31 import org.apache.fop.fo.FONode;
32 import org.apache.fop.fo.pagination.PageSequence;
33 import org.apache.fop.fo.pagination.SideRegion;
34 import org.apache.fop.fo.pagination.StaticContent;
35 import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
36 import org.apache.fop.layoutmgr.inline.TextLayoutManager;
37 import org.apache.fop.traits.MinOptMax;
38
39 /**
40  * LayoutManager for an fo:flow object.
41  * Its parent LM is the PageSequenceLayoutManager.
42  * This LM is responsible for getting columns of the appropriate size
43  * and filling them with block-level areas generated by its children.
44  */

45 public class StaticContentLayoutManager extends BlockStackingLayoutManager {
46
47     /**
48      * logging instance
49      */

50     private static Log log = LogFactory.getLog(StaticContentLayoutManager.class);
51
52     private RegionReference targetRegion;
53     private Block targetBlock;
54     private SideRegion regionFO;
55
56     private int contentAreaIPD = 0;
57     private int contentAreaBPD = -1;
58
59     /**
60      * Creates a new StaticContentLayoutManager.
61      * @param pslm PageSequenceLayoutManager this layout manager belongs to
62      * @param node static-content FO
63      * @param reg side region to layout into
64      */

65     public StaticContentLayoutManager(PageSequenceLayoutManager pslm,
66             StaticContent node, SideRegion reg) {
67         super(node);
68         setParent(pslm);
69         regionFO = reg;
70         targetRegion = getCurrentPV().getRegionReference(regionFO.getNameId());
71     }
72
73     /**
74      * Creates a new StaticContentLayoutManager.
75      * @param pslm PageSequenceLayoutManager this layout manager belongs to
76      * @param node static-content FO
77      * @param block the block to layout into
78      */

79     public StaticContentLayoutManager(PageSequenceLayoutManager pslm,
80             StaticContent node, Block block) {
81         super(node);
82         setParent(pslm);
83         targetBlock = block;
84     }
85
86     /** @see org.apache.fop.layoutmgr.LayoutManager */
87     public LinkedList JavaDoc getNextKnuthElements(LayoutContext context, int alignment) {
88         if (true) {
89             throw new UnsupportedOperationException JavaDoc(
90                 "Shouldn't this method be emptied because it's never called at all?");
91         }
92         //TODO Empty this method?!?
93
// set layout dimensions
94
setContentAreaIPD(context.getRefIPD());
95         setContentAreaBPD(context.getStackLimit().opt);
96
97         //TODO Copied from elsewhere. May be worthwhile to factor out the common parts.
98
// currently active LM
99
BlockLevelLayoutManager curLM;
100         BlockLevelLayoutManager prevLM = null;
101         MinOptMax stackSize = new MinOptMax();
102         LinkedList JavaDoc returnedList;
103         LinkedList JavaDoc returnList = new LinkedList JavaDoc();
104
105         while ((curLM = ((BlockLevelLayoutManager) getChildLM())) != null) {
106             if (curLM instanceof InlineLevelLayoutManager) {
107                 log.error("inline area not allowed under flow - ignoring");
108                 curLM.setFinished(true);
109                 continue;
110             }
111
112             // Set up a LayoutContext
113
MinOptMax bpd = context.getStackLimit();
114
115             LayoutContext childLC = new LayoutContext(0);
116             childLC.setStackLimit(MinOptMax.subtract(bpd, stackSize));
117             childLC.setRefIPD(context.getRefIPD());
118
119             // get elements from curLM
120
returnedList = curLM.getNextKnuthElements(childLC, alignment);
121             //log.debug("FLM.getNextKnuthElements> returnedList.size() = "
122
// + returnedList.size());
123

124             // "wrap" the Position inside each element
125
LinkedList JavaDoc tempList = returnedList;
126             KnuthElement tempElement;
127             returnedList = new LinkedList JavaDoc();
128             ListIterator JavaDoc listIter = tempList.listIterator();
129             while (listIter.hasNext()) {
130                 tempElement = (KnuthElement)listIter.next();
131                 tempElement.setPosition(new NonLeafPosition(this, tempElement.getPosition()));
132                 returnedList.add(tempElement);
133             }
134
135             if (returnedList.size() == 1
136                 && ((KnuthElement)returnedList.getFirst()).isPenalty()
137                 && ((KnuthPenalty)returnedList.getFirst()).getP() == -KnuthElement.INFINITE) {
138                 // a descendant of this flow has break-before
139
returnList.addAll(returnedList);
140                 return returnList;
141             } else {
142                 if (returnList.size() > 0) {
143                     // there is a block before this one
144
if (prevLM.mustKeepWithNext()
145                         || curLM.mustKeepWithPrevious()) {
146                         // add an infinite penalty to forbid a break between blocks
147
returnList.add(new KnuthPenalty(0,
148                                 KnuthElement.INFINITE, false,
149                                 new Position(this), false));
150                     } else if (!((KnuthElement) returnList.getLast()).isGlue()) {
151                         // add a null penalty to allow a break between blocks
152
returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
153                     }
154                 }
155 /*LF*/ if (returnedList.size() > 0) { // controllare!
156
returnList.addAll(returnedList);
157                     if (((KnuthElement)returnedList.getLast()).isPenalty()
158                             && ((KnuthPenalty)returnedList.getLast()).getP()
159                                     == -KnuthElement.INFINITE) {
160                         // a descendant of this flow has break-after
161
/*LF*/ //log.debug("FLM - break after!!");
162
return returnList;
163                     }
164 /*LF*/ }
165             }
166             prevLM = curLM;
167         }
168
169         setFinished(true);
170
171         if (returnList.size() > 0) {
172             return returnList;
173         } else {
174             return null;
175         }
176     }
177     
178     /**
179      * @see org.apache.fop.layoutmgr.LayoutManager#addAreas(PositionIterator, LayoutContext)
180      */

181     public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) {
182         AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
183
184         flush();
185         targetRegion = null;
186     }
187
188
189     /**
190      * Add child area to a the correct container, depending on its
191      * area class. A Flow can fill at most one area container of any class
192      * at any one time. The actual work is done by BlockStackingLM.
193      * @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(Area)
194      */

195     public void addChildArea(Area childArea) {
196         if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) {
197             targetBlock.addBlock((Block)childArea);
198         } else {
199             targetRegion.addBlock((Block)childArea);
200         }
201     }
202
203     /**
204      * @see org.apache.fop.layoutmgr.LayoutManager#getParentArea(Area)
205      */

206     public Area getParentArea(Area childArea) {
207         if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) {
208             return targetBlock;
209         } else {
210             return targetRegion;
211         }
212     }
213
214     /**
215      * Does the layout for a side region. Called by PageSequenceLayoutManager.
216      */

217     public void doLayout() {
218         int targetIPD = 0;
219         int targetBPD = 0;
220         int targetAlign = EN_AUTO;
221         boolean autoHeight = false;
222         StaticContentBreaker breaker;
223
224         if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) {
225             targetIPD = targetBlock.getIPD();
226             targetBPD = targetBlock.getBPD();
227             if (targetBPD == 0) {
228                 autoHeight = true;
229             }
230             targetAlign = EN_BEFORE;
231         } else {
232             targetIPD = targetRegion.getIPD();
233             targetBPD = targetRegion.getBPD();
234             targetAlign = regionFO.getDisplayAlign();
235         }
236         setContentAreaIPD(targetIPD);
237         setContentAreaBPD(targetBPD);
238         breaker = new StaticContentBreaker(this, targetIPD, targetAlign);
239         breaker.doLayout(targetBPD, autoHeight);
240         if (breaker.isOverflow()) {
241             if (!autoHeight) {
242                 //Overflow handling
243
if (regionFO.getOverflow() == EN_ERROR_IF_OVERFLOW) {
244                     //TODO throw layout exception
245
}
246                 log.warn(FONode.decorateWithContextInfo(
247                         "static-content overflows the available area.", fobj));
248             }
249         }
250     }
251     
252     /**
253      * Convenience method that returns the Static Content node.
254      * @return the static content node
255      */

256     protected StaticContent getStaticContentFO() {
257         return (StaticContent) fobj;
258     }
259
260     private class StaticContentBreaker extends AbstractBreaker {
261         private StaticContentLayoutManager lm;
262         private int displayAlign;
263         private int ipd;
264         private boolean overflow = false;
265         
266         public StaticContentBreaker(StaticContentLayoutManager lm, int ipd,
267                 int displayAlign) {
268             this.lm = lm;
269             this.ipd = ipd;
270             this.displayAlign = displayAlign;
271         }
272
273         /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
274         protected void observeElementList(List JavaDoc elementList) {
275             String JavaDoc elementListID = getStaticContentFO().getFlowName();
276             String JavaDoc pageSequenceID = ((PageSequence)lm.getParent().getFObj()).getId();
277             if (pageSequenceID != null && pageSequenceID.length() > 0) {
278                 elementListID += "-" + pageSequenceID;
279             }
280             ElementListObserver.observe(elementList, "static-content", elementListID);
281         }
282         
283         /** @see org.apache.fop.layoutmgr.AbstractBreaker#isPartOverflowRecoveryActivated() */
284         protected boolean isPartOverflowRecoveryActivated() {
285             //For side regions, this must be disabled because of wanted overflow.
286
return false;
287         }
288
289         public boolean isOverflow() {
290             return this.overflow;
291         }
292         
293         protected LayoutManager getTopLevelLM() {
294             return lm;
295         }
296
297         protected LayoutContext createLayoutContext() {
298             LayoutContext lc = super.createLayoutContext();
299             lc.setRefIPD(ipd);
300             return lc;
301         }
302         
303         protected LinkedList JavaDoc getNextKnuthElements(LayoutContext context, int alignment) {
304             LayoutManager curLM; // currently active LM
305
LinkedList JavaDoc returnList = new LinkedList JavaDoc();
306
307             while ((curLM = getChildLM()) != null) {
308                 LayoutContext childLC = new LayoutContext(0);
309                 childLC.setStackLimit(context.getStackLimit());
310                 childLC.setRefIPD(context.getRefIPD());
311                 childLC.setWritingMode(context.getWritingMode());
312
313                 LinkedList JavaDoc returnedList = null;
314                 //The following is a HACK! Ignore leading and trailing white space
315
boolean ignore = curLM instanceof TextLayoutManager;
316                 if (!curLM.isFinished()) {
317                     returnedList = curLM.getNextKnuthElements(childLC, alignment);
318                 }
319                 if (returnedList != null && !ignore) {
320                     lm.wrapPositionElements(returnedList, returnList);
321                 }
322             }
323             SpaceResolver.resolveElementList(returnList);
324             setFinished(true);
325             return returnList;
326         }
327
328         protected int getCurrentDisplayAlign() {
329             return displayAlign;
330         }
331         
332         protected boolean hasMoreContent() {
333             return !lm.isFinished();
334         }
335         
336         protected void addAreas(PositionIterator posIter, LayoutContext context) {
337             AreaAdditionUtil.addAreas(lm, posIter, context);
338         }
339         
340         protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
341                 BlockSequence originalList, BlockSequence effectiveList) {
342             //Directly add areas after finding the breaks
343
this.addAreas(alg, partCount, originalList, effectiveList);
344             if (partCount > 1) {
345                 overflow = true;
346             }
347         }
348         
349         protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
350             //nop for static content
351
}
352         
353         protected LayoutManager getCurrentChildLM() {
354             return null; //TODO NYI
355
}
356     }
357     
358     /**
359      * Returns the IPD of the content area
360      * @return the IPD of the content area
361      */

362     public int getContentAreaIPD() {
363         return contentAreaIPD;
364     }
365    
366     /** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager#setContentAreaIPD(int) */
367     protected void setContentAreaIPD(int contentAreaIPD) {
368         this.contentAreaIPD = contentAreaIPD;
369     }
370     
371     /**
372      * Returns the BPD of the content area
373      * @return the BPD of the content area
374      */

375     public int getContentAreaBPD() {
376         return contentAreaBPD;
377     }
378     
379     private void setContentAreaBPD(int contentAreaBPD) {
380         this.contentAreaBPD = contentAreaBPD;
381     }
382     
383 }
384
385
Popular Tags