1 /*
2  * $Id: PdfOutline.java 3373 2008-05-12 16:21:24Z xlv $
3  *
4  * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above.  If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49
50 package com.lowagie.text.pdf;
51
52 import java.awt.Color;
53 import java.io.IOException;
54 import java.io.OutputStream;
55 import java.util.ArrayList;
56 import java.util.Iterator;
57
58 import com.lowagie.text.Chunk;
59 import com.lowagie.text.Font;
60 import com.lowagie.text.Paragraph;
61
62 /**
63  * <CODE>PdfOutline</CODE> is an object that represents a PDF outline entry.
64  * <P>
65  * An outline allows a user to access views of a document by name.<BR>
66  * This object is described in the 'Portable Document Format Reference Manual version 1.3'
67  * section 6.7 (page 104-106)
68  *
69  * @see        PdfDictionary
70  */

71
72 public class PdfOutline extends PdfDictionary {
73     
74     // membervariables
75     
76     /** the <CODE>PdfIndirectReference</CODE> of this object */
77     private PdfIndirectReference reference;
78     
79     /** value of the <B>Count</B>-key */
80     private int count = 0;
81     
82     /** value of the <B>Parent</B>-key */
83     private PdfOutline parent;
84     
85     /** value of the <B>Destination</B>-key */
86     private PdfDestination destination;
87     
88     /** The <CODE>PdfAction</CODE> for this outline.
89      */

90     private PdfAction action;
91        
92     protected ArrayList kids = new ArrayList();
93     
94     protected PdfWriter writer;
95     
96     /** Holds value of property tag. */
97     private String tag;
98     
99     /** Holds value of property open. */
100     private boolean open;
101     
102     /** Holds value of property color. */
103     private Color color;
104     
105     /** Holds value of property style. */
106     private int style = 0;
107     
108     // constructors
109     
110     /**
111      * Constructs a <CODE>PdfOutline</CODE>.
112      * <P>
113      * This is the constructor for the <CODE>outlines object</CODE>.
114      * 
115      * @param writer The PdfWriter you are adding the outline to
116      */

117     
118     PdfOutline(PdfWriter writer) {
119         super(OUTLINES);
120         open = true;
121         parent = null;
122         this.writer = writer;
123     }
124     
125     /**
126      * Constructs a <CODE>PdfOutline</CODE>.
127      * <P>
128      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
129      * <CODE>true</CODE>.
130      *
131      * @param parent the parent of this outline item
132      * @param action the <CODE>PdfAction</CODE> for this outline item
133      * @param title the title of this outline item
134      */

135     
136     public PdfOutline(PdfOutline parent, PdfAction action, String title) {
137         this(parent, action, title, true);
138     }
139     
140     /**
141      * Constructs a <CODE>PdfOutline</CODE>.
142      * <P>
143      * This is the constructor for an <CODE>outline entry</CODE>.
144      *
145      * @param parent the parent of this outline item
146      * @param action the <CODE>PdfAction</CODE> for this outline item
147      * @param title the title of this outline item
148      * @param open <CODE>true</CODE> if the children are visible
149      */

150     public PdfOutline(PdfOutline parent, PdfAction action, String title, boolean open) {
151         super();
152         this.action = action;
153         initOutline(parent, title, open);
154     }
155     
156     /**
157      * Constructs a <CODE>PdfOutline</CODE>.
158      * <P>
159      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
160      * <CODE>true</CODE>.
161      *
162      * @param parent the parent of this outline item
163      * @param destination the destination for this outline item
164      * @param title the title of this outline item
165      */

166     
167     public PdfOutline(PdfOutline parent, PdfDestination destination, String title) {
168         this(parent, destination, title, true);
169     }
170     
171     /**
172      * Constructs a <CODE>PdfOutline</CODE>.
173      * <P>
174      * This is the constructor for an <CODE>outline entry</CODE>.
175      *
176      * @param parent the parent of this outline item
177      * @param destination the destination for this outline item
178      * @param title the title of this outline item
179      * @param open <CODE>true</CODE> if the children are visible
180      */

181     public PdfOutline(PdfOutline parent, PdfDestination destination, String title, boolean open) {
182         super();
183         this.destination = destination;
184         initOutline(parent, title, open);
185     }
186     
187     /**
188      * Constructs a <CODE>PdfOutline</CODE>.
189      * <P>
190      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
191      * <CODE>true</CODE>.
192      *
193      * @param parent the parent of this outline item
194      * @param action the <CODE>PdfAction</CODE> for this outline item
195      * @param title the title of this outline item
196      */

197     public PdfOutline(PdfOutline parent, PdfAction action, PdfString title) {
198         this(parent, action, title, true);
199     }
200     
201     /**
202      * Constructs a <CODE>PdfOutline</CODE>.
203      * <P>
204      * This is the constructor for an <CODE>outline entry</CODE>.
205      *
206      * @param parent the parent of this outline item
207      * @param action the <CODE>PdfAction</CODE> for this outline item
208      * @param title the title of this outline item
209      * @param open <CODE>true</CODE> if the children are visible
210      */

211     public PdfOutline(PdfOutline parent, PdfAction action, PdfString title, boolean open) {
212         this(parent, action, title.toString(), open);
213     }
214     
215     /**
216      * Constructs a <CODE>PdfOutline</CODE>.
217      * <P>
218      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
219      * <CODE>true</CODE>.
220      *
221      * @param parent the parent of this outline item
222      * @param destination the destination for this outline item
223      * @param title the title of this outline item
224      */

225     
226     public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title) {
227         this(parent, destination, title, true);
228     }
229     
230     /**
231      * Constructs a <CODE>PdfOutline</CODE>.
232      * <P>
233      * This is the constructor for an <CODE>outline entry</CODE>.
234      *
235      * @param parent the parent of this outline item
236      * @param destination the destination for this outline item
237      * @param title the title of this outline item
238      * @param open <CODE>true</CODE> if the children are visible
239      */

