# Tutorial: iText by Example

## Page Events

Page Event Methods:
If you generate a PDF file using high-level iText objects, you add structured content to a Document-object. This content is automatically being translated to PDF syntax by the PdfWriter. The hidden (package private) object PdfDocument-object is responsible for drawing the content on different pages. While this happens, the process adding content (your program) is not aware of all this PDF specific work. You can ask the PdfWriter for the current page number with PdfWriter.getPageNumber(), but this is all very limited. If you really want to control what happens inside the writer, you need to add a PdfPageEvent:

    // class MyPageEvent implements the PdfPageEvent interface
    MyPageEvent event = new MyPageEvent();
    writer.setPageEvent(event);

The PdfPageEvent interface contains the following methods you have to implement in your own class MyPageEvent:

- public void onOpenDocument(PdfWriter writer, Document document);
- public void onCloseDocument(PdfWriter writer, Document document);
- public void onStartPage(PdfWriter writer, Document document);
- public void onEndPage(PdfWriter writer, Document document);
- public void onParagraph(PdfWriter writer, Document document, float paragraphPosition);
- public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition);
- public void onChapter(PdfWriter writer,Document document,float paragraphPosition, Paragraph title);
- public void onChapterEnd(PdfWriter writer,Document document,float paragraphPosition);
- public void onSection(PdfWriter writer,Document document,float paragraphPosition, int depth, Paragraph title);
- public void onSectionEnd(PdfWriter writer,Document document,float paragraphPosition);
- public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text);

Of course, you don't always need all these methods, so it's easier not just to implement the PdfPageEvent-interface, but to extend the PdfPageEventHelper. This class contains 'empty' implementations of all the methods mentioned above. You just have to override the methods you need.
Open and close a document, start and end a page
The onOpenDocument method and the first onStartPage method are called just after the document is opened and after the first page has been initialized. onOpenDocument is mostly used to initialize some parameters that you defined yourself in your own page event implemantation. onStartPage is called just after each new page has been initialized. The onEndPage method is called just before a new page is started and initialized. This is the best method to add some headers and footers. I don't recomment to add headers and footers in the onStartPage method, because this can lead to all kinds of quirky effect (for instance an extra, unwanted blank page at the end of your document). The onCloseDocument method is called just before all streams are closed. This is the ideal place to complete the template containing the total number of pages, if you have some footer indicating 'page X of Y'. It is only just before closing the document that you know the exact value of Y. In your implementation of these methods, you always get the instance of the writer that triggered the event a Document-object. THIS IS NOT THE SAME OBJECT as the one you are adding structured content to. This is an instance of the (hidden) PdfDocument-object. You can only invoke a limited number of methods on this object.
Adding paragraphs, chapters, section
When a paragraph is added, you might want to know the current Y position on your page. Below you'll find an example adding bookmarks automatically; each entry in the outline tree points at the starting position of a paragraph. This outline tree is generated in an onParagraph event. If you need to add some object at an absolute place just after a paragraph, just use the onParagraphEnd-method.
The methods onChapter, onSection, onChapterEnd and onSectionEnd do just the same, but the first two also pass the chapter or section title. This can be used to set the content of some header or footer (as in the 'Romeo and Juliet' example below), or to construct a Table-of-Contents.
Generic tags
Generic tags are already discussed elsewhere, for instance when we added generic functionality to a Chunk object. In the 'Romeo and Juliet' example, we are going to use this method to count the number of interventions of each character in the play.
Go to top of the page
Examples:
Headers/Footers
If you want to add a Header and/or a Footer to each page in your document, you have to do this in an onEndPage event.
Example: java com.lowagie.examples.directcontent.pageevents.EndPage
Headers and footers in an EndPage event: see endpage.pdf
Page X of Y
In this example, not only we add a header and a footer. We also use a template in the footer to display 'page X of Y'. The total number of pages is added to the PdfTemplate in the onCloseDocument event. As you can see, watermarks can be added in onStartPage, but you could also do this in onEndPage (where we also draw a Rectangle around the text on each page).
Example: java com.lowagie.examples.directcontent.pageevents.PageNumbersWatermark
Making a document with a header containing 'page x of y' and with a watermark on every page.: see pageNumbersWatermark.pdf
External resources for this example: logo.gif
Bookmarks
This example was already mentioned in the chapter on bookmarks.
Example: java com.lowagie.examples.directcontent.pageevents.Bookmarks
Using paragraph events: see bookmarks.pdf
Go to top of the page
Romeo and Juliet: XML to PDF:
In this example, we combine some of the most interesting functionalities of iText. We have an XML file (playRomeoJuliet.xml) containing the complete play 'Romeo and Juliet' by William Shakespeare. We have defined a tagmap (tagmapRomeoJuliet.xml) that translates the tags in the XML to tags that can be understood by iText. iText will parse the XML and generate the PDF file using this tagmap.
A Speaker-class was written to keep track of all the different speakers. As you can see in the page event implementation, we update the list of speakers in the onGenericTag method. We do some initialisations in the onOpenDocument method, we keep track of the current act in the onChapter method, we add this information as a header on every even page of the document and also put a 'page X of Y'-footer in the onPageEnd method and finally, we set the value of this Y in the onCloseDocument method. After the document is parsed, we retrieve the alphabetical list of speaker from out event class and add an extra page with this info.
Example: java com.lowagie.examples.directcontent.pageevents.Events
Using PageEvents: see RomeoJuliet.pdf
External resources for this example: tagmapRomeoJuliet.xml playRomeoJuliet.xml
Extra jars needed in your CLASSPATH: crimson.jar
Go to top of the page
Amazon books:
amazon.co.uk-link