Source Code Cross Referenced for TableContentLayoutManager.java in  » Graphic-Library » fop » org » apache » fop » layoutmgr » table » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » fop » org.apache.fop.layoutmgr.table 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        /* $Id: TableContentLayoutManager.java 555651 2007-07-12 14:59:06Z vhennebert $ */
019:
020:        package org.apache.fop.layoutmgr.table;
021:
022:        import java.util.Iterator;
023:        import java.util.LinkedList;
024:        import java.util.List;
025:        import java.util.Map;
026:
027:        import org.apache.commons.logging.Log;
028:        import org.apache.commons.logging.LogFactory;
029:        import org.apache.fop.area.Block;
030:        import org.apache.fop.area.Trait;
031:        import org.apache.fop.datatypes.PercentBaseContext;
032:        import org.apache.fop.fo.Constants;
033:        import org.apache.fop.fo.FONode;
034:        import org.apache.fop.fo.FObj;
035:        import org.apache.fop.fo.flow.Table;
036:        import org.apache.fop.fo.flow.TableBody;
037:        import org.apache.fop.fo.flow.TableRow;
038:        import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
039:        import org.apache.fop.fo.properties.LengthRangeProperty;
040:        import org.apache.fop.layoutmgr.BreakElement;
041:        import org.apache.fop.layoutmgr.ElementListObserver;
042:        import org.apache.fop.layoutmgr.ElementListUtils;
043:        import org.apache.fop.layoutmgr.KnuthBox;
044:        import org.apache.fop.layoutmgr.KnuthElement;
045:        import org.apache.fop.layoutmgr.KnuthPenalty;
046:        import org.apache.fop.layoutmgr.KnuthPossPosIter;
047:        import org.apache.fop.layoutmgr.LayoutContext;
048:        import org.apache.fop.layoutmgr.ListElement;
049:        import org.apache.fop.layoutmgr.MinOptMaxUtil;
050:        import org.apache.fop.layoutmgr.Position;
051:        import org.apache.fop.layoutmgr.PositionIterator;
052:        import org.apache.fop.layoutmgr.TraitSetter;
053:        import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
054:        import org.apache.fop.traits.MinOptMax;
055:
056:        /**
057:         * Layout manager for table contents, particularly managing the creation of combined element lists.
058:         */
059:        public class TableContentLayoutManager implements  PercentBaseContext {
060:
061:            /** Logger **/
062:            private static Log log = LogFactory
063:                    .getLog(TableContentLayoutManager.class);
064:
065:            private TableLayoutManager tableLM;
066:            private TableRowIterator bodyIter;
067:            private TableRowIterator headerIter;
068:            private TableRowIterator footerIter;
069:            private LinkedList headerList;
070:            private LinkedList footerList;
071:            private int headerNetHeight = 0;
072:            private int footerNetHeight = 0;
073:
074:            private int startXOffset;
075:            private int usedBPD;
076:
077:            private TableStepper stepper = new TableStepper(this );
078:
079:            /**
080:             * Main constructor
081:             * @param parent Parent layout manager
082:             */
083:            public TableContentLayoutManager(TableLayoutManager parent) {
084:                this .tableLM = parent;
085:                Table table = getTableLM().getTable();
086:                this .bodyIter = new TableRowIterator(table, getTableLM()
087:                        .getColumns(), TableRowIterator.BODY);
088:                if (table.getTableHeader() != null) {
089:                    headerIter = new TableRowIterator(table, getTableLM()
090:                            .getColumns(), TableRowIterator.HEADER);
091:                }
092:                if (table.getTableFooter() != null) {
093:                    footerIter = new TableRowIterator(table, getTableLM()
094:                            .getColumns(), TableRowIterator.FOOTER);
095:                }
096:            }
097:
098:            /**
099:             * @return the table layout manager
100:             */
101:            public TableLayoutManager getTableLM() {
102:                return this .tableLM;
103:            }
104:
105:            /** @return true if the table uses the separate border model. */
106:            boolean isSeparateBorderModel() {
107:                return getTableLM().getTable().isSeparateBorderModel();
108:            }
109:
110:            /**
111:             * @return the column setup of this table
112:             */
113:            public ColumnSetup getColumns() {
114:                return getTableLM().getColumns();
115:            }
116:
117:            /** @return the net header height */
118:            protected int getHeaderNetHeight() {
119:                return this .headerNetHeight;
120:            }
121:
122:            /** @return the net footer height */
123:            protected int getFooterNetHeight() {
124:                return this .footerNetHeight;
125:            }
126:
127:            /** @return the header element list */
128:            protected LinkedList getHeaderElements() {
129:                return this .headerList;
130:            }
131:
132:            /** @return the footer element list */
133:            protected LinkedList getFooterElements() {
134:                return this .footerList;
135:            }
136:
137:            /** @see org.apache.fop.layoutmgr.LayoutManager */
138:            public LinkedList getNextKnuthElements(LayoutContext context,
139:                    int alignment) {
140:                log.debug("==> Columns: " + getTableLM().getColumns());
141:                KnuthBox headerAsFirst = null;
142:                KnuthBox headerAsSecondToLast = null;
143:                KnuthBox footerAsLast = null;
144:                if (headerIter != null && headerList == null) {
145:                    this .headerList = getKnuthElementsForRowIterator(
146:                            headerIter, context, alignment,
147:                            TableRowIterator.HEADER);
148:                    ElementListUtils.removeLegalBreaks(this .headerList);
149:                    this .headerNetHeight = ElementListUtils
150:                            .calcContentLength(this .headerList);
151:                    if (log.isDebugEnabled()) {
152:                        log.debug("==> Header: " + headerNetHeight + " - "
153:                                + this .headerList);
154:                    }
155:                    TableHeaderFooterPosition pos = new TableHeaderFooterPosition(
156:                            getTableLM(), true, this .headerList);
157:                    KnuthBox box = new KnuthBox(headerNetHeight, pos, false);
158:                    if (getTableLM().getTable().omitHeaderAtBreak()) {
159:                        //We can simply add the table header at the start 
160:                        //of the whole list
161:                        headerAsFirst = box;
162:                    } else {
163:                        headerAsSecondToLast = box;
164:                    }
165:                }
166:                if (footerIter != null && footerList == null) {
167:                    this .footerList = getKnuthElementsForRowIterator(
168:                            footerIter, context, alignment,
169:                            TableRowIterator.FOOTER);
170:                    ElementListUtils.removeLegalBreaks(this .footerList);
171:                    this .footerNetHeight = ElementListUtils
172:                            .calcContentLength(this .footerList);
173:                    if (log.isDebugEnabled()) {
174:                        log.debug("==> Footer: " + footerNetHeight + " - "
175:                                + this .footerList);
176:                    }
177:                    //We can simply add the table footer at the end of the whole list
178:                    TableHeaderFooterPosition pos = new TableHeaderFooterPosition(
179:                            getTableLM(), false, this .footerList);
180:                    KnuthBox box = new KnuthBox(footerNetHeight, pos, false);
181:                    footerAsLast = box;
182:                }
183:                LinkedList returnList = getKnuthElementsForRowIterator(
184:                        bodyIter, context, alignment, TableRowIterator.BODY);
185:                if (headerAsFirst != null) {
186:                    int insertionPoint = 0;
187:                    if (returnList.size() > 0
188:                            && ((ListElement) returnList.getFirst())
189:                                    .isForcedBreak()) {
190:                        insertionPoint++;
191:                    }
192:                    returnList.add(insertionPoint, headerAsFirst);
193:                } else if (headerAsSecondToLast != null) {
194:                    int insertionPoint = returnList.size();
195:                    if (returnList.size() > 0
196:                            && ((ListElement) returnList.getLast())
197:                                    .isForcedBreak()) {
198:                        insertionPoint--;
199:                    }
200:                    returnList.add(insertionPoint, headerAsSecondToLast);
201:                }
202:                if (footerAsLast != null) {
203:                    int insertionPoint = returnList.size();
204:                    if (returnList.size() > 0
205:                            && ((ListElement) returnList.getLast())
206:                                    .isForcedBreak()) {
207:                        insertionPoint--;
208:                    }
209:                    returnList.add(insertionPoint, footerAsLast);
210:                }
211:                return returnList;
212:            }
213:
214:            /**
215:             * Creates Knuth elements by iterating over a TableRowIterator.
216:             * @param iter TableRowIterator instance to fetch rows from
217:             * @param context Active LayoutContext
218:             * @param alignment alignment indicator
219:             * @param bodyType Indicates what kind of body is being processed 
220:             *                  (BODY, HEADER or FOOTER)
221:             * @return An element list
222:             */
223:            private LinkedList getKnuthElementsForRowIterator(
224:                    TableRowIterator iter, LayoutContext context,
225:                    int alignment, int bodyType) {
226:                LinkedList returnList = new LinkedList();
227:                EffRow[] rowGroup = null;
228:                while ((rowGroup = iter.getNextRowGroup()) != null) {
229:                    //Check for break-before on the table-row at the start of the row group
230:                    TableRow rowFO = rowGroup[0].getTableRow();
231:                    if (rowFO != null
232:                            && rowFO.getBreakBefore() != Constants.EN_AUTO) {
233:                        log.info("break-before found");
234:                        if (returnList.size() > 0) {
235:                            ListElement last = (ListElement) returnList
236:                                    .getLast();
237:                            if (last.isPenalty()) {
238:                                KnuthPenalty pen = (KnuthPenalty) last;
239:                                pen.setP(-KnuthPenalty.INFINITE);
240:                                pen.setBreakClass(rowFO.getBreakBefore());
241:                            } else {//if (last instanceof BreakElement) { // TODO vh: seems the only possibility
242:                                BreakElement breakPoss = (BreakElement) last;
243:                                breakPoss
244:                                        .setPenaltyValue(-KnuthPenalty.INFINITE);
245:                                breakPoss.setBreakClass(rowFO.getBreakBefore());
246:                            }
247:                        } else {
248:                            returnList.add(new BreakElement(new Position(
249:                                    getTableLM()), 0, -KnuthPenalty.INFINITE,
250:                                    rowFO.getBreakBefore(), context));
251:                        }
252:                    }
253:
254:                    //Border resolution
255:                    if (!isSeparateBorderModel()) {
256:                        resolveNormalBeforeAfterBordersForRowGroup(rowGroup,
257:                                iter);
258:                    }
259:
260:                    //Reset keep-with-next when remaining inside the table.
261:                    //The context flag is only used to propagate keep-with-next to the outside.
262:                    //The clearing is ok here because createElementsForRowGroup already handles
263:                    //the keep when inside a table.
264:                    context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING,
265:                            false);
266:
267:                    //Element list creation
268:                    createElementsForRowGroup(context, alignment, bodyType,
269:                            returnList, rowGroup);
270:
271:                    //Handle keeps
272:                    if (context.isKeepWithNextPending()) {
273:                        log
274:                                .debug("child LM (row group) signals pending keep-with-next");
275:                    }
276:                    if (context.isKeepWithPreviousPending()) {
277:                        log
278:                                .debug("child LM (row group) signals pending keep-with-previous");
279:                        if (returnList.size() > 0) {
280:                            //Modify last penalty
281:                            ListElement last = (ListElement) returnList
282:                                    .getLast();
283:                            if (last.isPenalty()) {
284:                                BreakElement breakPoss = (BreakElement) last;
285:                                //Only honor keep if there's no forced break
286:                                if (!breakPoss.isForcedBreak()) {
287:                                    breakPoss
288:                                            .setPenaltyValue(KnuthPenalty.INFINITE);
289:                                }
290:                            }
291:                        }
292:                    }
293:
294:                    //Check for break-after on the table-row at the end of the row group
295:                    rowFO = rowGroup[rowGroup.length - 1].getTableRow();
296:                    if (rowFO != null
297:                            && rowFO.getBreakAfter() != Constants.EN_AUTO) {
298:                        if (returnList.size() > 0) {
299:                            ListElement last = (ListElement) returnList
300:                                    .getLast();
301:                            if (last instanceof  KnuthPenalty) {
302:                                KnuthPenalty pen = (KnuthPenalty) last;
303:                                pen.setP(-KnuthPenalty.INFINITE);
304:                                pen.setBreakClass(rowFO.getBreakAfter());
305:                            } else if (last instanceof  BreakElement) {
306:                                BreakElement breakPoss = (BreakElement) last;
307:                                breakPoss
308:                                        .setPenaltyValue(-KnuthPenalty.INFINITE);
309:                                breakPoss.setBreakClass(rowFO.getBreakAfter());
310:                            }
311:                        }
312:                    }
313:                }
314:
315:                if (returnList.size() > 0) {
316:                    //Remove the last penalty produced by the combining algorithm (see TableStepper), for the last step
317:                    ListElement last = (ListElement) returnList.getLast();
318:                    if (last.isPenalty() || last instanceof  BreakElement) {
319:                        if (!last.isForcedBreak()) {
320:                            //Only remove if we don't signal a forced break
321:                            returnList.removeLast();
322:                        }
323:                    }
324:                }
325:
326:                //fox:widow-content-limit
327:                int widowContentLimit = getTableLM().getTable()
328:                        .getWidowContentLimit().getValue();
329:                if (widowContentLimit != 0 && bodyType == TableRowIterator.BODY) {
330:                    ElementListUtils.removeLegalBreaks(returnList,
331:                            widowContentLimit);
332:                }
333:                //fox:orphan-content-limit
334:                int orphanContentLimit = getTableLM().getTable()
335:                        .getOrphanContentLimit().getValue();
336:                if (orphanContentLimit != 0
337:                        && bodyType == TableRowIterator.BODY) {
338:                    ElementListUtils.removeLegalBreaksFromEnd(returnList,
339:                            orphanContentLimit);
340:                }
341:
342:                return returnList;
343:            }
344:
345:            /**
346:             * Resolves normal borders for a row group.
347:             * @param iter Table row iterator to operate on
348:             */
349:            private void resolveNormalBeforeAfterBordersForRowGroup(
350:                    EffRow[] rowGroup, TableRowIterator iter) {
351:                for (int rgi = 0; rgi < rowGroup.length; rgi++) {
352:                    EffRow row = rowGroup[rgi];
353:                    EffRow prevRow = iter.getPrecedingRow(row);
354:                    EffRow nextRow = iter.getFollowingRow(row);
355:                    if ((prevRow == null) && (iter == this .bodyIter)
356:                            && (this .headerIter != null)) {
357:                        prevRow = this .headerIter.getLastRow();
358:                    }
359:                    if ((nextRow == null) && (iter == this .headerIter)) {
360:                        nextRow = this .bodyIter.getFirstRow();
361:                    }
362:                    if ((nextRow == null) && (iter == this .bodyIter)
363:                            && (this .footerIter != null)) {
364:                        nextRow = this .footerIter.getFirstRow();
365:                    }
366:                    if ((prevRow == null) && (iter == this .footerIter)) {
367:                        //TODO This could be bad for memory consumption because it already causes the
368:                        //whole body iterator to be prefetched!
369:                        prevRow = this .bodyIter.getLastRow();
370:                    }
371:                    log.debug("prevRow-row-nextRow: " + prevRow + " - " + row
372:                            + " - " + nextRow);
373:
374:                    //Determine the grid units necessary for getting all the borders right
375:                    int guCount = row.getGridUnits().size();
376:                    if (prevRow != null) {
377:                        guCount = Math.max(guCount, prevRow.getGridUnits()
378:                                .size());
379:                    }
380:                    if (nextRow != null) {
381:                        guCount = Math.max(guCount, nextRow.getGridUnits()
382:                                .size());
383:                    }
384:                    GridUnit gu = row.getGridUnit(0);
385:                    //Create empty grid units to hold resolved borders of neighbouring cells
386:                    //TODO maybe this needs to be done differently (and sooner)
387:                    for (int i = 0; i < guCount - row.getGridUnits().size(); i++) {
388:                        //TODO This block is untested!
389:                        int pos = row.getGridUnits().size() + i;
390:                        row.getGridUnits().add(
391:                                new EmptyGridUnit(gu.getRow(), this .tableLM
392:                                        .getColumns().getColumn(pos + 1), gu
393:                                        .getBody(), pos));
394:                    }
395:
396:                    //Now resolve normal borders
397:                    if (getTableLM().getTable().isSeparateBorderModel()) {
398:                        //nop, borders are already assigned at this point
399:                    } else {
400:                        for (int i = 0; i < row.getGridUnits().size(); i++) {
401:                            gu = row.getGridUnit(i);
402:                            GridUnit other;
403:                            int flags = 0;
404:                            if (prevRow != null
405:                                    && i < prevRow.getGridUnits().size()) {
406:                                other = prevRow.getGridUnit(i);
407:                            } else {
408:                                other = null;
409:                            }
410:                            if (other == null || other.isEmpty()
411:                                    || gu.isEmpty()
412:                                    || gu.getPrimary() != other.getPrimary()) {
413:                                if ((iter == this .bodyIter)
414:                                        && gu.getFlag(GridUnit.FIRST_IN_TABLE)
415:                                        && (this .headerIter == null)) {
416:                                    flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
417:                                }
418:                                if ((iter == this .headerIter)
419:                                        && gu.getFlag(GridUnit.FIRST_IN_TABLE)) {
420:                                    flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
421:                                }
422:                                gu.resolveBorder(other,
423:                                        CommonBorderPaddingBackground.BEFORE,
424:                                        flags);
425:                            }
426:
427:                            flags = 0;
428:                            if (nextRow != null
429:                                    && i < nextRow.getGridUnits().size()) {
430:                                other = nextRow.getGridUnit(i);
431:                            } else {
432:                                other = null;
433:                            }
434:                            if (other == null || other.isEmpty()
435:                                    || gu.isEmpty()
436:                                    || gu.getPrimary() != other.getPrimary()) {
437:                                if ((iter == this .bodyIter)
438:                                        && gu.getFlag(GridUnit.LAST_IN_TABLE)
439:                                        && (this .footerIter == null)) {
440:                                    flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
441:                                }
442:                                if ((iter == this .footerIter)
443:                                        && gu.getFlag(GridUnit.LAST_IN_TABLE)) {
444:                                    flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
445:                                }
446:                                gu.resolveBorder(other,
447:                                        CommonBorderPaddingBackground.AFTER,
448:                                        flags);
449:                            }
450:                        }
451:                    }
452:                }
453:            }
454:
455:            /**
456:             * Creates Knuth elements for a row group (see TableRowIterator.getNextRowGroup()).
457:             * @param context Active LayoutContext
458:             * @param alignment alignment indicator
459:             * @param bodyType Indicates what kind of body is being processed (BODY, HEADER or FOOTER)
460:             * @param returnList List to received the generated elements
461:             * @param rowGroup row group to process
462:             */
463:            private void createElementsForRowGroup(LayoutContext context,
464:                    int alignment, int bodyType, LinkedList returnList,
465:                    EffRow[] rowGroup) {
466:                log.debug("Handling row group with " + rowGroup.length
467:                        + " rows...");
468:                MinOptMax[] rowHeights = new MinOptMax[rowGroup.length];
469:                MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length];
470:                EffRow row;
471:                int maxColumnCount = 0;
472:                List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units
473:                for (int rgi = 0; rgi < rowGroup.length; rgi++) {
474:                    row = rowGroup[rgi];
475:                    rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
476:                    explicitRowHeights[rgi] = new MinOptMax(0, 0,
477:                            Integer.MAX_VALUE);
478:
479:                    pgus.clear();
480:                    TableRow tableRow = null;
481:                    // The row's minimum content height; 0 if the row's height is auto, otherwise
482:                    // the .minimum component of the explicitely specified value
483:                    int minContentHeight = 0;
484:                    int maxCellHeight = 0;
485:                    int effRowContentHeight = 0;
486:                    for (int j = 0; j < row.getGridUnits().size(); j++) {
487:                        //                assert maxColumnCount == 0 || maxColumnCount == row.getGridUnits().size(); // TODO vh
488:                        maxColumnCount = Math.max(maxColumnCount, row
489:                                .getGridUnits().size());
490:                        GridUnit gu = row.getGridUnit(j);
491:                        if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu
492:                                .isLastGridUnitRowSpan()))
493:                                && !gu.isEmpty()) {
494:                            PrimaryGridUnit primary = gu.getPrimary();
495:
496:                            if (gu.isPrimary()) {
497:                                primary.getCellLM().setParent(getTableLM());
498:
499:                                //Determine the table-row if any
500:                                if (tableRow == null
501:                                        && primary.getRow() != null) {
502:                                    tableRow = primary.getRow();
503:
504:                                    //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms
505:                                    LengthRangeProperty bpd = tableRow
506:                                            .getBlockProgressionDimension();
507:                                    if (!bpd.getMinimum(getTableLM()).isAuto()) {
508:                                        minContentHeight = Math.max(
509:                                                minContentHeight, bpd
510:                                                        .getMinimum(
511:                                                                getTableLM())
512:                                                        .getLength().getValue(
513:                                                                getTableLM()));
514:                                    }
515:                                    MinOptMaxUtil.restrict(
516:                                            explicitRowHeights[rgi], bpd,
517:                                            getTableLM());
518:
519:                                }
520:
521:                                //Calculate width of cell
522:                                int spanWidth = 0;
523:                                for (int i = primary.getStartCol(); i < primary
524:                                        .getStartCol()
525:                                        + primary.getCell()
526:                                                .getNumberColumnsSpanned(); i++) {
527:                                    if (getTableLM().getColumns().getColumn(
528:                                            i + 1) != null) {
529:                                        spanWidth += getTableLM().getColumns()
530:                                                .getColumn(i + 1)
531:                                                .getColumnWidth().getValue(
532:                                                        getTableLM());
533:                                    }
534:                                }
535:                                LayoutContext childLC = new LayoutContext(0);
536:                                childLC.setStackLimit(context.getStackLimit()); //necessary?
537:                                childLC.setRefIPD(spanWidth);
538:
539:                                //Get the element list for the cell contents
540:                                LinkedList elems = primary.getCellLM()
541:                                        .getNextKnuthElements(childLC,
542:                                                alignment);
543:                                //Temporary? Multiple calls in case of break conditions.
544:                                //TODO Revisit when table layout is restartable
545:                                while (!primary.getCellLM().isFinished()) {
546:                                    LinkedList additionalElems = primary
547:                                            .getCellLM().getNextKnuthElements(
548:                                                    childLC, alignment);
549:                                    elems.addAll(additionalElems);
550:                                }
551:                                ElementListObserver
552:                                        .observe(elems, "table-cell", primary
553:                                                .getCell().getId());
554:
555:                                if ((elems.size() > 0)
556:                                        && ((KnuthElement) elems.getLast())
557:                                                .isForcedBreak()) {
558:                                    // a descendant of this block has break-after
559:                                    log
560:                                            .debug("Descendant of table-cell signals break: "
561:                                                    + primary.getCellLM()
562:                                                            .isFinished());
563:                                }
564:
565:                                primary.setElements(elems);
566:
567:                                if (childLC.isKeepWithNextPending()) {
568:                                    log
569:                                            .debug("child LM signals pending keep-with-next");
570:                                    primary.setFlag(
571:                                            GridUnit.KEEP_WITH_NEXT_PENDING,
572:                                            true);
573:                                }
574:                                if (childLC.isKeepWithPreviousPending()) {
575:                                    log
576:                                            .debug("child LM signals pending keep-with-previous");
577:                                    primary
578:                                            .setFlag(
579:                                                    GridUnit.KEEP_WITH_PREVIOUS_PENDING,
580:                                                    true);
581:                                }
582:                            }
583:
584:                            //Calculate height of cell contents
585:                            primary.setContentLength(ElementListUtils
586:                                    .calcContentLength(primary.getElements()));
587:                            maxCellHeight = Math.max(maxCellHeight, primary
588:                                    .getContentLength());
589:
590:                            //Calculate height of row, see CSS21, 17.5.3 Table height algorithms
591:                            if (gu.isLastGridUnitRowSpan()) {
592:                                int effCellContentHeight = minContentHeight;
593:                                LengthRangeProperty bpd = primary.getCell()
594:                                        .getBlockProgressionDimension();
595:                                if (!bpd.getMinimum(getTableLM()).isAuto()) {
596:                                    effCellContentHeight = Math.max(
597:                                            effCellContentHeight, bpd
598:                                                    .getMinimum(getTableLM())
599:                                                    .getLength().getValue(
600:                                                            getTableLM()));
601:                                }
602:                                if (!bpd.getOptimum(getTableLM()).isAuto()) {
603:                                    effCellContentHeight = Math.max(
604:                                            effCellContentHeight, bpd
605:                                                    .getOptimum(getTableLM())
606:                                                    .getLength().getValue(
607:                                                            getTableLM()));
608:                                }
609:                                if (gu.getRowSpanIndex() == 0) {
610:                                    //TODO ATM only non-row-spanned cells are taken for this
611:                                    MinOptMaxUtil.restrict(
612:                                            explicitRowHeights[rgi], bpd,
613:                                            tableLM);
614:                                }
615:                                effCellContentHeight = Math.max(
616:                                        effCellContentHeight, primary
617:                                                .getContentLength());
618:
619:                                int borderWidths;
620:                                if (isSeparateBorderModel()) {
621:                                    borderWidths = primary.getBorders()
622:                                            .getBorderBeforeWidth(false)
623:                                            + primary.getBorders()
624:                                                    .getBorderAfterWidth(false);
625:                                } else {
626:                                    borderWidths = primary
627:                                            .getHalfMaxBorderWidth();
628:                                }
629:                                int padding = 0;
630:                                effRowContentHeight = Math.max(
631:                                        effRowContentHeight,
632:                                        effCellContentHeight);
633:                                CommonBorderPaddingBackground cbpb = primary
634:                                        .getCell()
635:                                        .getCommonBorderPaddingBackground();
636:                                padding += cbpb.getPaddingBefore(false, primary
637:                                        .getCellLM());
638:                                padding += cbpb.getPaddingAfter(false, primary
639:                                        .getCellLM());
640:                                int effRowHeight = effCellContentHeight
641:                                        + padding
642:                                        + borderWidths
643:                                        + 2
644:                                        * getTableLM()
645:                                                .getHalfBorderSeparationBPD();
646:                                for (int previous = 0; previous < gu
647:                                        .getRowSpanIndex(); previous++) {
648:                                    effRowHeight -= rowHeights[rgi - previous
649:                                            - 1].opt;
650:                                }
651:                                if (effRowHeight > rowHeights[rgi].min) {
652:                                    //This is the new height of the (grid) row
653:                                    MinOptMaxUtil.extendMinimum(
654:                                            rowHeights[rgi], effRowHeight,
655:                                            false);
656:                                }
657:                            }
658:
659:                            if (gu.isPrimary()) {
660:                                pgus.add(primary);
661:                            }
662:                        }
663:                    }
664:
665:                    row.setHeight(rowHeights[rgi]);
666:                    row.setExplicitHeight(explicitRowHeights[rgi]);
667:                    if (effRowContentHeight > row.getExplicitHeight().max) {
668:                        log
669:                                .warn(FONode
670:                                        .decorateWithContextInfo(
671:                                                "The contents of row "
672:                                                        + (row.getIndex() + 1)
673:                                                        + " are taller than they should be (there is a"
674:                                                        + " block-progression-dimension or height constraint on the indicated row)."
675:                                                        + " Due to its contents the row grows"
676:                                                        + " to "
677:                                                        + effRowContentHeight
678:                                                        + " millipoints, but the row shouldn't get"
679:                                                        + " any taller than "
680:                                                        + row
681:                                                                .getExplicitHeight()
682:                                                        + " millipoints.", row
683:                                                        .getTableRow()));
684:                    }
685:                }
686:                if (log.isDebugEnabled()) {
687:                    log.debug("rowGroup:");
688:                    for (int i = 0; i < rowHeights.length; i++) {
689:                        log.debug("  height=" + rowHeights[i] + " explicit="
690:                                + explicitRowHeights[i]);
691:                    }
692:                }
693:                LinkedList returnedList = this .stepper
694:                        .getCombinedKnuthElementsForRowGroup(context, rowGroup,
695:                                maxColumnCount, bodyType);
696:                if (returnedList != null) {
697:                    returnList.addAll(returnedList);
698:                }
699:
700:            }
701:
702:            /**
703:             * Retuns the X offset of the given grid unit.
704:             * @param gu the grid unit
705:             * @return the requested X offset
706:             */
707:            protected int getXOffsetOfGridUnit(GridUnit gu) {
708:                int col = gu.getStartCol();
709:                return startXOffset
710:                        + getTableLM().getColumns().getXOffset(col + 1,
711:                                getTableLM());
712:            }
713:
714:            /**
715:             * Adds the areas generated by this layout manager to the area tree.
716:             * @param parentIter the position iterator
717:             * @param layoutContext the layout context for adding areas
718:             */
719:            public void addAreas(PositionIterator parentIter,
720:                    LayoutContext layoutContext) {
721:                this .usedBPD = 0;
722:                RowPainter painter = new RowPainter(this , layoutContext);
723:
724:                List positions = new java.util.ArrayList();
725:                List headerElements = null;
726:                List footerElements = null;
727:                Position firstPos = null;
728:                Position lastPos = null;
729:                Position lastCheckPos = null;
730:                while (parentIter.hasNext()) {
731:                    Position pos = (Position) parentIter.next();
732:                    if (pos instanceof  SpaceHandlingBreakPosition) {
733:                        //This position has only been needed before addAreas was called, now we need the
734:                        //original one created by the layout manager.
735:                        pos = ((SpaceHandlingBreakPosition) pos)
736:                                .getOriginalBreakPosition();
737:                    }
738:                    if (pos == null) {
739:                        continue;
740:                    }
741:                    if (firstPos == null) {
742:                        firstPos = pos;
743:                    }
744:                    lastPos = pos;
745:                    if (pos.getIndex() >= 0) {
746:                        lastCheckPos = pos;
747:                    }
748:                    if (pos instanceof  TableHeaderFooterPosition) {
749:                        TableHeaderFooterPosition thfpos = (TableHeaderFooterPosition) pos;
750:                        //these positions need to be unpacked
751:                        if (thfpos.header) {
752:                            //Positions for header will be added first
753:                            headerElements = thfpos.nestedElements;
754:                        } else {
755:                            //Positions for footers are simply added at the end
756:                            footerElements = thfpos.nestedElements;
757:                        }
758:                    } else if (pos instanceof  TableHFPenaltyPosition) {
759:                        //ignore for now, see special handling below if break is at a penalty
760:                        //Only if the last position in this part/page us such a position it will be used 
761:                    } else {
762:                        //leave order as is for the rest
763:                        positions.add(pos);
764:                    }
765:                }
766:                if (lastPos instanceof  TableHFPenaltyPosition) {
767:                    TableHFPenaltyPosition penaltyPos = (TableHFPenaltyPosition) lastPos;
768:                    log.debug("Break at penalty!");
769:                    if (penaltyPos.headerElements != null) {
770:                        //Header positions for the penalty position are in the last element and need to
771:                        //be handled first before all other TableContentPositions
772:                        headerElements = penaltyPos.headerElements;
773:                    }
774:                    if (penaltyPos.footerElements != null) {
775:                        footerElements = penaltyPos.footerElements;
776:                    }
777:                }
778:
779:                Map markers = getTableLM().getTable().getMarkers();
780:                if (markers != null) {
781:                    getTableLM().getCurrentPV().addMarkers(markers, true,
782:                            getTableLM().isFirst(firstPos),
783:                            getTableLM().isLast(lastCheckPos));
784:                }
785:
786:                if (headerElements != null) {
787:                    //header positions for the last part are the second-to-last element and need to
788:                    //be handled first before all other TableContentPositions
789:                    PositionIterator nestedIter = new KnuthPossPosIter(
790:                            headerElements);
791:                    iterateAndPaintPositions(nestedIter, painter);
792:                }
793:
794:                //Iterate over all steps
795:                Iterator posIter = positions.iterator();
796:                iterateAndPaintPositions(posIter, painter);
797:
798:                if (footerElements != null) {
799:                    //Positions for footers are simply added at the end
800:                    PositionIterator nestedIter = new KnuthPossPosIter(
801:                            footerElements);
802:                    iterateAndPaintPositions(nestedIter, painter);
803:                }
804:
805:                this .usedBPD += painter.getAccumulatedBPD();
806:
807:                if (markers != null) {
808:                    getTableLM().getCurrentPV().addMarkers(markers, false,
809:                            getTableLM().isFirst(firstPos),
810:                            getTableLM().isLast(lastCheckPos));
811:                }
812:            }
813:
814:            /**
815:             * Iterates over a part of the table (header, footer, body) and paints the related
816:             * elements.
817:             * 
818:             * @param iterator iterator over Position elements. Those positions correspond to the
819:             * elements of the table present on the current page
820:             * @param painter
821:             */
822:            private void iterateAndPaintPositions(Iterator iterator,
823:                    RowPainter painter) {
824:                List lst = new java.util.ArrayList();
825:                boolean firstPos = false;
826:                TableBody body = null;
827:                while (iterator.hasNext()) {
828:                    Position pos = (Position) iterator.next();
829:                    if (pos instanceof  TableContentPosition) {
830:                        TableContentPosition tcpos = (TableContentPosition) pos;
831:                        lst.add(tcpos);
832:                        GridUnitPart part = (GridUnitPart) tcpos.gridUnitParts
833:                                .get(0);
834:                        if (body == null) {
835:                            body = part.pgu.getBody();
836:                        }
837:                        if (tcpos
838:                                .getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
839:                                && tcpos.row.getFlag(EffRow.FIRST_IN_PART)) {
840:                            firstPos = true;
841:
842:                        }
843:                        if (tcpos
844:                                .getFlag(TableContentPosition.LAST_IN_ROWGROUP)
845:                                && tcpos.row.getFlag(EffRow.LAST_IN_PART)) {
846:                            log.trace("LAST_IN_ROWGROUP + LAST_IN_PART");
847:                            handleMarkersAndPositions(lst, body, firstPos,
848:                                    true, painter);
849:                            //reset
850:                            firstPos = false;
851:                            body = null;
852:                            lst.clear();
853:                        }
854:                    } else {
855:                        if (log.isDebugEnabled()) {
856:                            log.debug("Ignoring position: " + pos);
857:                        }
858:                    }
859:                }
860:                if (body != null) {
861:                    // Entering this block means that the end of the current table-part hasn't
862:                    // been reached (otherwise it would have been caught by the test above). So
863:                    // lastPos is necessarily false
864:                    handleMarkersAndPositions(lst, body, firstPos, false,
865:                            painter);
866:                }
867:                painter.addAreasAndFlushRow(true);
868:            }
869:
870:            private void handleMarkersAndPositions(List positions,
871:                    TableBody body, boolean firstPos, boolean lastPos,
872:                    RowPainter painter) {
873:                getTableLM().getCurrentPV().addMarkers(body.getMarkers(), true,
874:                        firstPos, lastPos);
875:                int size = positions.size();
876:                for (int i = 0; i < size; i++) {
877:                    painter
878:                            .handleTableContentPosition((TableContentPosition) positions
879:                                    .get(i));
880:                }
881:                getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
882:                        false, firstPos, lastPos);
883:            }
884:
885:            /**
886:             * Get the area for a row for background.
887:             * @param row the table-row object or null
888:             * @return the row area or null if there's no background to paint
889:             */
890:            public Block getRowArea(TableRow row) {
891:                if (row == null
892:                        || !row.getCommonBorderPaddingBackground()
893:                                .hasBackground()) {
894:                    return null;
895:                } else {
896:                    Block block = new Block();
897:                    block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
898:                    block.setPositioning(Block.ABSOLUTE);
899:                    return block;
900:                }
901:            }
902:
903:            /**
904:             * Adds the area for the row background if any.
905:             * @param row row for which to generate the background
906:             * @param bpd block-progression-dimension of the row
907:             * @param ipd inline-progression-dimension of the row
908:             * @param yoffset Y offset at which to paint
909:             */
910:            public void addRowBackgroundArea(TableRow row, int bpd, int ipd,
911:                    int yoffset) {
912:                //Add row background if any
913:                Block rowBackground = getRowArea(row);
914:                if (rowBackground != null) {
915:                    rowBackground.setBPD(bpd);
916:                    rowBackground.setIPD(ipd);
917:                    rowBackground.setXOffset(this .startXOffset);
918:                    rowBackground.setYOffset(yoffset);
919:                    getTableLM().addChildArea(rowBackground);
920:                    TraitSetter.addBackground(rowBackground, row
921:                            .getCommonBorderPaddingBackground(), getTableLM());
922:                }
923:            }
924:
925:            /**
926:             * Sets the overall starting x-offset. Used for proper placement of cells.
927:             * @param startXOffset starting x-offset (table's start-indent)
928:             */
929:            public void setStartXOffset(int startXOffset) {
930:                this .startXOffset = startXOffset;
931:            }
932:
933:            /**
934:             * @return the amount of block-progression-dimension used by the content
935:             */
936:            public int getUsedBPD() {
937:                return this .usedBPD;
938:            }
939:
940:            // --------- Property Resolution related functions --------- //
941:
942:            /**
943:             * @see org.apache.fop.datatypes.PercentBaseContext#getBaseLength(int, FObj)
944:             */
945:            public int getBaseLength(int lengthBase, FObj fobj) {
946:                return tableLM.getBaseLength(lengthBase, fobj);
947:            }
948:
949:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.