240     public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title, boolean open) {
241         this(parent, destination, title.toString(), true);
242     }
243     
244     /**
245      * Constructs a <CODE>PdfOutline</CODE>.
246      * <P>
247      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
248      * <CODE>true</CODE>.
249      *
250      * @param parent the parent of this outline item
251      * @param action the <CODE>PdfAction</CODE> for this outline item
252      * @param title the title of this outline item
253      */

254     
255     public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title) {
256         this(parent, action, title, true);
257     }
258     
259     /**
260      * Constructs a <CODE>PdfOutline</CODE>.
261      * <P>
262      * This is the constructor for an <CODE>outline entry</CODE>.
263      *
264      * @param parent the parent of this outline item
265      * @param action the <CODE>PdfAction</CODE> for this outline item
266      * @param title the title of this outline item
267      * @param open <CODE>true</CODE> if the children are visible
268      */

269     public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title, boolean open) {
270         super();
271         StringBuffer buf = new StringBuffer();
272         for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
273             Chunk chunk = (Chunk) i.next();
274             buf.append(chunk.getContent());
275         }
276         this.action = action;
277         initOutline(parent, buf.toString(), open);
278     }
279     
280     /**
281      * Constructs a <CODE>PdfOutline</CODE>.
282      * <P>
283      * This is the constructor for an <CODE>outline entry</CODE>. The open mode is
284      * <CODE>true</CODE>.
285      *
286      * @param parent the parent of this outline item
287      * @param destination the destination for this outline item
288      * @param title the title of this outline item
289      */

290     
291     public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title) {
292         this(parent, destination, title, true);
293     }
294     
295     /**
296      * Constructs a <CODE>PdfOutline</CODE>.
297      * <P>
298      * This is the constructor for an <CODE>outline entry</CODE>.
299      *
300      * @param parent the parent of this outline item
301      * @param destination the destination for this outline item
302      * @param title the title of this outline item
303      * @param open <CODE>true</CODE> if the children are visible
304      */

305     public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title, boolean open) {
306         super();
307         StringBuffer buf = new StringBuffer();
308         for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
309             Chunk chunk = (Chunk) i.next();
310             buf.append(chunk.getContent());
311         }
312         this.destination = destination;
313         initOutline(parent, buf.toString(), open);
314     }
315     
316     
317     // methods
318     
319     /** Helper for the constructors.
320      * @param parent the parent outline
321      * @param title the title for this outline
322      * @param open <CODE>true</CODE> if the children are visible
323      */

324     void initOutline(PdfOutline parent, String title, boolean open) {
325         this.open = open;
326         this.parent = parent;
327         writer = parent.writer;
328         put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
329         parent.addKid(this);
330         if (destination != null && !destination.hasPage()) // bugfix Finn Bock
331             setDestinationPage(writer.getCurrentPage());
332     }
333     
334     /**
335      * Sets the indirect reference of this <CODE>PdfOutline</CODE>.
336      *
337      * @param reference the <CODE>PdfIndirectReference</CODE> to this outline.
338      */

339     
340     public void setIndirectReference(PdfIndirectReference reference) {
341         this.reference = reference;
342     }
343     
344     /**
345      * Gets the indirect reference of this <CODE>PdfOutline</CODE>.
346      *
347      * @return        the <CODE>PdfIndirectReference</CODE> to this outline.
348      */

