001: /*
002: * $Id: Section.java 2748 2007-05-12 15:11:48Z blowagie $
003: * $Name$
004: *
005: * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
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, 2000, 2001, 2002 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, 2001, 2002 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;
052:
053: import java.util.ArrayList;
054: import java.util.Collection;
055: import java.util.Iterator;
056:
057: /**
058: * A <CODE>Section</CODE> is a part of a <CODE>Document</CODE> containing
059: * other <CODE>Section</CODE>s, <CODE>Paragraph</CODE>s, <CODE>List</CODE>
060: * and/or <CODE>Table</CODE>s.
061: * <P>
062: * Remark: you can not construct a <CODE>Section</CODE> yourself.
063: * You will have to ask an instance of <CODE>Section</CODE> to the
064: * <CODE>Chapter</CODE> or <CODE>Section</CODE> to which you want to
065: * add the new <CODE>Section</CODE>.
066: * <P>
067: * Example:
068: * <BLOCKQUOTE><PRE>
069: * Paragraph title2 = new Paragraph("This is Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
070: * Chapter chapter2 = new Chapter(title2, 2);
071: * Paragraph someText = new Paragraph("This is some text");
072: * chapter2.add(someText);
073: * Paragraph title21 = new Paragraph("This is Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
074: * <STRONG>Section section1 = chapter2.addSection(title21);</STRONG>
075: * Paragraph someSectionText = new Paragraph("This is some silly paragraph in a chapter and/or section. It contains some text to test the functionality of Chapters and Section.");
076: * <STRONG>section1.add(someSectionText);</STRONG>
077: * Paragraph title211 = new Paragraph("This is SubSection 1 in Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 14, Font.BOLD, new Color(255, 0, 0)));
078: * <STRONG>Section section11 = section1.addSection(40, title211, 2);</STRONG>
079: * <STRONG>section11.add(someSectionText);</STRONG>
080: * </PRE></BLOCKQUOTE>
081: */
082:
083: public class Section extends ArrayList implements TextElementArray {
084:
085: // constant
086: private static final long serialVersionUID = 3324172577544748043L;
087:
088: // member variables
089:
090: /** The title of this section. */
091: protected Paragraph title;
092:
093: /** The bookmark title if different from the content title */
094: protected String bookmarkTitle;
095:
096: /** The number of sectionnumbers that has to be shown before the section title. */
097: protected int numberDepth;
098:
099: /** The indentation of this section on the left side. */
100: protected float indentationLeft;
101:
102: /** The indentation of this section on the right side. */
103: protected float indentationRight;
104:
105: /** The additional indentation of the content of this section. */
106: protected float indentation;
107:
108: /** false if the bookmark children are not visible */
109: protected boolean bookmarkOpen = true;
110:
111: /** true if the section has to trigger a new page */
112: protected boolean triggerNewPage = false;
113:
114: /** This is the number of subsections. */
115: protected int subsections = 0;
116:
117: /** This is the complete list of sectionnumbers of this section and the parents of this section. */
118: protected ArrayList numbers = null;
119:
120: // constructors
121:
122: /**
123: * Constructs a new <CODE>Section</CODE>.
124: */
125: protected Section() {
126: title = new Paragraph();
127: numberDepth = 1;
128: }
129:
130: /**
131: * Constructs a new <CODE>Section</CODE>.
132: *
133: * @param title a <CODE>Paragraph</CODE>
134: * @param numberDepth the numberDepth
135: */
136: protected Section(Paragraph title, int numberDepth) {
137: this .numberDepth = numberDepth;
138: this .title = title;
139: }
140:
141: // implementation of the Element-methods
142:
143: /**
144: * Processes the element by adding it (or the different parts) to an
145: * <CODE>ElementListener</CODE>.
146: *
147: * @param listener the <CODE>ElementListener</CODE>
148: * @return <CODE>true</CODE> if the element was processed successfully
149: */
150: public boolean process(ElementListener listener) {
151: try {
152: Element element;
153: for (Iterator i = iterator(); i.hasNext();) {
154: element = (Element) i.next();
155: listener.add(element);
156: }
157: return true;
158: } catch (DocumentException de) {
159: return false;
160: }
161: }
162:
163: /**
164: * Gets the type of the text element.
165: *
166: * @return a type
167: */
168: public int type() {
169: return Element.SECTION;
170: }
171:
172: /**
173: * Checks if this object is a <CODE>Chapter</CODE>.
174: *
175: * @return <CODE>true</CODE> if it is a <CODE>Chapter</CODE>,
176: * <CODE>false</CODE> if it is a <CODE>Section</CODE>.
177: */
178: public boolean isChapter() {
179: return type() == Element.CHAPTER;
180: }
181:
182: /**
183: * Checks if this object is a <CODE>Section</CODE>.
184: *
185: * @return <CODE>true</CODE> if it is a <CODE>Section</CODE>,
186: * <CODE>false</CODE> if it is a <CODE>Chapter</CODE>.
187: */
188: public boolean isSection() {
189: return type() == Element.SECTION;
190: }
191:
192: /**
193: * Gets all the chunks in this element.
194: *
195: * @return an <CODE>ArrayList</CODE>
196: */
197: public ArrayList getChunks() {
198: ArrayList tmp = new ArrayList();
199: for (Iterator i = iterator(); i.hasNext();) {
200: tmp.addAll(((Element) i.next()).getChunks());
201: }
202: return tmp;
203: }
204:
205: // overriding some of the ArrayList-methods
206:
207: /**
208: * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
209: * to this <CODE>Section</CODE>.
210: *
211: * @param index index at which the specified element is to be inserted
212: * @param o an object of type <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>=
213: * @throws ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
214: */
215: public void add(int index, Object o) {
216: try {
217: Element element = (Element) o;
218: if (element.type() == Element.PARAGRAPH
219: || element.type() == Element.LIST
220: || element.type() == Element.CHUNK
221: || element.type() == Element.PHRASE
222: || element.type() == Element.ANCHOR
223: || element.type() == Element.ANNOTATION
224: || element.type() == Element.TABLE
225: || element.type() == Element.PTABLE
226: || element.type() == Element.IMGTEMPLATE
227: || element.type() == Element.JPEG
228: || element.type() == Element.IMGRAW) {
229: super .add(index, element);
230: } else {
231: throw new ClassCastException("You can add a "
232: + element.getClass().getName()
233: + " to a Section.");
234: }
235: } catch (ClassCastException cce) {
236: throw new ClassCastException(
237: "Insertion of illegal Element: " + cce.getMessage());
238: }
239: }
240:
241: /**
242: * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
243: * to this <CODE>Section</CODE>.
244: *
245: * @param o an object of type <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
246: * @return a boolean
247: * @throws ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or <CODE>Section</CODE>
248: */
249: public boolean add(Object o) {
250: try {
251: Element element = (Element) o;
252: if (element.type() == Element.PARAGRAPH
253: || element.type() == Element.LIST
254: || element.type() == Element.CHUNK
255: || element.type() == Element.PHRASE
256: || element.type() == Element.ANCHOR
257: || element.type() == Element.ANNOTATION
258: || element.type() == Element.TABLE
259: || element.type() == Element.IMGTEMPLATE
260: || element.type() == Element.PTABLE
261: || element.type() == Element.JPEG
262: || element.type() == Element.IMGRAW) {
263: return super .add(o);
264: } else if (element.type() == Element.SECTION) {
265: Section section = (Section) o;
266: section.setNumbers(++subsections, numbers);
267: return super .add(section);
268: } else if (o instanceof MarkedSection
269: && ((MarkedObject) o).element.type() == Element.SECTION) {
270: MarkedSection mo = (MarkedSection) o;
271: Section section = (Section) mo.element;
272: section.setNumbers(++subsections, numbers);
273: return super .add(mo);
274: } else if (element instanceof MarkedObject) {
275: return super .add(o);
276: } else {
277: throw new ClassCastException("You can add a "
278: + element.getClass().getName()
279: + " to a Section.");
280: }
281: } catch (ClassCastException cce) {
282: throw new ClassCastException(
283: "Insertion of illegal Element: " + cce.getMessage());
284: }
285: }
286:
287: /**
288: * Adds a collection of <CODE>Element</CODE>s
289: * to this <CODE>Section</CODE>.
290: *
291: * @param collection a collection of <CODE>Paragraph</CODE>s, <CODE>List</CODE>s and/or <CODE>Table</CODE>s
292: * @return <CODE>true</CODE> if the action succeeded, <CODE>false</CODE> if not.
293: * @throws ClassCastException if one of the objects isn't a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE>
294: */
295: public boolean addAll(Collection collection) {
296: for (Iterator iterator = collection.iterator(); iterator
297: .hasNext();) {
298: this .add(iterator.next());
299: }
300: return true;
301: }
302:
303: // methods that return a Section
304:
305: /**
306: * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
307: *
308: * @param indentation the indentation of the new section
309: * @param title the title of the new section
310: * @param numberDepth the numberDepth of the section
311: * @return a new Section object
312: */
313: public Section addSection(float indentation, Paragraph title,
314: int numberDepth) {
315: Section section = new Section(title, numberDepth);
316: section.setIndentation(indentation);
317: add(section);
318: return section;
319: }
320:
321: /**
322: * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
323: *
324: * @param indentation the indentation of the new section
325: * @param title the title of the new section
326: * @return a new Section object
327: */
328: public Section addSection(float indentation, Paragraph title) {
329: return addSection(indentation, title, numberDepth + 1);
330: }
331:
332: /**
333: * Creates a <CODE>Section</CODE>, add it to this <CODE>Section</CODE> and returns it.
334: *
335: * @param title the title of the new section
336: * @param numberDepth the numberDepth of the section
337: * @return a new Section object
338: */
339: public Section addSection(Paragraph title, int numberDepth) {
340: return addSection(0, title, numberDepth);
341: }
342:
343: /**
344: * Adds a marked section. For use in class MarkedSection only!
345: */
346: public MarkedSection addMarkedSection() {
347: MarkedSection section = new MarkedSection(new Section(null,
348: numberDepth + 1));
349: add(section);
350: return section;
351: }
352:
353: /**
354: * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
355: *
356: * @param title the title of the new section
357: * @return a new Section object
358: */
359: public Section addSection(Paragraph title) {
360: return addSection(0, title, numberDepth + 1);
361: }
362:
363: /**
364: * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
365: *
366: * @param indentation the indentation of the new section
367: * @param title the title of the new section
368: * @param numberDepth the numberDepth of the section
369: * @return a new Section object
370: */
371: public Section addSection(float indentation, String title,
372: int numberDepth) {
373: return addSection(indentation, new Paragraph(title),
374: numberDepth);
375: }
376:
377: /**
378: * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
379: *
380: * @param title the title of the new section
381: * @param numberDepth the numberDepth of the section
382: * @return a new Section object
383: */
384: public Section addSection(String title, int numberDepth) {
385: return addSection(new Paragraph(title), numberDepth);
386: }
387:
388: /**
389: * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
390: *
391: * @param indentation the indentation of the new section
392: * @param title the title of the new section
393: * @return a new Section object
394: */
395: public Section addSection(float indentation, String title) {
396: return addSection(indentation, new Paragraph(title));
397: }
398:
399: /**
400: * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
401: *
402: * @param title the title of the new section
403: * @return a new Section object
404: */
405: public Section addSection(String title) {
406: return addSection(new Paragraph(title));
407: }
408:
409: // public methods
410:
411: /**
412: * Sets the title of this section.
413: *
414: * @param title the new title
415: */
416: public void setTitle(Paragraph title) {
417: this .title = title;
418: }
419:
420: /**
421: * Returns the title, preceeded by a certain number of sectionnumbers.
422: *
423: * @return a <CODE>Paragraph</CODE>
424: */
425: public Paragraph getTitle() {
426: if (title == null) {
427: return null;
428: }
429: int depth = Math.min(numbers.size(), numberDepth);
430: if (depth < 1) {
431: return title;
432: }
433: StringBuffer buf = new StringBuffer(" ");
434: for (int i = 0; i < depth; i++) {
435: buf.insert(0, ".");
436: buf.insert(0, ((Integer) numbers.get(i)).intValue());
437: }
438: Paragraph result = new Paragraph(title);
439: result.add(0, new Chunk(buf.toString(), title.getFont()));
440: return result;
441: }
442:
443: /**
444: * Sets the depth of the sectionnumbers that will be shown preceding the title.
445: * <P>
446: * If the numberdepth is 0, the sections will not be numbered. If the numberdepth
447: * is 1, the section will be numbered with their own number. If the numberdepth is
448: * higher (for instance x > 1), the numbers of x - 1 parents will be shown.
449: *
450: * @param numberDepth the new numberDepth
451: */
452: public void setNumberDepth(int numberDepth) {
453: this .numberDepth = numberDepth;
454: }
455:
456: /**
457: * Returns the numberdepth of this <CODE>Section</CODE>.
458: *
459: * @return the numberdepth
460: */
461: public int getNumberDepth() {
462: return numberDepth;
463: }
464:
465: /**
466: * Sets the indentation of this <CODE>Section</CODE> on the left side.
467: *
468: * @param indentation the indentation
469: */
470: public void setIndentationLeft(float indentation) {
471: indentationLeft = indentation;
472: }
473:
474: /**
475: * Returns the indentation of this <CODE>Section</CODE> on the left side.
476: *
477: * @return the indentation
478: */
479: public float getIndentationLeft() {
480: return indentationLeft;
481: }
482:
483: /**
484: * Sets the indentation of this <CODE>Section</CODE> on the right side.
485: *
486: * @param indentation the indentation
487: */
488: public void setIndentationRight(float indentation) {
489: indentationRight = indentation;
490: }
491:
492: /**
493: * Returns the indentation of this <CODE>Section</CODE> on the right side.
494: *
495: * @return the indentation
496: */
497: public float getIndentationRight() {
498: return indentationRight;
499: }
500:
501: /**
502: * Sets the indentation of the content of this <CODE>Section</CODE>.
503: *
504: * @param indentation the indentation
505: */
506: public void setIndentation(float indentation) {
507: this .indentation = indentation;
508: }
509:
510: /**
511: * Returns the indentation of the content of this <CODE>Section</CODE>.
512: *
513: * @return the indentation
514: */
515: public float getIndentation() {
516: return indentation;
517: }
518:
519: /** Setter for property bookmarkOpen.
520: * @param bookmarkOpen false if the bookmark children are not
521: * visible.
522: */
523: public void setBookmarkOpen(boolean bookmarkOpen) {
524: this .bookmarkOpen = bookmarkOpen;
525: }
526:
527: /**
528: * Getter for property bookmarkOpen.
529: * @return Value of property bookmarkOpen.
530: */
531: public boolean isBookmarkOpen() {
532: return bookmarkOpen;
533: }
534:
535: /**
536: * Setter for property triggerNewPage.
537: * @param triggerNewPage true if a new page has to be triggered.
538: */
539: public void setTriggerNewPage(boolean triggerNewPage) {
540: this .triggerNewPage = triggerNewPage;
541: }
542:
543: /**
544: * Getter for property bookmarkOpen.
545: * @return Value of property triggerNewPage.
546: */
547: public boolean isTriggerNewPage() {
548: return triggerNewPage;
549: }
550:
551: /**
552: * Sets the bookmark title. The bookmark title is the same as the section title but
553: * can be changed with this method.
554: * @param bookmarkTitle the bookmark title
555: */
556: public void setBookmarkTitle(String bookmarkTitle) {
557: this .bookmarkTitle = bookmarkTitle;
558: }
559:
560: /**
561: * Gets the bookmark title.
562: * @return the bookmark title
563: */
564: public Paragraph getBookmarkTitle() {
565: if (bookmarkTitle == null)
566: return getTitle();
567: else
568: return new Paragraph(bookmarkTitle);
569: }
570:
571: /**
572: * Changes the Chapter number.
573: */
574: public void setChapterNumber(int number) {
575: numbers.set(numbers.size() - 1, new Integer(number));
576: Object s;
577: for (Iterator i = iterator(); i.hasNext();) {
578: s = i.next();
579: if (s instanceof Section) {
580: ((Section) s).setChapterNumber(number);
581: }
582: }
583: }
584:
585: /**
586: * Returns the depth of this section.
587: *
588: * @return the depth
589: */
590: public int getDepth() {
591: return numbers.size();
592: }
593:
594: // private methods
595:
596: /**
597: * Sets the number of this section.
598: *
599: * @param number the number of this section
600: * @param numbers an <CODE>ArrayList</CODE>, containing the numbers of the Parent
601: */
602: private void setNumbers(int number, ArrayList numbers) {
603: this .numbers = new ArrayList();
604: this .numbers.add(new Integer(number));
605: this .numbers.addAll(numbers);
606: }
607:
608: // deprecated stuff
609:
610: /**
611: * Returns the title, preceeded by a certain number of sectionnumbers.
612: *
613: * @return a <CODE>Paragraph</CODE>
614: * @deprecated Use {@link #getTitle()} instead
615: */
616: public Paragraph title() {
617: return getTitle();
618: }
619:
620: /**
621: * Returns the numberdepth of this <CODE>Section</CODE>.
622: *
623: * @return the numberdepth
624: * @deprecated Use {@link #getNumberDepth()} instead
625: */
626: public int numberDepth() {
627: return getNumberDepth();
628: }
629:
630: /**
631: * Returns the indentation of this <CODE>Section</CODE> on the left side.
632: *
633: * @return the indentation
634: * @deprecated Use {@link #getIndentationLeft()} instead
635: */
636: public float indentationLeft() {
637: return getIndentationLeft();
638: }
639:
640: /**
641: * Returns the indentation of this <CODE>Section</CODE> on the right side.
642: *
643: * @return the indentation
644: * @deprecated Use {@link #getIndentationRight()} instead
645: */
646: public float indentationRight() {
647: return getIndentationRight();
648: }
649:
650: /**
651: * Returns the indentation of the content of this <CODE>Section</CODE>.
652: *
653: * @return the indentation
654: * @deprecated Use {@link #getIndentation()} instead
655: */
656: public float indentation() {
657: return getIndentation();
658: }
659:
660: /**
661: * Returns the depth of this section.
662: *
663: * @return the depth
664: * @deprecated Use {@link #getDepth()} instead
665: */
666: public int depth() {
667: return getDepth();
668: }
669:
670: /**
671: * Creates a given <CODE>Section</CODE> following a set of attributes and adds it to this one.
672: *
673: * @param attributes the attributes
674: * @return a Section
675: * @deprecated Use ElementFactory.getSection(this, attributes)
676: */
677: public Section addSection(java.util.Properties attributes) {
678: return com.lowagie.text.factories.ElementFactory.getSection(
679: this, attributes);
680: }
681: }
|