Source Code Cross Referenced for MultiColumnText.java in  » PDF » pdf-itext » com » lowagie » text » pdf » 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 » PDF » pdf itext » com.lowagie.text.pdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: MultiColumnText.java 2441 2006-10-27 17:24:01Z xlv $
003:         * $Name$
004:         *
005:         * Copyright 2004 Steve Appling
006:         *
007:         * The contents of this file are subject to the Mozilla Public License Version 1.1
008:         * (the "License"); you may not use this file except in compliance with the License.
009:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010:         *
011:         * Software distributed under the License is distributed on an "AS IS" basis,
012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013:         * for the specific language governing rights and limitations under the License.
014:         *
015:         * The Original Code is 'iText, a free JAVA-PDF library'.
016:         *
017:         * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018:         * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
019:         * All Rights Reserved.
020:         * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021:         * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
022:         *
023:         * Contributor(s): all the names of the contributors are added in the source code
024:         * where applicable.
025:         *
026:         * Alternatively, the contents of this file may be used under the terms of the
027:         * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028:         * provisions of LGPL are applicable instead of those above.  If you wish to
029:         * allow use of your version of this file only under the terms of the LGPL
030:         * License and not to allow others to use your version of this file under
031:         * the MPL, indicate your decision by deleting the provisions above and
032:         * replace them with the notice and other provisions required by the LGPL.
033:         * If you do not delete the provisions above, a recipient may use your version
034:         * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035:         *
036:         * This library is free software; you can redistribute it and/or modify it
037:         * under the terms of the MPL as stated above or under the terms of the GNU
038:         * Library General Public License as published by the Free Software Foundation;
039:         * either version 2 of the License, or any later version.
040:         *
041:         * This library is distributed in the hope that it will be useful, but WITHOUT
042:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043:         * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044:         * details.
045:         *
046:         * If you didn't download this code from the following link, you should check if
047:         * you aren't using an obsolete version:
048:         * http://www.lowagie.com/iText/
049:         */
050:
051:        package com.lowagie.text.pdf;
052:
053:        import java.util.ArrayList;
054:
055:        import com.lowagie.text.Chunk;
056:        import com.lowagie.text.DocumentException;
057:        import com.lowagie.text.Element;
058:        import com.lowagie.text.ElementListener;
059:        import com.lowagie.text.Phrase;
060:        import com.lowagie.text.Rectangle;
061:
062:        /**
063:         * Formats content into one or more columns bounded by a
064:         * rectangle.  The columns may be simple rectangles or
065:         * more complicated shapes. Add all of the columns before
066:         * adding content. Column continuation is supported. A MultiColumnText object may be added to
067:         * a document using <CODE>Document.add</CODE>.
068:         * @author Steve Appling
069:         */
070:        public class MultiColumnText implements  Element {
071:
072:            /** special constant for automatic calculation of height */
073:            public static final float AUTOMATIC = -1f;
074:
075:            /**
076:             * total desiredHeight of columns.  If <CODE>AUTOMATIC</CODE>, this means fill pages until done.
077:             * This may be larger than one page
078:             */
079:            private float desiredHeight;
080:
081:            /**
082:             * total height of element written out so far
083:             */
084:            private float totalHeight;
085:
086:            /**
087:             * true if all the text could not be written out due to height restriction
088:             */
089:            private boolean overflow;
090:
091:            /**
092:             * Top of the columns - y position on starting page.
093:             * If <CODE>AUTOMATIC</CODE>, it means current y position when added to document
094:             */
095:            private float top;
096:
097:            /**
098:             * used to store the y position of the bottom of the page
099:             */
100:            private float pageBottom;
101:
102:            /**
103:             * ColumnText object used to do all the real work.  This same object is used for all columns
104:             */
105:            private ColumnText columnText;
106:
107:            /**
108:             * Array of <CODE>ColumnDef</CODE> objects used to define the columns
109:             */
110:            private ArrayList columnDefs;
111:
112:            /**
113:             * true if all columns are simple (rectangular)
114:             */
115:            private boolean simple = true;
116:
117:            private int currentColumn = 0;
118:
119:            private float nextY = AUTOMATIC;
120:
121:            private boolean columnsRightToLeft = false;
122:
123:            private PdfDocument document;
124:
125:            /**
126:             * Default constructor.  Sets height to <CODE>AUTOMATIC</CODE>.
127:             * Columns will repeat on each page as necessary to accomodate content length.
128:             */
129:            public MultiColumnText() {
130:                this (AUTOMATIC);
131:            }
132:
133:            /**
134:             * Construct a MultiColumnText container of the specified height.
135:             * If height is <CODE>AUTOMATIC</CODE>, fill complete pages until done.
136:             * If a specific height is used, it may span one or more pages.
137:             *
138:             * @param height
139:             */
140:            public MultiColumnText(float height) {
141:                columnDefs = new ArrayList();
142:                desiredHeight = height;
143:                top = AUTOMATIC;
144:                // canvas will be set later
145:                columnText = new ColumnText(null);
146:                totalHeight = 0f;
147:            }
148:
149:            /**
150:             * Construct a MultiColumnText container of the specified height
151:             * starting at the specified Y position.
152:             *
153:             * @param height
154:             * @param top
155:             */
156:            public MultiColumnText(float top, float height) {
157:                columnDefs = new ArrayList();
158:                desiredHeight = height;
159:                this .top = top;
160:                nextY = top;
161:                // canvas will be set later
162:                columnText = new ColumnText(null);
163:                totalHeight = 0f;
164:            }
165:
166:            /**
167:             * Indicates that all of the text did not fit in the
168:             * specified height. Note that isOverflow will return
169:             * false before the MultiColumnText object has been
170:             * added to the document.  It will always be false if
171:             * the height is AUTOMATIC.
172:             *
173:             * @return true if there is still space left in the column
174:             */
175:            public boolean isOverflow() {
176:                return overflow;
177:            }
178:
179:            /**
180:             * Copy the parameters from the specified ColumnText to use
181:             * when rendering.  Parameters like <CODE>setArabicOptions</CODE>
182:             * must be set in this way.
183:             *
184:             * @param sourceColumn
185:             */
186:            public void useColumnParams(ColumnText sourceColumn) {
187:                // note that canvas will be overwritten later
188:                columnText.setSimpleVars(sourceColumn);
189:            }
190:
191:            /**
192:             * Add a new column.  The parameters are limits for each column
193:             * wall in the format of a sequence of points (x1,y1,x2,y2,...).
194:             *
195:             * @param left  limits for left column
196:             * @param right limits for right column
197:             */
198:            public void addColumn(float[] left, float[] right) {
199:                ColumnDef nextDef = new ColumnDef(left, right);
200:                simple = nextDef.isSimple();
201:                columnDefs.add(nextDef);
202:            }
203:
204:            /**
205:             * Add a simple rectangular column with specified left
206:             * and right x position boundaries.
207:             *
208:             * @param left  left boundary
209:             * @param right right boundary
210:             */
211:            public void addSimpleColumn(float left, float right) {
212:                ColumnDef newCol = new ColumnDef(left, right);
213:                columnDefs.add(newCol);
214:            }
215:
216:            /**
217:             * Add the specified number of evenly spaced rectangular columns.
218:             * Columns will be seperated by the specified gutterWidth.
219:             *
220:             * @param left        left boundary of first column
221:             * @param right       right boundary of last column
222:             * @param gutterWidth width of gutter spacing between columns
223:             * @param numColumns  number of columns to add
224:             */
225:            public void addRegularColumns(float left, float right,
226:                    float gutterWidth, int numColumns) {
227:                float currX = left;
228:                float width = right - left;
229:                float colWidth = (width - (gutterWidth * (numColumns - 1)))
230:                        / numColumns;
231:                for (int i = 0; i < numColumns; i++) {
232:                    addSimpleColumn(currX, currX + colWidth);
233:                    currX += colWidth + gutterWidth;
234:                }
235:            }
236:
237:            /**
238:             * Add an element to be rendered in a column.
239:             * Note that you can only add a <CODE>Phrase</CODE>
240:             * or a <CODE>Chunk</CODE> if the columns are
241:             * not all simple.  This is an underlying restriction in
242:             * {@link com.lowagie.text.pdf.ColumnText}
243:             *
244:             * @param element element to add
245:             * @throws DocumentException if element can't be added
246:             */
247:            public void addElement(Element element) throws DocumentException {
248:                if (simple) {
249:                    columnText.addElement(element);
250:                } else if (element instanceof  Phrase) {
251:                    columnText.addText((Phrase) element);
252:                } else if (element instanceof  Chunk) {
253:                    columnText.addText((Chunk) element);
254:                } else {
255:                    throw new DocumentException("Can't add "
256:                            + element.getClass()
257:                            + " to MultiColumnText with complex columns");
258:                }
259:            }
260:
261:            /**
262:             * Write out the columns.  After writing, use
263:             * {@link #isOverflow()} to see if all text was written.
264:             * @param canvas PdfContentByte to write with
265:             * @param document document to write to (only used to get page limit info)
266:             * @param documentY starting y position to begin writing at
267:             * @return the current height (y position) after writing the columns
268:             * @throws DocumentException on error
269:             */
270:            public float write(PdfContentByte canvas, PdfDocument document,
271:                    float documentY) throws DocumentException {
272:                this .document = document;
273:                columnText.setCanvas(canvas);
274:                if (columnDefs.isEmpty()) {
275:                    throw new DocumentException(
276:                            "MultiColumnText has no columns");
277:                }
278:                overflow = false;
279:                pageBottom = document.bottom();
280:                float currentHeight = 0;
281:                boolean done = false;
282:                try {
283:                    while (!done) {
284:                        if (nextY == AUTOMATIC) {
285:                            nextY = document.getVerticalPosition(true); // RS - 07/07/2005 - - Get current doc writing position for top of columns on new page.
286:                        }
287:                        if (top == AUTOMATIC) {
288:                            top = document.getVerticalPosition(true); // RS - 07/07/2005 - Get current doc writing position for top of columns on new page.
289:                        }
290:
291:                        ColumnDef currentDef = (ColumnDef) columnDefs
292:                                .get(getCurrentColumn());
293:                        columnText.setYLine(top);
294:
295:                        float[] left = currentDef
296:                                .resolvePositions(Rectangle.LEFT);
297:                        float[] right = currentDef
298:                                .resolvePositions(Rectangle.RIGHT);
299:                        if (document.isMarginMirroring()
300:                                && document.getPageNumber() % 2 == 0) {
301:                            float delta = document.rightMargin()
302:                                    - document.left();
303:                            left = (float[]) left.clone();
304:                            right = (float[]) right.clone();
305:                            for (int i = 0; i < left.length; i += 2) {
306:                                left[i] -= delta;
307:                            }
308:                            for (int i = 0; i < right.length; i += 2) {
309:                                right[i] -= delta;
310:                            }
311:                        }
312:
313:                        currentHeight = Math.max(currentHeight, getHeight(left,
314:                                right));
315:
316:                        if (currentDef.isSimple()) {
317:                            columnText.setSimpleColumn(left[2], left[3],
318:                                    right[0], right[1]);
319:                        } else {
320:                            columnText.setColumns(left, right);
321:                        }
322:
323:                        int result = columnText.go();
324:                        if ((result & ColumnText.NO_MORE_TEXT) != 0) {
325:                            done = true;
326:                            top = columnText.getYLine();
327:                        } else if (shiftCurrentColumn()) {
328:                            top = nextY;
329:                        } else { // check if we are done because of height
330:                            totalHeight += currentHeight;
331:                            if ((desiredHeight != AUTOMATIC)
332:                                    && (totalHeight >= desiredHeight)) {
333:                                overflow = true;
334:                                break;
335:                            } else { // need to start new page and reset the columns
336:                                documentY = nextY;
337:                                newPage();
338:                                currentHeight = 0;
339:                            }
340:                        }
341:                    }
342:                } catch (DocumentException ex) {
343:                    ex.printStackTrace();
344:                    throw ex;
345:                }
346:                if (desiredHeight == AUTOMATIC && columnDefs.size() == 1) {
347:                    currentHeight = documentY - columnText.getYLine();
348:                }
349:                return currentHeight;
350:            }
351:
352:            private void newPage() throws DocumentException {
353:                resetCurrentColumn();
354:                if (desiredHeight == AUTOMATIC) {
355:                    top = nextY = AUTOMATIC;
356:                } else {
357:                    top = nextY;
358:                }
359:                totalHeight = 0;
360:                if (document != null) {
361:                    document.newPage();
362:                }
363:            }
364:
365:            /**
366:             * Figure out the height of a column from the border extents
367:             *
368:             * @param left  left border
369:             * @param right right border
370:             * @return height
371:             */
372:            private float getHeight(float[] left, float[] right) {
373:                float max = Float.MIN_VALUE;
374:                float min = Float.MAX_VALUE;
375:                for (int i = 0; i < left.length; i += 2) {
376:                    min = Math.min(min, left[i + 1]);
377:                    max = Math.max(max, left[i + 1]);
378:                }
379:                for (int i = 0; i < right.length; i += 2) {
380:                    min = Math.min(min, right[i + 1]);
381:                    max = Math.max(max, right[i + 1]);
382:                }
383:                return max - min;
384:            }
385:
386:            /**
387:             * Processes the element by adding it to an
388:             * <CODE>ElementListener</CODE>.
389:             *
390:             * @param	listener	an <CODE>ElementListener</CODE>
391:             * @return	<CODE>true</CODE> if the element was processed successfully
392:             */
393:            public boolean process(ElementListener listener) {
394:                try {
395:                    return listener.add(this );
396:                } catch (DocumentException de) {
397:                    return false;
398:                }
399:            }
400:
401:            /**
402:             * Gets the type of the text element.
403:             *
404:             * @return	a type
405:             */
406:
407:            public int type() {
408:                return Element.MULTI_COLUMN_TEXT;
409:            }
410:
411:            /**
412:             * Returns null - not used
413:             *
414:             * @return	null
415:             */
416:
417:            public ArrayList getChunks() {
418:                return null;
419:            }
420:
421:            /**
422:             * Calculates the appropriate y position for the bottom
423:             * of the columns on this page.
424:             *
425:             * @return the y position of the bottom of the columns
426:             */
427:            private float getColumnBottom() {
428:                if (desiredHeight == AUTOMATIC) {
429:                    return pageBottom;
430:                } else {
431:                    return Math.max(top - (desiredHeight - totalHeight),
432:                            pageBottom);
433:                }
434:            }
435:
436:            /**
437:             * Moves the text insertion point to the beginning of the next column, issuing a page break if
438:             * needed.
439:             * @throws DocumentException on error
440:             */
441:            public void nextColumn() throws DocumentException {
442:                currentColumn = (currentColumn + 1) % columnDefs.size();
443:                top = nextY;
444:                if (currentColumn == 0) {
445:                    newPage();
446:                }
447:            }
448:
449:            /**
450:             * Gets the current column.
451:             * @return the current column
452:             */
453:            public int getCurrentColumn() {
454:                if (columnsRightToLeft) {
455:                    return (columnDefs.size() - currentColumn - 1);
456:                }
457:                return currentColumn;
458:            }
459:
460:            /**
461:             * Resets the current column.
462:             */
463:            public void resetCurrentColumn() {
464:                currentColumn = 0;
465:            }
466:
467:            /**
468:             * Shifts the current column.
469:             * @return true if the currentcolumn has changed
470:             */
471:            public boolean shiftCurrentColumn() {
472:                if (currentColumn + 1 < columnDefs.size()) {
473:                    currentColumn++;
474:                    return true;
475:                }
476:                return false;
477:            }
478:
479:            /**
480:             * Sets the direction of the columns.
481:             * @param direction true = right2left; false = left2right
482:             */
483:            public void setColumnsRightToLeft(boolean direction) {
484:                columnsRightToLeft = direction;
485:            }
486:
487:            /** Sets the ratio between the extra word spacing and the extra character spacing
488:             * when the text is fully justified.
489:             * Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing.
490:             * If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing
491:             * will be zero.
492:             * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
493:             */
494:            public void setSpaceCharRatio(float spaceCharRatio) {
495:                columnText.setSpaceCharRatio(spaceCharRatio);
496:            }
497:
498:            /** Sets the run direction. 
499:             * @param runDirection the run direction
500:             */
501:            public void setRunDirection(int runDirection) {
502:                columnText.setRunDirection(runDirection);
503:            }
504:
505:            /** Sets the arabic shaping options. The option can be AR_NOVOWEL,
506:             * AR_COMPOSEDTASHKEEL and AR_LIG.
507:             * @param arabicOptions the arabic shaping options
508:             */
509:            public void setArabicOptions(int arabicOptions) {
510:                columnText.setArabicOptions(arabicOptions);
511:            }
512:
513:            /** Sets the default alignment
514:             * @param alignment the default alignment
515:             */
516:            public void setAlignment(int alignment) {
517:                columnText.setAlignment(alignment);
518:            }
519:
520:            /**
521:             * Inner class used to define a column
522:             */
523:            private class ColumnDef {
524:                private float[] left;
525:                private float[] right;
526:
527:                ColumnDef(float[] newLeft, float[] newRight) {
528:                    left = newLeft;
529:                    right = newRight;
530:                }
531:
532:                ColumnDef(float leftPosition, float rightPosition) {
533:                    left = new float[4];
534:                    left[0] = leftPosition; // x1
535:                    left[1] = top; // y1
536:                    left[2] = leftPosition; // x2
537:                    if (desiredHeight == AUTOMATIC || top == AUTOMATIC) {
538:                        left[3] = AUTOMATIC;
539:                    } else {
540:                        left[3] = top - desiredHeight;
541:                    }
542:
543:                    right = new float[4];
544:                    right[0] = rightPosition; // x1
545:                    right[1] = top; // y1
546:                    right[2] = rightPosition; // x2
547:                    if (desiredHeight == AUTOMATIC || top == AUTOMATIC) {
548:                        right[3] = AUTOMATIC;
549:                    } else {
550:                        right[3] = top - desiredHeight;
551:                    }
552:                }
553:
554:                /**
555:                 * Resolves the positions for the specified side of the column
556:                 * into real numbers once the top of the column is known.
557:                 *
558:                 * @param side either <CODE>Rectangle.LEFT</CODE>
559:                 *             or <CODE>Rectangle.RIGHT</CODE>
560:                 * @return the array of floats for the side
561:                 */
562:                float[] resolvePositions(int side) {
563:                    if (side == Rectangle.LEFT) {
564:                        return resolvePositions(left);
565:                    } else {
566:                        return resolvePositions(right);
567:                    }
568:                }
569:
570:                private float[] resolvePositions(float[] positions) {
571:                    if (!isSimple()) {
572:                        return positions;
573:                    }
574:                    if (top == AUTOMATIC) {
575:                        // this is bad - must be programmer error
576:                        throw new RuntimeException(
577:                                "resolvePositions called with top=AUTOMATIC (-1).  "
578:                                        + "Top position must be set befure lines can be resolved");
579:                    }
580:                    positions[1] = top;
581:                    positions[3] = getColumnBottom();
582:                    return positions;
583:                }
584:
585:                /**
586:                 * Checks if column definition is a simple rectangle
587:                 * @return true if it is a simple column 
588:                 */
589:                private boolean isSimple() {
590:                    return (left.length == 4 && right.length == 4)
591:                            && (left[0] == left[2] && right[0] == right[2]);
592:                }
593:
594:            }
595:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.