349     
350     public PdfIndirectReference indirectReference() {
351         return reference;
352     }
353     
354     /**
355      * Gets the parent of this <CODE>PdfOutline</CODE>.
356      *
357      * @return        the <CODE>PdfOutline</CODE> that is the parent of this outline.
358      */

359     
360     public PdfOutline parent() {
361         return parent;
362     }
363     
364     /**
365      * Set the page of the <CODE>PdfDestination</CODE>-object.
366      *
367      * @param pageReference indirect reference to the page
368      * @return <CODE>true</CODE> if this page was set as the <CODE>PdfDestination</CODE>-page.
369      */

370     
371     public boolean setDestinationPage(PdfIndirectReference pageReference) {
372         if (destination == null) {
373             return false;
374         }
375         return destination.addPage(pageReference);
376     }
377     
378     /**
379      * Gets the destination for this outline.
380      * @return the destination
381      */

382     public PdfDestination getPdfDestination() {
383         return destination;
384     }
385     
386     int getCount() {
387         return count;
388     }
389
390     void setCount(int count) {
391         this.count = count;
392     }
393     
394     /**
395      * returns the level of this outline.
396      *
397      * @return        a level
398      */

399     
400     public int level() {
401         if (parent == null) {
402             return 0;
403         }
404         return (parent.level() + 1);
405     }
406     
407     /**
408      * Returns the PDF representation of this <CODE>PdfOutline</CODE>.
409      *
410      * @param writer the encryption information
411      * @param os
412      * @throws IOException
413      */

414     
415     public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
416         if (color != null && !color.equals(Color.black)) {
417             put(PdfName.C, new PdfArray(new float[]{color.getRed()/255f,color.getGreen()/255f,color.getBlue()/255f}));
418         }
419         int flag = 0;
420         if ((style & Font.BOLD) != 0)
421             flag |= 2;
422         if ((style & Font.ITALIC) != 0)
423             flag |= 1;
424         if (flag != 0)
425             put(PdfName.F, new PdfNumber(flag));
426         if (parent != null) {
427             put(PdfName.PARENT, parent.indirectReference());
428         }
429         if (destination != null && destination.hasPage()) {
430             put(PdfName.DEST, destination);
431         }
432         if (action != null)
433             put(PdfName.A, action);
434         if (count != 0) {
435             put(PdfName.COUNT, new PdfNumber(count));
436         }
437         super.toPdf(writer, os);
438     }
439     
440     /**
441      * Adds a kid to the outline
442      * @param outline
443      */

444     public void addKid(PdfOutline outline) {
445         kids.add(outline);
446     }
447     
448     /**
449      * Returns the kids of this outline
450      * @return an ArrayList with PdfOutlines
451      */

452     public ArrayList getKids() {
453         return kids;
454     }
455     
456     /**
457      * Sets the kids of this outline
458      * @param kids
459      */

460     public void setKids(ArrayList kids) {
461         this.kids = kids;
462     }
463     
464     /** Getter for property tag.
465      * @return Value of property tag.
466      */

467     public String getTag() {
468         return tag;
469     }
470     
471     /** Setter for property tag.
472      * @param tag New value of property tag.
473      */

474     public void setTag(String tag) {
475         this.tag = tag;
476     }
477     
478     /**
479      * Gets the title of this outline
480      * @return the title as a String
481      */

482     public String getTitle() {
483         PdfString title = (PdfString)get(PdfName.TITLE);
484         return title.toString();
485     }
486     
487     /**
488      * Sets the title of this outline
489      * @param title
490      */

491     public void setTitle(String title) {
492         put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
493     }
494     
495     /** Getter for property open.
496      * @return Value of property open.
497      */

498     public boolean isOpen() {
499         return open;
500     }
501     
502     /** Setter for property open.
503      * @param open New value of property open.
504      */

505     public void setOpen(boolean open) {
506         this.open = open;
507     }
508     
509     /** Getter for property color.
510      * @return Value of property color.
511      *
512      */

513     public Color getColor() {
514         return this.color;
515     }
516     
517     /** Setter for property color.
518      * @param color New value of property color.
519      *
520      */

521     public void setColor(Color color) {
522         this.color = color;
523     }
524     
525     /** Getter for property style.
526      * @return Value of property style.
527      *
528      */

529     public int getStyle() {
530         return this.style;
531     }
532     
533     /** Setter for property style.
534      * @param style New value of property style.
535      *
536      */

537     public void setStyle(int style) {
538         this.style = style;
539     }
540     
541 }