001/*
002 * $Id: Section.java 4862 2011-05-11 15:57:42Z redlab_b $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text;
045
046import java.util.ArrayList;
047import java.util.Collection;
048import java.util.Iterator;
049import java.util.List;
050
051import com.itextpdf.text.api.Indentable;
052import com.itextpdf.text.error_messages.MessageLocalization;
053
054/**
055 * A <CODE>Section</CODE> is a part of a <CODE>Document</CODE> containing
056 * other <CODE>Section</CODE>s, <CODE>Paragraph</CODE>s, <CODE>List</CODE>
057 * and/or <CODE>Table</CODE>s.
058 * <P>
059 * Remark: you can not construct a <CODE>Section</CODE> yourself.
060 * You will have to ask an instance of <CODE>Section</CODE> to the
061 * <CODE>Chapter</CODE> or <CODE>Section</CODE> to which you want to
062 * add the new <CODE>Section</CODE>.
063 * <P>
064 * Example:
065 * <BLOCKQUOTE><PRE>
066 * Paragraph title2 = new Paragraph("This is Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
067 * Chapter chapter2 = new Chapter(title2, 2);
068 * Paragraph someText = new Paragraph("This is some text");
069 * chapter2.add(someText);
070 * Paragraph title21 = new Paragraph("This is Section 1 in Chapter 2", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
071 * <STRONG>Section section1 = chapter2.addSection(title21);</STRONG>
072 * 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.");
073 * <STRONG>section1.add(someSectionText);</STRONG>
074 * 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)));
075 * <STRONG>Section section11 = section1.addSection(40, title211, 2);</STRONG>
076 * <STRONG>section11.add(someSectionText);</STRONG>
077 * </PRE></BLOCKQUOTE>
078 */
079
080public class Section extends ArrayList<Element> implements TextElementArray, LargeElement, Indentable {
081    // constant
082        /**
083         * A possible number style. The default number style: "1.2.3."
084         * @since       iText 2.0.8
085         */
086        public static final int NUMBERSTYLE_DOTTED = 0;
087        /**
088         * A possible number style. For instance: "1.2.3"
089         * @since       iText 2.0.8
090         */
091        public static final int NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT = 1;
092
093        /** A serial version uid. */
094        private static final long serialVersionUID = 3324172577544748043L;
095
096        // member variables
097
098        /** The title of this section. */
099    protected Paragraph title;
100
101    /** The bookmark title if different from the content title */
102    protected String bookmarkTitle;
103
104    /** The number of sectionnumbers that has to be shown before the section title. */
105    protected int numberDepth;
106
107    /**
108     * The style for sectionnumbers.
109     * @since   iText 2.0.8
110     */
111    protected int numberStyle = NUMBERSTYLE_DOTTED;
112
113    /** The indentation of this section on the left side. */
114    protected float indentationLeft;
115
116    /** The indentation of this section on the right side. */
117    protected float indentationRight;
118
119    /** The additional indentation of the content of this section. */
120    protected float indentation;
121
122    /** false if the bookmark children are not visible */
123    protected boolean bookmarkOpen = true;
124
125    /** true if the section has to trigger a new page */
126    protected boolean triggerNewPage = false;
127
128    /** This is the number of subsections. */
129    protected int subsections = 0;
130
131    /** This is the complete list of sectionnumbers of this section and the parents of this section. */
132    protected ArrayList<Integer> numbers = null;
133
134    /**
135     * Indicates if the Section will be complete once added to the document.
136     * @since   iText 2.0.8
137     */
138    protected boolean complete = true;
139
140    /**
141     * Indicates if the Section was added completely to the document.
142     * @since   iText 2.0.8
143     */
144    protected boolean addedCompletely = false;
145
146    /**
147     * Indicates if this is the first time the section was added.
148     * @since   iText 2.0.8
149     */
150    protected boolean notAddedYet = true;
151
152    // constructors
153
154    /**
155     * Constructs a new <CODE>Section</CODE>.
156     */
157    protected Section() {
158        title = new Paragraph();
159        numberDepth = 1;
160    }
161
162    /**
163     * Constructs a new <CODE>Section</CODE>.
164     *
165     * @param   title                   a <CODE>Paragraph</CODE>
166     * @param   numberDepth             the numberDepth
167     */
168    protected Section(final Paragraph title, final int numberDepth) {
169        this.numberDepth = numberDepth;
170        this.title = title;
171    }
172
173    // implementation of the Element-methods
174
175    /**
176     * Processes the element by adding it (or the different parts) to an
177     * <CODE>ElementListener</CODE>.
178     *
179     * @param   listener                the <CODE>ElementListener</CODE>
180     * @return  <CODE>true</CODE> if the element was processed successfully
181     */
182    public boolean process(final ElementListener listener) {
183        try {
184                Element element;
185            for (Object element2 : this) {
186                element = (Element)element2;
187                listener.add(element);
188            }
189            return true;
190        }
191        catch(DocumentException de) {
192            return false;
193        }
194    }
195
196    /**
197     * Gets the type of the text element.
198     *
199     * @return  a type
200     */
201    public int type() {
202        return Element.SECTION;
203    }
204
205    /**
206     * Checks if this object is a <CODE>Chapter</CODE>.
207     *
208     * @return  <CODE>true</CODE> if it is a <CODE>Chapter</CODE>,
209     *                  <CODE>false</CODE> if it is a <CODE>Section</CODE>.
210     */
211    public boolean isChapter() {
212        return type() == Element.CHAPTER;
213    }
214
215    /**
216     * Checks if this object is a <CODE>Section</CODE>.
217     *
218     * @return  <CODE>true</CODE> if it is a <CODE>Section</CODE>,
219     *                  <CODE>false</CODE> if it is a <CODE>Chapter</CODE>.
220     */
221    public boolean isSection() {
222        return type() == Element.SECTION;
223    }
224
225    /**
226     * Gets all the chunks in this element.
227     *
228     * @return  an <CODE>ArrayList</CODE>
229     */
230    public List<Chunk> getChunks() {
231        List<Chunk> tmp = new ArrayList<Chunk>();
232        for (Object element : this) {
233            tmp.addAll(((Element) element).getChunks());
234        }
235        return tmp;
236    }
237
238        /**
239         * @see com.itextpdf.text.Element#isContent()
240         * @since       iText 2.0.8
241         */
242        public boolean isContent() {
243                return true;
244        }
245
246        /**
247         * @see com.itextpdf.text.Element#isNestable()
248         * @since       iText 2.0.8
249         */
250        public boolean isNestable() {
251                return false;
252        }
253
254    // overriding some of the ArrayList-methods
255
256    /**
257     * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
258     * to this <CODE>Section</CODE>.
259     *
260     * @param   index   index at which the specified element is to be inserted
261     * @param   element         an element of type <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>=
262     * @throws  ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE> or <CODE>Table</CODE>
263     * @since 5.0.1 (signature changed to use Element)
264     */
265    @Override
266    public void add(final int index, final Element element) {
267        if (isAddedCompletely()) {
268                throw new IllegalStateException(MessageLocalization.getComposedMessage("this.largeelement.has.already.been.added.to.the.document"));
269        }
270        try {
271            if (element.isNestable()) {
272                super.add(index, element);
273            }
274            else {
275                throw new ClassCastException(MessageLocalization.getComposedMessage("you.can.t.add.a.1.to.a.section", element.getClass().getName()));
276            }
277        }
278        catch(ClassCastException cce) {
279            throw new ClassCastException(MessageLocalization.getComposedMessage("insertion.of.illegal.element.1", cce.getMessage()));
280        }
281    }
282
283    /**
284     * Adds a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
285     * to this <CODE>Section</CODE>.
286     *
287     * @param   element   an element of type <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or another <CODE>Section</CODE>
288     * @return  a boolean
289     * @throws  ClassCastException if the object is not a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE> or <CODE>Section</CODE>
290     * @since 5.0.1 (signature changed to use Element)
291     */
292    @Override
293    public boolean add(final Element element) {
294        if (isAddedCompletely()) {
295                throw new IllegalStateException(MessageLocalization.getComposedMessage("this.largeelement.has.already.been.added.to.the.document"));
296        }
297        try {
298            if (element.type() == Element.SECTION) {
299                Section section = (Section) element;
300                section.setNumbers(++subsections, numbers);
301                return super.add(section);
302            }
303            else if (element instanceof MarkedSection && ((MarkedObject)element).element.type() == Element.SECTION) {
304                MarkedSection mo = (MarkedSection)element;
305                Section section = (Section)mo.element;
306                section.setNumbers(++subsections, numbers);
307                return super.add(mo);
308            }
309            else if (element.isNestable()) {
310                return super.add(element);
311            }
312            else {
313                throw new ClassCastException(MessageLocalization.getComposedMessage("you.can.t.add.a.1.to.a.section", element.getClass().getName()));
314            }
315        }
316        catch(ClassCastException cce) {
317            throw new ClassCastException(MessageLocalization.getComposedMessage("insertion.of.illegal.element.1", cce.getMessage()));
318        }
319    }
320
321    /**
322     * Adds a collection of <CODE>Element</CODE>s
323     * to this <CODE>Section</CODE>.
324     *
325     * @param   collection      a collection of <CODE>Paragraph</CODE>s, <CODE>List</CODE>s and/or <CODE>Table</CODE>s
326     * @return  <CODE>true</CODE> if the action succeeded, <CODE>false</CODE> if not.
327     * @throws  ClassCastException if one of the objects isn't a <CODE>Paragraph</CODE>, <CODE>List</CODE>, <CODE>Table</CODE>
328     */
329    @Override
330    public boolean addAll(final Collection<? extends Element> collection) {
331        for (Element element : collection) {
332            this.add(element);
333        }
334        return true;
335    }
336
337    // methods that return a Section
338
339    /**
340     * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
341     *
342     * @param   indentation     the indentation of the new section
343     * @param   title           the title of the new section
344     * @param   numberDepth     the numberDepth of the section
345     * @return  a new Section object
346     */
347    public Section addSection(final float indentation, final Paragraph title, final int numberDepth) {
348        if (isAddedCompletely()) {
349                throw new IllegalStateException(MessageLocalization.getComposedMessage("this.largeelement.has.already.been.added.to.the.document"));
350        }
351        Section section = new Section(title, numberDepth);
352        section.setIndentation(indentation);
353        add(section);
354        return section;
355    }
356
357    /**
358     * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
359     *
360     * @param   indentation     the indentation of the new section
361     * @param   title           the title of the new section
362     * @return  a new Section object
363     */
364    public Section addSection(final float indentation, final Paragraph title) {
365        return addSection(indentation, title, numberDepth + 1);
366    }
367
368    /**
369     * Creates a <CODE>Section</CODE>, add it to this <CODE>Section</CODE> and returns it.
370     *
371     * @param   title           the title of the new section
372     * @param   numberDepth     the numberDepth of the section
373     * @return  a new Section object
374     */
375    public Section addSection(final Paragraph title, final int numberDepth) {
376        return addSection(0, title, numberDepth);
377    }
378
379    /**
380     * Adds a marked section. For use in class MarkedSection only!
381     * @return the MarkedSection
382     */
383    protected MarkedSection addMarkedSection() {
384        MarkedSection section = new MarkedSection(new Section(null, numberDepth + 1));
385        add(section);
386        return section;
387    }
388
389    /**
390     * Creates a <CODE>Section</CODE>, adds it to this <CODE>Section</CODE> and returns it.
391     *
392     * @param   title           the title of the new section
393     * @return  a new Section object
394     */
395    public Section addSection(final Paragraph title) {
396        return addSection(0, title, numberDepth + 1);
397    }
398
399    /**
400     * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
401     *
402     * @param   indentation     the indentation of the new section
403     * @param   title           the title of the new section
404     * @param   numberDepth     the numberDepth of the section
405     * @return  a new Section object
406     */
407    public Section addSection(final float indentation, final String title, final int numberDepth) {
408        return addSection(indentation, new Paragraph(title), numberDepth);
409    }
410
411    /**
412     * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
413     *
414     * @param   title           the title of the new section
415     * @param   numberDepth     the numberDepth of the section
416     * @return  a new Section object
417     */
418    public Section addSection(final String title, final int numberDepth) {
419        return addSection(new Paragraph(title), numberDepth);
420    }
421
422    /**
423     * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
424     *
425     * @param   indentation     the indentation of the new section
426     * @param   title           the title of the new section
427     * @return  a new Section object
428     */
429    public Section addSection(final float indentation, final String title) {
430        return addSection(indentation, new Paragraph(title));
431    }
432
433    /**
434     * Adds a <CODE>Section</CODE> to this <CODE>Section</CODE> and returns it.
435     *
436     * @param   title           the title of the new section
437     * @return  a new Section object
438     */
439    public Section addSection(final String title) {
440        return addSection(new Paragraph(title));
441    }
442
443    // public methods
444
445    /**
446     * Sets the title of this section.
447     *
448     * @param   title   the new title
449     */
450    public void setTitle(final Paragraph title) {
451        this.title = title;
452    }
453
454        /**
455     * Returns the title, preceded by a certain number of sectionnumbers.
456     *
457     * @return  a <CODE>Paragraph</CODE>
458     */
459    public Paragraph getTitle() {
460        return constructTitle(title, numbers, numberDepth, numberStyle);
461    }
462
463    /**
464     * Constructs a Paragraph that will be used as title for a Section or Chapter.
465     * @param   title   the title of the section
466     * @param   numbers a list of sectionnumbers
467     * @param   numberDepth     how many numbers have to be shown
468     * @param   numberStyle     the numbering style
469     * @return  a Paragraph object
470         * @since       iText 2.0.8
471     */
472    public static Paragraph constructTitle(final Paragraph title, final ArrayList<Integer> numbers, final int numberDepth, final int numberStyle) {
473        if (title == null) {
474                return null;
475        }
476
477        int depth = Math.min(numbers.size(), numberDepth);
478        if (depth < 1) {
479            return title;
480        }
481        StringBuffer buf = new StringBuffer(" ");
482        for (int i = 0; i < depth; i++) {
483            buf.insert(0, ".");
484            buf.insert(0, numbers.get(i).intValue());
485        }
486        if (numberStyle == NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT) {
487                buf.deleteCharAt(buf.length() - 2);
488        }
489        Paragraph result = new Paragraph(title);
490        result.add(0, new Chunk(buf.toString(), title.getFont()));
491        return result;
492    }
493
494    /**
495     * Sets the depth of the sectionnumbers that will be shown preceding the title.
496     * <P>
497     * If the numberdepth is 0, the sections will not be numbered. If the numberdepth
498     * is 1, the section will be numbered with their own number. If the numberdepth is
499     * higher (for instance x > 1), the numbers of x - 1 parents will be shown.
500     *
501     * @param   numberDepth             the new numberDepth
502     */
503    public void setNumberDepth(final int numberDepth) {
504        this.numberDepth = numberDepth;
505    }
506
507        /**
508     * Returns the numberdepth of this <CODE>Section</CODE>.
509     *
510     * @return  the numberdepth
511     */
512    public int getNumberDepth() {
513        return numberDepth;
514    }
515
516    /**
517     * Sets the style for numbering sections.
518     * Possible values are {@link Section#NUMBERSTYLE_DOTTED}: 1.2.3. (the default)
519     * or {@link Section#NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT}: 1.2.3
520     * @param numberStyle the style to use
521         * @since       iText 2.0.8
522     */
523        public void setNumberStyle(final int numberStyle) {
524                this.numberStyle = numberStyle;
525        }
526
527        /**
528         * Gets the style used for numbering sections.
529         * @since       iText 2.0.8
530         * @return      a value corresponding with a numbering style
531         */
532        public int getNumberStyle() {
533                return numberStyle;
534        }
535
536    /**
537     * Sets the indentation of this <CODE>Section</CODE> on the left side.
538     *
539     * @param   indentation             the indentation
540     */
541    public void setIndentationLeft(final float indentation) {
542        indentationLeft = indentation;
543    }
544
545        /**
546     * Returns the indentation of this <CODE>Section</CODE> on the left side.
547     *
548     * @return  the indentation
549     */
550    public float getIndentationLeft() {
551        return indentationLeft;
552    }
553
554    /**
555     * Sets the indentation of this <CODE>Section</CODE> on the right side.
556     *
557     * @param   indentation             the indentation
558     */
559    public void setIndentationRight(final float indentation) {
560        indentationRight = indentation;
561    }
562
563        /**
564     * Returns the indentation of this <CODE>Section</CODE> on the right side.
565     *
566     * @return  the indentation
567     */
568    public float getIndentationRight() {
569        return indentationRight;
570    }
571
572    /**
573     * Sets the indentation of the content of this <CODE>Section</CODE>.
574     *
575     * @param   indentation             the indentation
576     */
577    public void setIndentation(final float indentation) {
578        this.indentation = indentation;
579    }
580
581        /**
582     * Returns the indentation of the content of this <CODE>Section</CODE>.
583     *
584     * @return  the indentation
585     */
586    public float getIndentation() {
587        return indentation;
588    }
589
590    /** Setter for property bookmarkOpen.
591     * @param bookmarkOpen false if the bookmark children are not
592     * visible.
593     */
594    public void setBookmarkOpen(final boolean bookmarkOpen) {
595        this.bookmarkOpen = bookmarkOpen;
596    }
597
598    /**
599     * Getter for property bookmarkOpen.
600     * @return Value of property bookmarkOpen.
601     */
602    public boolean isBookmarkOpen() {
603        return bookmarkOpen;
604    }
605
606    /**
607     * Setter for property triggerNewPage.
608     * @param triggerNewPage true if a new page has to be triggered.
609     */
610        public void setTriggerNewPage(final boolean triggerNewPage) {
611                this.triggerNewPage = triggerNewPage;
612        }
613
614    /**
615     * Getter for property bookmarkOpen.
616     * @return Value of property triggerNewPage.
617     */
618    public boolean isTriggerNewPage() {
619                return triggerNewPage && notAddedYet;
620        }
621
622    /**
623     * Sets the bookmark title. The bookmark title is the same as the section title but
624     * can be changed with this method.
625     * @param bookmarkTitle the bookmark title
626     */
627    public void setBookmarkTitle(final String bookmarkTitle) {
628        this.bookmarkTitle = bookmarkTitle;
629    }
630
631        /**
632     * Gets the bookmark title.
633     * @return the bookmark title
634     */
635    public Paragraph getBookmarkTitle() {
636        if (bookmarkTitle == null)
637            return getTitle();
638        else
639            return new Paragraph(bookmarkTitle);
640    }
641
642    /**
643     * Changes the Chapter number.
644     * @param number the new number
645     */
646    public void setChapterNumber(final int number) {
647        numbers.set(numbers.size() - 1, Integer.valueOf(number));
648        Object s;
649        for (Iterator<Element> i = iterator(); i.hasNext(); ) {
650                s = i.next();
651                if (s instanceof Section) {
652                        ((Section)s).setChapterNumber(number);
653                }
654        }
655    }
656
657        /**
658     * Returns the depth of this section.
659     *
660     * @return  the depth
661     */
662    public int getDepth() {
663        return numbers.size();
664    }
665
666    // private methods
667
668    /**
669     * Sets the number of this section.
670     *
671     * @param   number          the number of this section
672     * @param   numbers         an <CODE>ArrayList<Integer></CODE>, containing the numbers of the Parent
673     */
674    private void setNumbers(final int number, final ArrayList<Integer> numbers) {
675        this.numbers = new ArrayList<Integer>();
676        this.numbers.add(Integer.valueOf(number));
677        this.numbers.addAll(numbers);
678    }
679
680        /**
681         * Indicates if this is the first time the section is added.
682         * @since       iText2.0.8
683         * @return      true if the section wasn't added yet
684         */
685        public boolean isNotAddedYet() {
686                return notAddedYet;
687        }
688
689        /**
690         * Sets the indication if the section was already added to
691         * the document.
692         * @since       iText2.0.8
693         * @param notAddedYet
694         */
695        public void setNotAddedYet(final boolean notAddedYet) {
696                this.notAddedYet = notAddedYet;
697        }
698
699    /**
700     * @return return the addedCompletely value
701     * @since   iText 2.0.8
702     */
703    protected boolean isAddedCompletely() {
704                return addedCompletely;
705        }
706
707        /**
708     * @param addedCompletely true if section was completely added, false otherwise
709         * @since       iText 2.0.8
710         */
711        protected void setAddedCompletely(final boolean addedCompletely) {
712                this.addedCompletely = addedCompletely;
713        }
714
715        /**
716         * @since       iText 2.0.8
717         * @see com.itextpdf.text.LargeElement#flushContent()
718         */
719        public void flushContent() {
720                setNotAddedYet(false);
721                title = null;
722                Element element;
723                for (Iterator<Element> i = iterator(); i.hasNext(); ) {
724                        element = i.next();
725                        if (element instanceof Section) {
726                                Section s = (Section)element;
727                                if (!s.isComplete() && size() == 1) {
728                                        s.flushContent();
729                                        return;
730                                }
731                                else {
732                                        s.setAddedCompletely(true);
733                                }
734                        }
735                        i.remove();
736                }
737        }
738
739        /**
740     * @since   iText 2.0.8
741         * @see com.itextpdf.text.LargeElement#isComplete()
742         */
743        public boolean isComplete() {
744                return complete;
745        }
746
747        /**
748     * @since   iText 2.0.8
749         * @see com.itextpdf.text.LargeElement#setComplete(boolean)
750         */
751        public void setComplete(final boolean complete) {
752                this.complete = complete;
753        }
754
755        /**
756         * Adds a new page to the section.
757         * @since       2.1.1
758         */
759        public void newPage() {
760                this.add(Chunk.NEXTPAGE);
761        }
762}