001/*
002 * $Id: Paragraph.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 com.itextpdf.text.api.Indentable;
047import com.itextpdf.text.api.Spaceable;
048
049/**
050 * A <CODE>Paragraph</CODE> is a series of <CODE>Chunk</CODE>s and/or <CODE>Phrases</CODE>.
051 * <P>
052 * A <CODE>Paragraph</CODE> has the same qualities of a <CODE>Phrase</CODE>, but also
053 * some additional layout-parameters:
054 * <UL>
055 * <LI>the indentation
056 * <LI>the alignment of the text
057 * </UL>
058 *
059 * Example:
060 * <BLOCKQUOTE><PRE>
061 * <STRONG>Paragraph p = new Paragraph("This is a paragraph",
062 *               FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));</STRONG>
063 * </PRE></BLOCKQUOTE>
064 *
065 * @see         Element
066 * @see         Phrase
067 * @see         ListItem
068 */
069
070public class Paragraph extends Phrase implements Indentable, Spaceable {
071
072        // constants
073        private static final long serialVersionUID = 7852314969733375514L;
074
075    // membervariables
076
077        /** The alignment of the text. */
078    protected int alignment = Element.ALIGN_UNDEFINED;
079
080    /** The text leading that is multiplied by the biggest font size in the line. */
081    protected float multipliedLeading = 0;
082
083    /** The indentation of this paragraph on the left side. */
084    protected float indentationLeft;
085
086    /** The indentation of this paragraph on the right side. */
087    protected float indentationRight;
088
089    /** Holds value of property firstLineIndent. */
090    private float firstLineIndent = 0;
091
092    /** The spacing before the paragraph. */
093    protected float spacingBefore;
094
095    /** The spacing after the paragraph. */
096    protected float spacingAfter;
097
098    /** Holds value of property extraParagraphSpace. */
099    private float extraParagraphSpace = 0;
100
101    /** Does the paragraph has to be kept together on 1 page. */
102    protected boolean keeptogether = false;
103
104    // constructors
105
106    /**
107     * Constructs a <CODE>Paragraph</CODE>.
108     */
109    public Paragraph() {
110        super();
111    }
112
113    /**
114     * Constructs a <CODE>Paragraph</CODE> with a certain leading.
115     *
116     * @param   leading         the leading
117     */
118    public Paragraph(float leading) {
119        super(leading);
120    }
121
122    /**
123     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Chunk</CODE>.
124     *
125     * @param   chunk           a <CODE>Chunk</CODE>
126     */
127    public Paragraph(Chunk chunk) {
128        super(chunk);
129    }
130
131    /**
132     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Chunk</CODE>
133     * and a certain leading.
134     *
135     * @param   leading         the leading
136     * @param   chunk           a <CODE>Chunk</CODE>
137     */
138    public Paragraph(float leading, Chunk chunk) {
139        super(leading, chunk);
140    }
141
142    /**
143     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>.
144     *
145     * @param   string          a <CODE>String</CODE>
146     */
147    public Paragraph(String string) {
148        super(string);
149    }
150
151    /**
152     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>
153     * and a certain <CODE>Font</CODE>.
154     *
155     * @param   string          a <CODE>String</CODE>
156     * @param   font            a <CODE>Font</CODE>
157     */
158    public Paragraph(String string, Font font) {
159        super(string, font);
160    }
161
162    /**
163     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>String</CODE>
164     * and a certain leading.
165     *
166     * @param   leading         the leading
167     * @param   string          a <CODE>String</CODE>
168     */
169    public Paragraph(float leading, String string) {
170        super(leading, string);
171    }
172
173    /**
174     * Constructs a <CODE>Paragraph</CODE> with a certain leading, <CODE>String</CODE>
175     * and <CODE>Font</CODE>.
176     *
177     * @param   leading         the leading
178     * @param   string          a <CODE>String</CODE>
179     * @param   font            a <CODE>Font</CODE>
180     */
181    public Paragraph(float leading, String string, Font font) {
182        super(leading, string, font);
183    }
184
185    /**
186     * Constructs a <CODE>Paragraph</CODE> with a certain <CODE>Phrase</CODE>.
187     *
188     * @param   phrase          a <CODE>Phrase</CODE>
189     */
190    public Paragraph(Phrase phrase) {
191        super(phrase);
192        if (phrase instanceof Paragraph) {
193                Paragraph p = (Paragraph)phrase;
194                setAlignment(p.alignment);
195                setLeading(phrase.getLeading(), p.multipliedLeading);
196                setIndentationLeft(p.getIndentationLeft());
197                setIndentationRight(p.getIndentationRight());
198                setFirstLineIndent(p.getFirstLineIndent());
199                setSpacingAfter(p.getSpacingAfter());
200                setSpacingBefore(p.getSpacingBefore());
201                setExtraParagraphSpace(p.getExtraParagraphSpace());
202        }
203    }
204
205    // implementation of the Element-methods
206
207    /**
208     * Gets the type of the text element.
209     *
210     * @return  a type
211     */
212    @Override
213    public int type() {
214        return Element.PARAGRAPH;
215    }
216
217    // methods
218
219    /**
220     * Adds an <CODE>Element</CODE> to the <CODE>Paragraph</CODE>.
221     *
222     * @param   o the element to add.
223     * @return true is adding the object succeeded
224     */
225    @Override
226    public boolean add(Element o) {
227        if (o instanceof List) {
228            List list = (List) o;
229            list.setIndentationLeft(list.getIndentationLeft() + indentationLeft);
230            list.setIndentationRight(indentationRight);
231            return super.add(list);
232        }
233        else if (o instanceof Image) {
234            super.addSpecial(o);
235            return true;
236        }
237        else if (o instanceof Paragraph) {
238            super.add(o);
239            java.util.List<Chunk> chunks = getChunks();
240            if (!chunks.isEmpty()) {
241                Chunk tmp = chunks.get(chunks.size() - 1);
242                super.add(new Chunk("\n", tmp.getFont()));
243            }
244            else {
245                super.add(Chunk.NEWLINE);
246            }
247            return true;
248        }
249        return super.add(o);
250    }
251
252    // setting the membervariables
253
254    /**
255     * Sets the alignment of this paragraph.
256     *
257     * @param   alignment               the new alignment
258     */
259    public void setAlignment(int alignment) {
260        this.alignment = alignment;
261    }
262
263    /**
264     * @see com.itextpdf.text.Phrase#setLeading(float)
265     */
266    @Override
267    public void setLeading(float fixedLeading) {
268        this.leading = fixedLeading;
269        this.multipliedLeading = 0;
270    }
271
272    /**
273     * Sets the variable leading. The resultant leading will be
274     * multipliedLeading*maxFontSize where maxFontSize is the
275     * size of the biggest font in the line.
276     * @param multipliedLeading the variable leading
277     */
278    public void setMultipliedLeading(float multipliedLeading) {
279        this.leading = 0;
280        this.multipliedLeading = multipliedLeading;
281    }
282
283    /**
284     * Sets the leading fixed and variable. The resultant leading will be
285     * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
286     * size of the biggest font in the line.
287     * @param fixedLeading the fixed leading
288     * @param multipliedLeading the variable leading
289     */
290    public void setLeading(float fixedLeading, float multipliedLeading) {
291        this.leading = fixedLeading;
292        this.multipliedLeading = multipliedLeading;
293    }
294
295    /* (non-Javadoc)
296         * @see com.itextpdf.text.Indentable#setIndentationLeft(float)
297         */
298    public void setIndentationLeft(float indentation) {
299        this.indentationLeft = indentation;
300    }
301
302    /* (non-Javadoc)
303         * @see com.itextpdf.text.Indentable#setIndentationRight(float)
304         */
305    public void setIndentationRight(float indentation) {
306        this.indentationRight = indentation;
307    }
308
309    /**
310     * Setter for property firstLineIndent.
311     * @param firstLineIndent New value of property firstLineIndent.
312     */
313    public void setFirstLineIndent(float firstLineIndent) {
314        this.firstLineIndent = firstLineIndent;
315    }
316
317    /* (non-Javadoc)
318         * @see com.itextpdf.text.Spaceable#setSpacingBefore(float)
319         */
320    public void setSpacingBefore(float spacing) {
321        this.spacingBefore = spacing;
322    }
323
324    /* (non-Javadoc)
325         * @see com.itextpdf.text.Spaceable#setSpacingAfter(float)
326         */
327    public void setSpacingAfter(float spacing) {
328        this.spacingAfter = spacing;
329    }
330
331    /**
332     * Indicates that the paragraph has to be kept together on one page.
333     *
334     * @param   keeptogether    true of the paragraph may not be split over 2 pages
335     */
336    public void setKeepTogether(boolean keeptogether) {
337        this.keeptogether = keeptogether;
338    }
339
340    /**
341     * Checks if this paragraph has to be kept together on one page.
342     *
343     * @return  true if the paragraph may not be split over 2 pages.
344     */
345    public boolean getKeepTogether() {
346        return keeptogether;
347    }
348
349    // methods to retrieve information
350
351        /**
352     * Gets the alignment of this paragraph.
353     *
354     * @return  alignment
355     */
356    public int getAlignment() {
357        return alignment;
358    }
359
360    /**
361     * Gets the variable leading
362     * @return the leading
363     */
364    public float getMultipliedLeading() {
365        return multipliedLeading;
366    }
367
368    /**
369     * Gets the total leading.
370     * This method is based on the assumption that the
371     * font of the Paragraph is the font of all the elements
372     * that make part of the paragraph. This isn't necessarily
373     * true.
374     * @return the total leading (fixed and multiplied)
375     */
376    public float getTotalLeading() {
377        float m = font == null ?
378                        Font.DEFAULTSIZE * multipliedLeading : font.getCalculatedLeading(multipliedLeading);
379        if (m > 0 && !hasLeading()) {
380                return m;
381        }
382        return getLeading() + m;
383    }
384
385        /* (non-Javadoc)
386         * @see com.itextpdf.text.Indentable#getIndentationLeft()
387         */
388    public float getIndentationLeft() {
389        return indentationLeft;
390    }
391
392        /* (non-Javadoc)
393         * @see com.itextpdf.text.Indentable#getIndentationRight()
394         */
395    public float getIndentationRight() {
396        return indentationRight;
397    }
398
399    /**
400     * Getter for property firstLineIndent.
401     * @return Value of property firstLineIndent.
402     */
403    public float getFirstLineIndent() {
404        return this.firstLineIndent;
405    }
406
407    /* (non-Javadoc)
408         * @see com.itextpdf.text.Spaceable#getSpacingBefore()
409         */
410    public float getSpacingBefore() {
411        return spacingBefore;
412    }
413
414    /* (non-Javadoc)
415         * @see com.itextpdf.text.Spaceable#getSpacingAfter()
416         */
417    public float getSpacingAfter() {
418        return spacingAfter;
419    }
420
421    /**
422     * Getter for property extraParagraphSpace.
423     * @return Value of property extraParagraphSpace.
424     */
425    public float getExtraParagraphSpace() {
426        return this.extraParagraphSpace;
427    }
428
429    /**
430     * Setter for property extraParagraphSpace.
431     * @param extraParagraphSpace New value of property extraParagraphSpace.
432     */
433    public void setExtraParagraphSpace(float extraParagraphSpace) {
434        this.extraParagraphSpace = extraParagraphSpace;
435    }
436
437    // scheduled for removal
438
439    /**
440     * Gets the spacing before this paragraph.
441     *
442     * @return  the spacing
443     * @deprecated As of iText 2.1.5, replaced by {@link #getSpacingBefore()},
444     * scheduled for removal at 2.3.0
445     */
446    @Deprecated
447    public float spacingBefore() {
448        return getSpacingBefore();
449    }
450
451    /**
452     * Gets the spacing after this paragraph.
453     *
454     * @return  the spacing
455     * @deprecated As of iText 2.1.5, replaced by {@link #getSpacingAfter()},
456     * scheduled for removal at 2.3.0
457     */
458    @Deprecated
459    public float spacingAfter() {
460        return spacingAfter;
461    }
462
463}