iText pdf library
Website search

Chapter 5: Table, cell, and page events

These examples were written in the context of Chapter 5 of the book "iText in Action - Second Edition".

AlternatingBackground.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPTableEvent;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
 
public class AlternatingBackground implements PdfPTableEvent {
 
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/alternating.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename) throws SQLException, DocumentException, IOException {
        // Create a database connection 
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        List<Date> days = PojoFactory.getDays(connection);
        PdfPTableEvent event = new AlternatingBackground();
        for (Date day : days) {
            PdfPTable table = getTable(connection, day);
            table.setTableEvent(event);
            document.add(table);
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Creates a table with film festival screenings.
     * @param connection a database connection
     * @param day a film festival day
     * @return a table with screenings.
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable getTable(DatabaseConnection connection, Date day)
        throws SQLException, DocumentException, IOException {
        PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1 });
        table.setWidthPercentage(100f);
        table.getDefaultCell().setPadding(3);
        table.getDefaultCell().setUseAscender(true);
        table.getDefaultCell().setUseDescender(true);
        table.getDefaultCell().setColspan(5);
        table.getDefaultCell().setBackgroundColor(BaseColor.RED);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.addCell(day.toString());
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.getDefaultCell().setColspan(1);
        table.getDefaultCell().setBackgroundColor(BaseColor.ORANGE);
        for (int i = 0; i < 2; i++) {
            table.addCell("Location");
            table.addCell("Time");
            table.addCell("Run Length");
            table.addCell("Title");
            table.addCell("Year");
        }
        table.getDefaultCell().setBackgroundColor(null);
        table.setHeaderRows(3);
        table.setFooterRows(1);
        List<Screening> screenings = PojoFactory.getScreenings(connection, day);
        Movie movie;
        for (Screening screening : screenings) {
            movie = screening.getMovie();
            table.addCell(screening.getLocation());
            table.addCell(String.format("%1$tH:%1$tM", screening.getTime()));
            table.addCell(String.format("%d '", movie.getDuration()));
            table.addCell(movie.getMovieTitle());
            table.addCell(String.valueOf(movie.getYear()));
        }
        return table;
    }
    
    /**
     * Draws a background for every other row.
     * @see com.itextpdf.text.pdf.PdfPTableEvent#tableLayout(
     *      com.itextpdf.text.pdf.PdfPTable, float[][], float[], int, int,
     *      com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void tableLayout(PdfPTable table, float[][] widths, float[] heights,
        int headerRows, int rowStart, PdfContentByte[] canvases) {
        int columns;
        Rectangle rect;
        int footer = widths.length - table.getFooterRows();
        int header = table.getHeaderRows() - table.getFooterRows() + 1;
        for (int row = header; row < footer; row += 2) {
            columns = widths[row].length - 1;
            rect = new Rectangle(widths[row][0], heights[row],
                        widths[row][columns], heights[row + 1]);
            rect.setBackgroundColor(BaseColor.YELLOW);
            rect.setBorder(Rectangle.NO_BORDER);
            canvases[PdfPTable.BASECANVAS].rectangle(rect);
        }
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException, DocumentException, IOException {
        new AlternatingBackground().createPdf(RESULT);
    }
}
RunLengthEvent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
 
public class RunLengthEvent {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part1/chapter05/run_length.pdf";
 
    /** Inner class to draw a bar inside a cell. */
    class RunLength implements PdfPCellEvent {
        
        public int duration;
        
        public RunLength(int duration) {
            this.duration = duration;
        }
        
        /**
         * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(
         *      com.lowagie.text.pdf.PdfPCell, com.lowagie.text.Rectangle,
         *      com.lowagie.text.pdf.PdfContentByte[])
         */
        public void cellLayout(PdfPCell cell, Rectangle rect,
                PdfContentByte[] canvas) {
            PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
            cb.saveState();
            if (duration < 90) {
                cb.setRGBColorFill(0x7C, 0xFC, 0x00);
            }
            else if (duration > 120) {
                cb.setRGBColorFill(0x8B, 0x00, 0x00);
            } 
            else {
                cb.setRGBColorFill(0xFF, 0xA5, 0x00);
            }
            cb.rectangle(rect.getLeft(), rect.getBottom(),
                rect.getWidth() * duration / 240, rect.getHeight());
            cb.fill();
            cb.restoreState();
        }
    }
 
    /** Inner class to add the words PRESS PREVIEW to a cell. */
    class PressPreview implements PdfPCellEvent {
        
        public BaseFont bf;
        
        public PressPreview() throws DocumentException, IOException {
            bf = BaseFont.createFont();
        }
        
        /**
         * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(com.lowagie.text.pdf.PdfPCell,
         *      com.lowagie.text.Rectangle,
         *      com.lowagie.text.pdf.PdfContentByte[])
         */
        public void cellLayout(PdfPCell cell, Rectangle rect,
                PdfContentByte[] canvas) {
            PdfContentByte cb = canvas[PdfPTable.TEXTCANVAS];
            cb.beginText();
            cb.setFontAndSize(bf, 12);
            cb.showTextAligned(Element.ALIGN_RIGHT, "PRESS PREVIEW",
                rect.getRight() - 3, rect.getBottom() + 4.5f, 0);
            cb.endText();
        }
    }
    
    /** The press cell event. */
    public PdfPCellEvent press;
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws SQLException, DocumentException, IOException {
        press = new PressPreview();
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        List<Date> days = PojoFactory.getDays(connection);
        for (Date day : days) {
            document.add(getTable(connection, day));
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * @param connection
     * @param day
     * @return
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable getTable(DatabaseConnection connection, Date day)
        throws SQLException, DocumentException, IOException {
        PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1 });
        table.setWidthPercentage(100f);
        table.getDefaultCell().setPadding(3);
        table.getDefaultCell().setUseAscender(true);
        table.getDefaultCell().setUseDescender(true);
        table.getDefaultCell().setColspan(5);
        table.getDefaultCell().setBackgroundColor(BaseColor.RED);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.addCell(day.toString());
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.getDefaultCell().setColspan(1);
        table.getDefaultCell().setBackgroundColor(BaseColor.YELLOW);
        for (int i = 0; i < 2; i++) {
            table.addCell("Location");
            table.addCell("Time");
            table.addCell("Run Length");
            table.addCell("Title");
            table.addCell("Year");
        }
        table.getDefaultCell().setBackgroundColor(null);
        table.setHeaderRows(3);
        table.setFooterRows(1);
        List<Screening> screenings = PojoFactory.getScreenings(connection, day);
        Movie movie;
        PdfPCell runLength;
        for (Screening screening : screenings) {
            movie = screening.getMovie();
            table.addCell(screening.getLocation());
            table.addCell(String.format("%1$tH:%1$tM", screening.getTime()));
            runLength = new PdfPCell(table.getDefaultCell());
            runLength.setPhrase(new Phrase(String.format("%d '", movie.getDuration())));
            runLength.setCellEvent(new RunLength(movie.getDuration()));
            if (screening.isPress()) {
                runLength.setCellEvent(press);
            }
            table.addCell(runLength);
            table.addCell(movie.getMovieTitle());
            table.addCell(String.valueOf(movie.getYear()));
        }
        return table;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException, DocumentException, IOException {
        new RunLengthEvent().createPdf(RESULT);
    }
}
PressPreviews.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPTableEvent;
import com.itextpdf.text.pdf.PdfWriter;
 
public class PressPreviews implements PdfPCellEvent, PdfPTableEvent {
 
    /** The resulting PDF. */
    public static final String RESULT = "results/part1/chapter05/press_previews.pdf";
 
    /**
     * @see com.itextpdf.text.pdf.PdfPTableEvent#tableLayout(com.itextpdf.text.pdf.PdfPTable,
     *      float[][], float[], int, int, com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void tableLayout(PdfPTable table, float[][] width, float[] height,
            int headerRows, int rowStart, PdfContentByte[] canvas) {
        float widths[] = width[0];
        float x1 = widths[0];
        float x2 = widths[widths.length - 1];
        float y1 = height[0];
        float y2 = height[height.length - 1];
        PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
        cb.rectangle(x1, y1, x2 - x1, y2 - y1);
        cb.stroke();
        cb.resetRGBColorStroke();
    }
 
    /**
     * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(com.lowagie.text.pdf.PdfPCell,
     *      com.lowagie.text.Rectangle, com.lowagie.text.pdf.PdfContentByte[])
     */
    public void cellLayout(PdfPCell cell, Rectangle position,
            PdfContentByte[] canvases) {
        float x1 = position.getLeft() + 2;
        float x2 = position.getRight() - 2;
        float y1 = position.getTop() - 2;
        float y2 = position.getBottom() + 2;
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.rectangle(x1, y1, x2 - x1, y2 - y1);
        canvas.stroke();
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws SQLException, DocumentException, IOException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        document.add(getTable(connection));
        // step 5
        document.close();
        // close the database connection
        connection.close();
    }
    
    /**
     * Creates a table that mimics cellspacing using table and cell events.
     * @param connection
     * @return a table
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable getTable(DatabaseConnection connection)
        throws SQLException, DocumentException, IOException {
        PdfPTable table = new PdfPTable(new float[] { 1, 2, 2, 5, 1 });
        table.setTableEvent(new PressPreviews());
        table.setWidthPercentage(100f);
        table.getDefaultCell().setPadding(5);
        table.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
        table.getDefaultCell().setCellEvent(new PressPreviews());
        for (int i = 0; i < 2; i++) {
            table.addCell("Location");
            table.addCell("Date/Time");
            table.addCell("Run Length");
            table.addCell("Title");
            table.addCell("Year");
        }
        table.getDefaultCell().setBackgroundColor(null);
        table.setHeaderRows(2);
        table.setFooterRows(1);
        List<Screening> screenings = PojoFactory.getPressPreviews(connection);
        Movie movie;
        for (Screening screening : screenings) {
            movie = screening.getMovie();
            table.addCell(screening.getLocation());
            table.addCell(String.format("%s   %2$tH:%2$tM",
                screening.getDate().toString(), screening.getTime()));
            table.addCell(String.format("%d '", movie.getDuration()));
            table.addCell(movie.getMovieTitle());
            table.addCell(String.valueOf(movie.getYear()));
        }
        return table;
    }
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException, DocumentException, IOException {
        new PressPreviews().createPdf(RESULT);
    }
}
PdfCalendar.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPTableEvent;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.VerticalPositionMark;
 
public class PdfCalendar extends part1.chapter04.PdfCalendar {
 
    /** The resulting PDF. */
    public static final String RESULT = "results/part1/chapter05/calendar.pdf";
 
    /** A table event. */
    public PdfPTableEvent tableBackground;
    /** A cell event. */
    public PdfPCellEvent cellBackground;
    /** A cell event. */
    public PdfPCellEvent roundRectangle;
    /** A cell event. */
    public PdfPCellEvent whiteRectangle;
    
    /**
     * Inner class with a table event that draws a background with rounded corners.
     */
    class TableBackground implements PdfPTableEvent {
        
        public void tableLayout(PdfPTable table, float[][] width, float[] height,
                int headerRows, int rowStart, PdfContentByte[] canvas) {
            PdfContentByte background = canvas[PdfPTable.BASECANVAS];
            background.saveState();
            background.setCMYKColorFill(0x00, 0x00, 0xFF, 0x0F);
            background.roundRectangle(
                width[0][0], height[height.length - 1] - 2,
                width[0][1] - width[0][0] + 6, height[0] - height[height.length - 1] - 4, 4);
            background.fill();
            background.restoreState();
        }
 
    }
    
    /**
     * Inner class with a cell event that draws a background with rounded corners.
     */
    class CellBackground implements PdfPCellEvent {
        
        public void cellLayout(PdfPCell cell, Rectangle rect,
                PdfContentByte[] canvas) {
            PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
            cb.roundRectangle(
                rect.getLeft() + 1.5f, rect.getBottom() + 1.5f, rect.getWidth() - 3,
                rect.getHeight() - 3, 4);
            cb.setCMYKColorFill(0x00, 0x00, 0x00, 0x00);
            cb.fill();
        }
    }
 
    /**
     * Inner class with a cell event that draws a border with rounded corners.
     */
    class RoundRectangle implements PdfPCellEvent {
        /** the border color described as CMYK values. */
        protected int[] color;
        /** Constructs the event using a certain color. */
        public RoundRectangle(int[] color) {
            this.color = color;
        }
        
        public void cellLayout(PdfPCell cell, Rectangle rect,
                PdfContentByte[] canvas) {
            PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
            cb.roundRectangle(
                rect.getLeft() + 1.5f, rect.getBottom() + 1.5f, rect.getWidth() - 3,
                rect.getHeight() - 3, 4);
            cb.setLineWidth(1.5f);
            cb.setCMYKColorStrokeF(color[0], color[1], color[2], color[3]);
            cb.stroke();
        }
    }
    
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws IOException 
     * @throws DocumentException 
     */
    public static void main(String[] args) throws IOException, DocumentException {
        Locale locale = new Locale(LANGUAGE);
        new PdfCalendar().createPdf(RESULT, locale, YEAR);
    }
 
    /**
     * Initializes the fonts and collections.
     * @throws DocumentException
     * @throws IOException
     */
    public PdfCalendar() throws DocumentException, IOException {
        super();
        tableBackground = new TableBackground();
        cellBackground = new CellBackground();
        roundRectangle = new RoundRectangle(new int[]{ 0xFF, 0x00, 0xFF, 0x00 });
        whiteRectangle = new RoundRectangle(new int[]{ 0x00, 0x00, 0x00, 0x00 });
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @param locale Locale in case you want to create
     * a Calendar in another language
     * @param year the year for which you want to make a calendar
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename, Locale locale, int year) throws IOException, DocumentException {
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table;
        Calendar calendar;
        PdfContentByte canvas = writer.getDirectContent();
        // Loop over the months
        for (int month = 0; month < 12; month++) {
            calendar = new GregorianCalendar(year, month, 1);
            // draw the background
            drawImageAndText(canvas, calendar);
            // create a table with 7 columns
            table = new PdfPTable(7);
            table.setTableEvent(tableBackground);
            table.setTotalWidth(504);
            // add the name of the month
            table.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
            table.getDefaultCell().setCellEvent(whiteRectangle);
            table.addCell(getMonthCell(calendar, locale));
            int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            int day = 1;
            int position = 2;
            // add empty cells
            while (position != calendar.get(Calendar.DAY_OF_WEEK)) {
                position = (position % 7) + 1;
                table.addCell("");
            }
            // add cells for each day
            while (day <= daysInMonth) {
                calendar = new GregorianCalendar(year, month, day++);
                table.addCell(getDayCell(calendar, locale));
            }
            // complete the table
            table.completeRow();
            // write the table to an absolute position
            table.writeSelectedRows(0, -1, 169, table.getTotalHeight() + 20, canvas);
            document.newPage();
        }
        // step 5
        document.close();
    }
    
    /**
     * Creates a PdfPCell with the name of the month
     * @param calendar a date
     * @param locale a locale
     * @return a PdfPCell with rowspan 7, containing the name of the month
     */
    public PdfPCell getMonthCell(Calendar calendar, Locale locale) {
        PdfPCell cell = new PdfPCell();
        cell.setColspan(7);
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setUseDescender(true);
        Paragraph p = new Paragraph(String.format(locale, "%1$tB %1$tY", calendar), bold);
        p.setAlignment(Element.ALIGN_CENTER);
        cell.addElement(p);
        return cell;
    }
 
    /**
     * Creates a PdfPCell for a specific day
     * @param calendar a date
     * @param locale a locale
     * @return a PdfPCell
     */
    public PdfPCell getDayCell(Calendar calendar, Locale locale) {
        PdfPCell cell = new PdfPCell();
        // set the event to draw the background
        cell.setCellEvent(cellBackground);
        // set the event to draw a special border
        if (isSunday(calendar) || isSpecialDay(calendar))
            cell.setCellEvent(roundRectangle);
        cell.setPadding(3);
        cell.setBorder(PdfPCell.NO_BORDER);
        // set the content in the language of the locale
        Chunk chunk = new Chunk(String.format(locale, "%1$ta", calendar), small);
        chunk.setTextRise(8);
        // a paragraph with the day
        Paragraph p = new Paragraph(chunk);
        // a separator
        p.add(new Chunk(new VerticalPositionMark()));
        // and the number of the day
        p.add(new Chunk(String.format(locale, "%1$te", calendar), normal));
        cell.addElement(p);
        return cell;
    }
    
    /**
     * Returns true if the date was found in a list with special days (holidays).
     * @param calendar a date
     * @return true for holidays
     */
    public boolean isSpecialDay(Calendar calendar) {
        if (specialDays.containsKey(String.format("%1$tm%1$td", calendar)))
            return true;
        return false;
    }
}
MovieYears.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
 
public class MovieYears {
    
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter05/movie_years.pdf";
 
    /**
     * Inner class to add functionality to a Chunk in a generic way.
     */
    class GenericTags extends PdfPageEventHelper {
         
        public void onGenericTag(PdfWriter writer, Document pdfDocument,
                Rectangle rect, String text) {
            if ("strip".equals(text))
                strip(writer.getDirectContent(), rect);
            else if ("ellipse".equals(text))
                ellipse(writer.getDirectContentUnder(), rect);
            else
                countYear(text);
        }
 
        public void strip(PdfContentByte content, Rectangle rect) {
            content.rectangle(rect.getLeft() - 1, rect.getBottom() - 5f,
                    rect.getWidth(), rect.getHeight() + 8);
            content.rectangle(rect.getLeft(), rect.getBottom() - 2,
                    rect.getWidth() - 2, rect.getHeight() + 2);
            float y1 = rect.getTop() + 0.5f;
            float y2 = rect.getBottom() - 4;
            for (float f = rect.getLeft(); f < rect.getRight() - 4; f += 5) {
                content.rectangle(f, y1, 4f, 1.5f);
                content.rectangle(f, y2, 4f, 1.5f);
            }
            content.eoFill();
        }
        
        public void ellipse(PdfContentByte content, Rectangle rect) {
            content.saveState();
            content.setRGBColorFill(0x00, 0x00, 0xFF);
            content.ellipse(rect.getLeft() - 3f, rect.getBottom() - 5f,
                    rect.getRight() + 3f, rect.getTop() + 3f);
            content.fill();
            content.restoreState();
        }
 
        TreeMap<String, Integer> years = new TreeMap<String, Integer>();
        
        public void countYear(String text) {
            Integer count = years.get(text);
            if (count == null) {
                years.put(text, 1);
            }
            else {
                years.put(text, count + 1);
            }
        }
    }
    
    /**
     * Inner class to add lines when a paragraph begins and ends.
     */
    class ParagraphPositions extends PdfPageEventHelper {
        public void onParagraph(PdfWriter writer, Document pdfDocument,
                float paragraphPosition) {
            drawLine(writer.getDirectContent(),
                    pdfDocument.left(), pdfDocument.right(), paragraphPosition - 8);
        }
 
        public void onParagraphEnd(PdfWriter writer, Document pdfDocument,
                float paragraphPosition) {
            drawLine(writer.getDirectContent(),
                    pdfDocument.left(), pdfDocument.right(), paragraphPosition - 5);
        }
        
        public void drawLine(PdfContentByte cb, float x1, float x2, float y) {
            cb.moveTo(x1, y);
            cb.lineTo(x2, y);
            cb.stroke();
        }
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename) throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        GenericTags event = new GenericTags();
        writer.setPageEvent(event);
        writer.setPageEvent(new ParagraphPositions());
        // step 3
        document.open();
        // step 4
        Font bold = new Font(FontFamily.HELVETICA, 11, Font.BOLD);
        Font italic = new Font(FontFamily.HELVETICA, 11, Font.ITALIC);
        Font white = new Font(FontFamily.HELVETICA, 12, Font.BOLD | Font.ITALIC, BaseColor.WHITE);
        Paragraph p;
        Chunk c;
        
        Set<Movie> movies = 
            new TreeSet<Movie>(new MovieComparator(MovieComparator.BY_YEAR));
        movies.addAll(PojoFactory.getMovies(connection));
        for (Movie movie : movies) {
            p = new Paragraph(22);
            c = new Chunk(String.format("%d ", movie.getYear()), bold);
            c.setGenericTag("strip");
            p.add(c);
            c = new Chunk(movie.getMovieTitle());
            c.setGenericTag(String.valueOf(movie.getYear()));
            p.add(c);
            c = new Chunk(String.format(" (%d minutes)  ", movie.getDuration()), italic);
            p.add(c);
            c = new Chunk("IMDB", white);
            c.setAnchor("http://www.imdb.com/title/tt" + movie.getImdb());
            c.setGenericTag("ellipse");
            p.add(c);
            document.add(p);
        }
        document.newPage();
        writer.setPageEvent(null);
        for (Map.Entry<String,Integer> entry : event.years.entrySet()) {
            p = new Paragraph(String.format("%s: %d movie(s)", entry.getKey(), entry.getValue()));
            document.add(p);
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieYears().createPdf(RESULT);
    }
}
MovieHistory1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chapter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Section;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieHistory1 {
    
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/movie_history1.pdf";
 
    /**
     * Inner class to keep track of the TOC
     * and to draw lines under ever chapter and section.
     */
    class ChapterSectionTOC extends PdfPageEventHelper {
        /** List with the titles. */
        List<Paragraph> titles = new ArrayList<Paragraph>();
        
        public void onChapter(PdfWriter writer, Document document,
                float position, Paragraph title) {
            titles.add(new Paragraph(title.getContent(), FONT[4]));
        }
 
        public void onChapterEnd(PdfWriter writer, Document document,
                float position) {
            drawLine(writer.getDirectContent(),
                    document.left(), document.right(), position - 5);
        }
 
        public void onSection(PdfWriter writer, Document document,
                float position, int depth, Paragraph title) {
            title = new Paragraph(title.getContent(), FONT[4]);
            title.setIndentationLeft(18 * depth);
            titles.add(title);
        }
 
        public void onSectionEnd(PdfWriter writer, Document document,
                float position) {
            drawLine(writer.getDirectContent(),
                    document.left(), document.right(), position - 3);
        }
        
        public void drawLine(PdfContentByte cb, float x1, float x2, float y) {
            cb.moveTo(x1, y);
            cb.lineTo(x2, y);
            cb.stroke();
        }
    }
    
    /** The different epochs. */
    public static final String[] EPOCH =
        { "Forties", "Fifties", "Sixties", "Seventies", "Eighties",
          "Nineties", "Twenty-first Century" };
    /** The fonts for the title. */
    public static final Font[] FONT = new Font[5];
    static {
        FONT[0] = new Font(FontFamily.HELVETICA, 24);
        FONT[1] = new Font(FontFamily.HELVETICA, 18);
        FONT[2] = new Font(FontFamily.HELVETICA, 14);
        FONT[3] = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
        FONT[4] = new Font(FontFamily.HELVETICA, 10);
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // IMPORTANT: set linear page mode!
        writer.setLinearPageMode();
        ChapterSectionTOC event = new ChapterSectionTOC();
        writer.setPageEvent(event);
        // step 3
        document.open();
        // step 4
        // add the chapters
        Set<Movie> movies = 
            new TreeSet<Movie>(new MovieComparator(MovieComparator.BY_YEAR));
        movies.addAll(PojoFactory.getMovies(connection));
        int epoch = -1;
        int currentYear = 0;
        Paragraph title = null;
        Chapter chapter = null;
        Section section = null;
        Section subsection = null;
        for (Movie movie : movies) {
            if (epoch < (movie.getYear() - 1940) / 10) {
                epoch = (movie.getYear() - 1940) / 10;
                if (chapter != null) {
                    document.add(chapter);
                }
                title = new Paragraph(EPOCH[epoch], FONT[0]);
                chapter = new Chapter(title, epoch + 1);
            }
            if (currentYear < movie.getYear()) {
                currentYear = movie.getYear();
                title = new Paragraph(
                    String.format("The year %d", movie.getYear()), FONT[1]);
                section = chapter.addSection(title);
                section.setBookmarkTitle(String.valueOf(movie.getYear()));
                section.setIndentation(30);
                section.setBookmarkOpen(false);
                section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
                section.add(new Paragraph(
                    String.format("Movies from the year %d:", movie.getYear())));
            }
            title = new Paragraph(movie.getMovieTitle(), FONT[2]);
            subsection = section.addSection(title);
            subsection.setIndentationLeft(20);
            subsection.setNumberDepth(1);
            subsection.add(new Paragraph("Duration: " + movie.getDuration(), FONT[3]));
            subsection.add(new Paragraph("Director(s):", FONT[3]));
            subsection.add(PojoToElementFactory.getDirectorList(movie));
            subsection.add(new Paragraph("Countries:", FONT[3]));
            subsection.add(PojoToElementFactory.getCountryList(movie));
        }
        document.add(chapter);
        // add the TOC starting on the next page
        document.newPage();
        int toc = writer.getPageNumber();
        for (Paragraph p : event.titles) {
            document.add(p);
        }
        // always go to a new page before reordering pages.
        document.newPage();
        // get the total number of pages that needs to be reordered
        int total = writer.reorderPages(null);
        // change the order
        int[] order = new int[total];
        for (int i = 0; i < total; i++) {
            order[i] = i + toc;
            if (order[i] > total)
                order[i] -= total;
        }
        // apply the new order
        writer.reorderPages(order);
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieHistory1().createPdf(RESULT);
    }
}
NewPage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
 
public class NewPage {
    
    /** Path to the resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/new_page.pdf";
    
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws IOException 
     * @throws DocumentException 
     */
    public static void main(String[] args) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("This page will NOT be followed by a blank page!"));
        document.newPage();
        // we don't add anything to this page: newPage() will be ignored
        document.newPage();
        document.add(new Paragraph("This page will be followed by a blank page!"));
        document.newPage();
        writer.setPageEmpty(false);
        document.newPage();
        document.add(new Paragraph("The previous page was a blank page!"));
        // step 5
        document.close();
        
    }
}
Hero1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class Hero1 {
 
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter05/hero1.pdf";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/txt/hero.txt";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
        // step 1
        Rectangle rect = new Rectangle(-1192, -1685, 1192, 1685);
        Document document = new Document(rect);
        // step 2
        PdfWriter writer =
            PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfContentByte content = writer.getDirectContent();
        PdfTemplate template = createTemplate(content, rect, 4);
        content.addTemplate(template, -1192, -1685);
        content.moveTo(-595, 0);
        content.lineTo(595, 0);
        content.moveTo(0, -842);
        content.lineTo(0, 842);
        content.stroke();
        // step 5
        document.close();
    }
    
    /**
     * Creates a template based on a stream of PDF syntax.
     * @param content The direct content
     * @param rect The dimension of the templare
     * @param factor A magnification factor
     * @return A PdfTemplate
     * @throws IOException
     */
    public PdfTemplate createTemplate(PdfContentByte content, Rectangle rect, int factor)
        throws IOException {
        PdfTemplate template = content.createTemplate(rect.getWidth(), rect.getHeight());
        template.concatCTM(factor, 0, 0, factor, 0, 0);
        FileReader reader = new FileReader(RESOURCE);
        int c;
        while ((c = reader.read()) > -1) {
            template.setLiteral((char)c);
        }
        return template;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new Hero1().createPdf(RESULT);
    }
}
Hero2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class Hero2 extends Hero1 {
 
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter05/hero2.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        float w = PageSize.A4.getWidth();
        float h = PageSize.A4.getHeight();
        Rectangle rect = new Rectangle(-2*w, -2*h, 2*w, 2*h);
        Rectangle crop = new Rectangle(-2 * w, h, -w, 2 * h);
        // step 1
        Document document = new Document(rect);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        writer.setCropBoxSize(crop);
        // step 3
        document.open();
        // step 4
        PdfContentByte content = writer.getDirectContent();
        PdfTemplate template = createTemplate(content, rect, 4);
        float adjust;
        while(true) {
            content.addTemplate(template, -2*w, -2*h);
            adjust = crop.getRight() + w;
            if (adjust > 2 * w) {
                adjust = crop.getBottom() - h;
                if (adjust < - 2 * h)
                    break;
                crop = new Rectangle(-2*w, adjust, -w, crop.getBottom());
            }
            else {
                crop = new Rectangle(crop.getRight(), crop.getBottom(), adjust, crop.getTop());
            }
            writer.setCropBoxSize(crop);
            document.newPage();
        }
        // step 5
        document.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new Hero2().createPdf(RESULT);
    }
}
Hero3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class Hero3 extends Hero1 {
 
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter05/hero3.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
        Document document = new Document(PageSize.A4);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        Rectangle art = new Rectangle(50, 50, 545, 792);
        writer.setBoxSize("art", art);
        // step 3
        document.open();
        // step 4
        PdfContentByte content = writer.getDirectContent();
        PdfTemplate template = createTemplate(content, PageSize.A4, 1);
        content.addTemplate(template, 0, 0);
        // step 5
        document.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new Hero3().createPdf(RESULT);
    }
}
MovieHistory2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Set;
import java.util.TreeSet;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chapter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Section;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieHistory2 {
    
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/movie_history2.pdf";
    
    /** Inner class to add a header and a footer. */
    class HeaderFooter extends PdfPageEventHelper {
        /** Alternating phrase for the header. */
        Phrase[] header = new Phrase[2];
        /** Current page number (will be reset for every chapter). */
        int pagenumber;
        
        /**
         * Initialize one of the headers.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onOpenDocument(PdfWriter writer, Document document) {
            header[0] = new Phrase("Movie history");
        }
        
        /**
         * Initialize one of the headers, based on the chapter title;
         * reset the page number.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onChapter(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document, float,
         *      com.itextpdf.text.Paragraph)
         */
        public void onChapter(PdfWriter writer, Document document,
                float paragraphPosition, Paragraph title) {
            header[1] = new Phrase(title.getContent());
            pagenumber = 1;
        }
 
        /**
         * Increase the page number.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onStartPage(PdfWriter writer, Document document) {
            pagenumber++;
        }
        
        /**
         * Adds the header and the footer.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onEndPage(PdfWriter writer, Document document) {
            Rectangle rect = writer.getBoxSize("art");
            switch(writer.getPageNumber() % 2) {
            case 0:
                ColumnText.showTextAligned(writer.getDirectContent(),
                        Element.ALIGN_RIGHT, header[0],
                        rect.getRight(), rect.getTop(), 0);
                break;
            case 1:
                ColumnText.showTextAligned(writer.getDirectContent(),
                        Element.ALIGN_LEFT, header[1],
                        rect.getLeft(), rect.getTop(), 0);
                break;
            }
            ColumnText.showTextAligned(writer.getDirectContent(),
                    Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)),
                    (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
        }
    }
    
    /** The different epochs. */
    public static final String[] EPOCH =
        { "Forties", "Fifties", "Sixties", "Seventies", "Eighties",
          "Nineties", "Twenty-first Century" };
    /** The fonts for the title. */
    public static final Font[] FONT = new Font[4];
    static {
        FONT[0] = new Font(FontFamily.HELVETICA, 24);
        FONT[1] = new Font(FontFamily.HELVETICA, 18);
        FONT[2] = new Font(FontFamily.HELVETICA, 14);
        FONT[3] = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 54, 54);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        HeaderFooter event = new HeaderFooter();
        writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
        writer.setPageEvent(event);
        // step 3
        document.open();
        // step 4
        Set<Movie> movies = 
            new TreeSet<Movie>(new MovieComparator(MovieComparator.BY_YEAR));
        movies.addAll(PojoFactory.getMovies(connection));
        int epoch = -1;
        int currentYear = 0;
        Paragraph title = null;
        Chapter chapter = null;
        Section section = null;
        Section subsection = null;
        for (Movie movie : movies) {
            if (epoch < (movie.getYear() - 1940) / 10) {
                epoch = (movie.getYear() - 1940) / 10;
                if (chapter != null) {
                    document.add(chapter);
                }
                title = new Paragraph(EPOCH[epoch], FONT[0]);
                chapter = new Chapter(title, epoch + 1);
            }
            if (currentYear < movie.getYear()) {
                currentYear = movie.getYear();
                title = new Paragraph(String.format("The year %d", movie.getYear()), FONT[1]);
                section = chapter.addSection(title);
                section.setBookmarkTitle(String.valueOf(movie.getYear()));
                section.setIndentation(30);
                section.setBookmarkOpen(false);
                section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
                section.add(new Paragraph(String.format("Movies from the year %d:", movie.getYear())));
            }
            title = new Paragraph(movie.getMovieTitle(), FONT[2]);
            subsection = section.addSection(title);
            subsection.setIndentationLeft(20);
            subsection.setNumberDepth(1);
            subsection.add(new Paragraph("Duration: " + movie.getDuration(), FONT[3]));
            subsection.add(new Paragraph("Director(s):", FONT[3]));
            subsection.add(PojoToElementFactory.getDirectorList(movie));
            subsection.add(new Paragraph("Countries:", FONT[3]));
            subsection.add(PojoToElementFactory.getCountryList(movie));
        }
        document.add(chapter);
        // step 5
        document.close();
        // close the database connection
        connection.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieHistory2().createPdf(RESULT);
    }
}
MovieCountries1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.TreeSet;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.ExceptionConverter;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieCountries1 {
    
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/movie_countries1.pdf";
 
    /**
     * Inner class to add a table as header.
     */
    class TableHeader extends PdfPageEventHelper {
        /** The header text. */
        String header;
        /** The template with the total number of pages. */
        PdfTemplate total;
        
        /**
         * Allows us to change the content of the header.
         * @param header The new header String
         */
        public void setHeader(String header) {
            this.header = header;
        }
 
        /**
         * Creates the PdfTemplate that will hold the total number of pages.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onOpenDocument(PdfWriter writer, Document document) {
            total = writer.getDirectContent().createTemplate(30, 16);
        }
        
        /**
         * Adds a header to every page
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onEndPage(PdfWriter writer, Document document) {
            PdfPTable table = new PdfPTable(3);
            try {
                table.setWidths(new int[]{24, 24, 2});
                table.setTotalWidth(527);
                table.setLockedWidth(true);
                table.getDefaultCell().setFixedHeight(20);
                table.getDefaultCell().setBorder(Rectangle.BOTTOM);
                table.addCell(header);
                table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
                table.addCell(String.format("Page %d of", writer.getPageNumber()));
                PdfPCell cell = new PdfPCell(Image.getInstance(total));
                cell.setBorder(Rectangle.BOTTOM);
                table.addCell(cell);
                table.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent());
            }
            catch(DocumentException de) {
                throw new ExceptionConverter(de);
            }
        }
        
        /**
         * Fills out the total number of pages before the document is closed.
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(
         *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
         */
        public void onCloseDocument(PdfWriter writer, Document document) {
            ColumnText.showTextAligned(total, Element.ALIGN_LEFT,
                    new Phrase(String.valueOf(writer.getPageNumber() - 1)),
                    2, 2, 0);
        }
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 54, 36);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        TableHeader event = new TableHeader();
        writer.setPageEvent(event);
        // step 3
        document.open();
        // step 4
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        while (rs.next()) {
            event.setHeader(rs.getString("country"));
            Set<Movie> movies = 
                new TreeSet<Movie>(new MovieComparator(MovieComparator.BY_YEAR));
            movies.addAll(PojoFactory.getMovies(connection, rs.getString("id")));
            for(Movie movie : movies) {
                document.add(new Paragraph(movie.getMovieTitle(), FilmFonts.BOLD));
                if (movie.getOriginalTitle() != null)
                    document.add(new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC));
                document.add(new Paragraph(
                    String.format("Year: %d; run length: %d minutes",
                        movie.getYear(), movie.getDuration()), FilmFonts.NORMAL));
                document.add(PojoToElementFactory.getDirectorList(movie));
            }
            document.newPage();
        }
        // step 4
        document.close();
        // close the database connection
        connection.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieCountries1().createPdf(RESULT);
    }
}
MovieCountries2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.TreeSet;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieCountries2 extends MovieCountries1 {
    
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter05/movie_countries2.pdf";
 
    /**
     * Inner class to add a watermark to every page.
     */
    class Watermark extends PdfPageEventHelper {
        
        Font FONT = new Font(FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));
        
        public void onEndPage(PdfWriter writer, Document document) {
            ColumnText.showTextAligned(writer.getDirectContentUnder(),
                    Element.ALIGN_CENTER, new Phrase("FOOBAR FILM FESTIVAL", FONT),
                    297.5f, 421, writer.getPageNumber() % 2 == 1 ? 45 : -45);
        }
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 54, 36);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        TableHeader event = new TableHeader();
        writer.setPageEvent(event);
        writer.setPageEvent(new Watermark());
        // step 3
        document.open();
        // step 4
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        while (rs.next()) {
            event.setHeader(rs.getString("country"));
            Set<Movie> movies = 
                new TreeSet<Movie>(new MovieComparator(MovieComparator.BY_YEAR));
            movies.addAll(PojoFactory.getMovies(connection, rs.getString("id")));
            for(Movie movie : movies) {
                document.add(new Paragraph(movie.getMovieTitle(), FilmFonts.BOLD));
                if (movie.getOriginalTitle() != null)
                    document.add(new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC));
                document.add(new Paragraph(String.format("Year: %d; run length: %d minutes",
                    movie.getYear(), movie.getDuration()), FilmFonts.NORMAL));
                document.add(PojoToElementFactory.getDirectorList(movie));
            }
            document.newPage();
        }
        // step 5
        document.close();
        // close the database connection
        connection.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieCountries2().createPdf(RESULT);
    }
}
MovieSlideShow.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part1.chapter05;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTransition;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieSlideShow {
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter05/movie_slides.pdf";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/posters/%s.jpg";
    
    
    /**
     * Page event to set the transition and duration for every page.
     */
    class TransitionDuration extends PdfPageEventHelper {
 
        public void onStartPage(PdfWriter writer, Document document) {
            writer.setTransition(new PdfTransition(PdfTransition.DISSOLVE, 3));
            writer.setDuration(5);
        }
        
    }
        
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");    
        // step 1
        Document document = new Document(PageSize.A5.rotate());
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        writer.setViewerPreferences(PdfWriter.PageModeFullScreen);
        writer.setPageEvent(new TransitionDuration());
        // step 3
        document.open();
        // step 4
        List<Movie> movies = PojoFactory.getMovies(connection);
        Image img;
        PdfPCell cell;
        PdfPTable table = new PdfPTable(6);
        for (Movie movie : movies) {
            img = Image.getInstance(String.format(RESOURCE, movie.getImdb()));
            cell = new PdfPCell(img, true);
            cell.setBorder(PdfPCell.NO_BORDER);
            table.addCell(cell);
        }
        document.add(table);
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws IOException 
     * @throws DocumentException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new MovieSlideShow().createPdf(RESULT);
    }
}
AlternatingBackground.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class AlternatingBackground : IWriter, IPdfPTableEvent {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4.Rotate())) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        List<string> days = PojoFactory.GetDays();
        IPdfPTableEvent Pevent = new AlternatingBackground();
        foreach (string day in days) {
          PdfPTable table = GetTable(day);
          table.TableEvent = Pevent;
          document.Add(table);
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a table with film festival screenings.
     * @param day a film festival day
     * @return a table with screenings.
     */
    public PdfPTable GetTable(string day) {
      PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1 });
      table.WidthPercentage = 100f;
      table.DefaultCell.Padding = 3;
      table.DefaultCell.UseAscender = true;
      table.DefaultCell.UseDescender = true;
      table.DefaultCell.Colspan = 5;
      table.DefaultCell.BackgroundColor = BaseColor.RED;
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
      table.AddCell(day);
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT;
      table.DefaultCell.Colspan = 1;
      table.DefaultCell.BackgroundColor = BaseColor.ORANGE;
      for (int i = 0; i < 2; i++) {
        table.AddCell("Location");
        table.AddCell("Time");
        table.AddCell("Run Length");
        table.AddCell("Title");
        table.AddCell("Year");
      }
      table.DefaultCell.BackgroundColor = null;
      table.HeaderRows = 3;
      table.FooterRows = 1;
      List<Screening> screenings = PojoFactory.GetScreenings(day);
      Movie movie;
      foreach (Screening screening in screenings) {
        movie = screening.movie;
        table.AddCell(screening.Location);
        table.AddCell(screening.Time.Substring(0, 5));
        table.AddCell(movie.Duration.ToString() + " '");
        table.AddCell(movie.MovieTitle);
        table.AddCell(movie.Year.ToString());
      }
      return table;
    }
// ---------------------------------------------------------------------------
    /**
     * Draws a background for every other row.
     * @see com.itextpdf.text.pdf.PdfPTableEvent#tableLayout(
     *      com.itextpdf.text.pdf.PdfPTable, float[][], float[], int, int,
     *      com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void TableLayout(
      PdfPTable table, float[][] widths, float[] heights,
      int headerRows, int rowStart, PdfContentByte[] canvases
    ) {
      int columns;
      Rectangle rect;
      int footer = widths.Length - table.FooterRows;
      int header = table.HeaderRows - table.FooterRows + 1;
      for (int row = header; row < footer; row += 2) {
        columns = widths[row].Length - 1;
        rect = new Rectangle(
          widths[row][0], heights[row],
          widths[row][columns], heights[row + 1]
        );
        rect.BackgroundColor = BaseColor.YELLOW;
        rect.Border = Rectangle.NO_BORDER;
        canvases[PdfPTable.BASECANVAS].Rectangle(rect);
      }
    }    
// ===========================================================================
  }
}
RunLengthEvent.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class RunLengthEvent : IWriter {
// ===========================================================================
    /** Inner class to draw a bar inside a cell. */
    class RunLength : IPdfPCellEvent {
      public int duration;
      
      public RunLength(int duration) {
        this.duration = duration;
      }
      
      /**
       * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(
       *      com.lowagie.text.pdf.PdfPCell, com.lowagie.text.Rectangle,
       *      com.lowagie.text.pdf.PdfContentByte[])
       */
      public void CellLayout(
        PdfPCell cell, Rectangle rect, PdfContentByte[] canvas
      ) {
        PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
        cb.SaveState();
        if (duration < 90) {
          cb.SetRGBColorFill(0x7C, 0xFC, 0x00);
        }
        else if (duration > 120) {
          cb.SetRGBColorFill(0x8B, 0x00, 0x00);
        } 
        else {
          cb.SetRGBColorFill(0xFF, 0xA5, 0x00);
        }
        cb.Rectangle(
          rect.Left, rect.Bottom, 
          rect.Width * duration / 240, rect.Height
        );
        cb.Fill();
        cb.RestoreState();
      }
    }
/*
 * end inner class
*/ 
    /** Inner class to add the words PRESS PREVIEW to a cell. */
    class PressPreview : IPdfPCellEvent {
      public BaseFont bf;
      public PressPreview() {
        bf = BaseFont.CreateFont();
      }
      
      /**
       * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(com.lowagie.text.pdf.PdfPCell,
       *      com.lowagie.text.Rectangle,
       *      com.lowagie.text.pdf.PdfContentByte[])
       */
      public void CellLayout(
        PdfPCell cell, Rectangle rect, PdfContentByte[] canvas
      ) {
        PdfContentByte cb = canvas[PdfPTable.TEXTCANVAS];
        cb.BeginText();
        cb.SetFontAndSize(bf, 12);
        cb.ShowTextAligned(
          Element.ALIGN_RIGHT, "PRESS PREVIEW",
          rect.Right - 3,
          rect.Bottom + 4.5f, 0
        );
        cb.EndText();
      }
    }
/*
 * end inner class
*/  
// ---------------------------------------------------------------------------
    /** The press cell event. */
    public IPdfPCellEvent press;
    public void Write(Stream stream) {
      press = new PressPreview();
      // step 1
      using (Document document = new Document(PageSize.A4.Rotate())) {
        // step 2
        PdfWriter.GetInstance(document, stream);      
        // step 3
        document.Open();
        // step 4
        List<string> days = PojoFactory.GetDays();
        foreach (string day in days) {
          document.Add(GetTable(day));
          document.NewPage();
        }        
      }
    }
// ---------------------------------------------------------------------------
    /**
     * @param connection
     * @param day
     * @return
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable GetTable(string day) {
      PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1 });
      table.WidthPercentage = 100f;
      table.DefaultCell.Padding = 3;
      table.DefaultCell.UseAscender = true;
      table.DefaultCell.UseDescender = true;
      table.DefaultCell.Colspan = 5;
      table.DefaultCell.BackgroundColor = BaseColor.RED;
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
      table.AddCell(day);
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT;
      table.DefaultCell.Colspan = 1;
      table.DefaultCell.BackgroundColor = BaseColor.YELLOW;
      for (int i = 0; i < 2; i++) {
        table.AddCell("Location");
        table.AddCell("Time");
        table.AddCell("Run Length");
        table.AddCell("Title");
        table.AddCell("Year");
      }
      table.DefaultCell.BackgroundColor = null;
      table.HeaderRows = 3;
      table.FooterRows = 1;
      List<Screening> screenings = PojoFactory.GetScreenings(day);
      Movie movie;
      PdfPCell runLength;
      foreach (Screening screening in screenings) {
        movie = screening.movie;
        table.AddCell(screening.Location);
        table.AddCell(screening.Time.Substring(0, 5));
        runLength = new PdfPCell(table.DefaultCell);
        runLength.Phrase = new Phrase(String.Format(
          "{0} '", movie.Duration
        ));
        runLength.CellEvent = new RunLength(movie.Duration);
        if (screening.Press) {
          runLength.CellEvent = press;
        }
        table.AddCell(runLength);
        table.AddCell(movie.MovieTitle);
        table.AddCell(movie.Year.ToString());
      }
      return table;
    }
// ===========================================================================
  }
}
PressPreviews.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class PressPreviews : IWriter, IPdfPCellEvent, IPdfPTableEvent {
// ===========================================================================
    /**
     * @see com.itextpdf.text.pdf.PdfPTableEvent#tableLayout(com.itextpdf.text.pdf.PdfPTable,
     *      float[][], float[], int, int, com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void TableLayout(
      PdfPTable table, float[][] width, float[] height,
      int headerRows, int rowStart, PdfContentByte[] canvas
    ) {
      float[] widths = width[0];
      float x1 = widths[0];
      float x2 = widths[widths.Length - 1];
      float y1 = height[0];
      float y2 = height[height.Length - 1];
      PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
      cb.Rectangle(x1, y1, x2 - x1, y2 - y1);
      cb.Stroke();
      cb.ResetRGBColorStroke();
    }
 
    /**
     * @see com.lowagie.text.pdf.PdfPCellEvent#cellLayout(com.lowagie.text.pdf.PdfPCell,
     *      com.lowagie.text.Rectangle, com.lowagie.text.pdf.PdfContentByte[])
     */
    public void CellLayout(
      PdfPCell cell, Rectangle position, PdfContentByte[] canvases
    ) {
      float x1 = position.Left + 2;
      float x2 = position.Right - 2;
      float y1 = position.Top - 2;
      float y2 = position.Bottom + 2;
      PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
      canvas.Rectangle(x1, y1, x2 - x1, y2 - y1);
      canvas.Stroke();
      canvas.ResetRGBColorStroke();
    }
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4.Rotate())) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(GetTable()); 
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a table that mimics cellspacing using table and cell events.
     * @param connection
     * @return a table
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable GetTable() {
      PdfPTable table = new PdfPTable(new float[] { 1, 2, 2, 5, 1 });
      table.TableEvent = new PressPreviews();
      table.WidthPercentage = 100f;
      table.DefaultCell.Padding = 5;
      table.DefaultCell.Border = PdfPCell.NO_BORDER;
      table.DefaultCell.CellEvent = new PressPreviews();
      for (int i = 0; i < 2; i++) {
        table.AddCell("Location");
        table.AddCell("Date/Time");
        table.AddCell("Run Length");
        table.AddCell("Title");
        table.AddCell("Year");
      }
      table.DefaultCell.BackgroundColor = null;
      table.HeaderRows = 2;
      table.FooterRows = 1;
      List<Screening> screenings = PojoFactory.GetPressPreviews();
      foreach (Screening screening in screenings) {
        Movie movie = screening.movie;
        table.AddCell(screening.Location);
        table.AddCell(String.Format(
          "{0}   {1}", screening.Date, 
          screening.Time.Substring(0, 5)
        ));
        table.AddCell(String.Format("{0} '", movie.Duration));
        table.AddCell(movie.MovieTitle);
        table.AddCell(movie.Year.ToString());
      }
      return table;
    }    
// ===========================================================================
  }
}
PdfCalendar.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO; 
using System.Globalization; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.draw;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class PdfCalendar : kuujinbo.iTextInAction2Ed.Chapter04.PdfCalendar {
// ===========================================================================
    /** A table event. */
    public IPdfPTableEvent tableBackground;
    /** A cell event. */
    public IPdfPCellEvent cellBackground;
    /** A cell event. */
    public IPdfPCellEvent roundRectangle;
    /** A cell event. */
    public IPdfPCellEvent whiteRectangle;
    /**
     * Inner class with a table event that draws a background with rounded corners.
     */
    class TableBackground : IPdfPTableEvent {
      public void TableLayout(
        PdfPTable table, float[][] width, float[] height,
        int headerRows, int rowStart, PdfContentByte[] canvas
      ) {
        PdfContentByte background = canvas[PdfPTable.BASECANVAS];
        background.SaveState();
        background.SetCMYKColorFill(0x00, 0x00, 0xFF, 0x0F);
        background.RoundRectangle(
          width[0][0], height[height.Length - 1] - 2,
          width[0][1] - width[0][0] + 6, 
          height[0] - height[height.Length - 1] - 4, 4
        );
        background.Fill();
        background.RestoreState();
      }
    }
/*
 * end inner class
*/     
    /**
     * Inner class with a cell event that draws a background with rounded corners.
     */
    class CellBackground : IPdfPCellEvent {
      public void CellLayout(
        PdfPCell cell, Rectangle rect, PdfContentByte[] canvas
    ) {
        PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
        cb.RoundRectangle(
          rect.Left + 1.5f, 
          rect.Bottom + 1.5f, 
          rect.Width - 3,
          rect.Height - 3, 4
        );
        cb.SetCMYKColorFill(0x00, 0x00, 0x00, 0x00);
        cb.Fill();
      }
    }
/*
 * end inner class
*/ 
    /**
     * Inner class with a cell event that draws a border with rounded corners.
     */
    class RoundRectangle : IPdfPCellEvent {
      /** the border color described as CMYK values. */
      protected int[] color;
      /** Constructs the event using a certain color. */
      public RoundRectangle(int[] color) {
        this.color = color;
      }
      
      public void CellLayout(
        PdfPCell cell, Rectangle rect, PdfContentByte[] canvas
      ) {
        PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
        cb.RoundRectangle(
          rect.Left + 1.5f, 
          rect.Bottom + 1.5f, 
          rect.Width - 3,
          rect.Height - 3, 4
        );
        cb.SetLineWidth(1.5f);
        cb.SetCMYKColorStrokeF(color[0], color[1], color[2], color[3]);
        cb.Stroke();
      }
    }
/*
 * end inner class
*/ 
// ---------------------------------------------------------------------------
    /**
     * Initializes the fonts and collections.
     */
    public PdfCalendar() : base() {
      tableBackground = new TableBackground();
      cellBackground = new CellBackground();
      roundRectangle = new RoundRectangle(new int[]{ 0xFF, 0x00, 0xFF, 0x00 });
      whiteRectangle = new RoundRectangle(new int[]{ 0x00, 0x00, 0x00, 0x00 });
    }
 
    public override void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4.Rotate())) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        // "en" => System.Globalization.GregorianCalendar 
        Calendar calendar = new CultureInfo(LANGUAGE, false).Calendar;
        PdfPTable table;
        PdfContentByte canvas = writer.DirectContent;
        // Loop over the months
        for (int month = 0; month < 12; month++) {
          int current_month = month + 1;
          DateTime dt = new DateTime(YEAR, current_month, 1, calendar);
          // draw the background
          DrawImageAndText(canvas, dt);
          // create a table with 7 columns
          table = new PdfPTable(7);
          table.TableEvent = tableBackground;
          table.TotalWidth = 504;
          // add the name of the month
          table.DefaultCell.Border  = PdfPCell.NO_BORDER;
          table.DefaultCell.CellEvent = whiteRectangle;
          table.AddCell(GetMonthCell(dt));
          int daysInMonth = DateTime.DaysInMonth(YEAR, dt.Month);
          int day = 1;
          // add empty cells
          // SUNDAY; Java => 1, .NET => 0
          int position = 0;
          while (position++ != (int) dt.DayOfWeek) {
            table.AddCell("");
          }
          // add cells for each day
          while (day <= daysInMonth) {
            dt = new DateTime(YEAR, current_month, day++, calendar);
            table.AddCell(GetDayCell(dt));
          }          
          // complete the table
          table.CompleteRow();
          // write the table to an absolute position
          table.WriteSelectedRows(0, -1, 169, table.TotalHeight + 20, canvas);
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a PdfPCell with the name of the month
     * @param dt a DateTime
     * @return a PdfPCell with rowspan 7, containing the name of the month
     */
    public new PdfPCell GetMonthCell(DateTime dt) {
      PdfPCell cell = new PdfPCell();
      cell.Colspan = 7;
      cell.Border = PdfPCell.NO_BORDER;
      cell.UseDescender = true;
      Paragraph p = new Paragraph(dt.ToString("MMMM yyyy"), bold);
      p.Alignment = Element.ALIGN_CENTER;
      cell.AddElement(p);
      return cell;
    }
 
    /**
     * Creates a PdfPCell for a specific day
     * @param dt a DateTime
     * @return a PdfPCell
     */
    public new PdfPCell GetDayCell(DateTime dt) {
      PdfPCell cell = new PdfPCell();
      // set the event to draw the background
      cell.CellEvent = cellBackground;
      // set the event to draw a special border
      if (IsSunday(dt) || IsSpecialDay(dt))
          cell.CellEvent = roundRectangle;
      cell.Padding = 3;
      cell.Border = PdfPCell.NO_BORDER;
      // set the content in the language of the locale
      Chunk chunk = new Chunk(dt.ToString("ddd"), small);
      chunk.SetTextRise(8);
      // a paragraph with the day
      Paragraph p = new Paragraph(chunk);
      // a separator
      p.Add(new Chunk(new VerticalPositionMark()));
      // and the number of the day
      p.Add(new Chunk(dt.ToString("%d"), normal));
      cell.AddElement(p);
      return cell;
    }
    
    /**
     * Returns true if the date was found in a list with special days (holidays).
     * @param dt a DateTime
     * @return true for holidays
     */
    public new bool IsSpecialDay(DateTime dt) {
      return specialDays.ContainsKey(dt.ToString("MMdd"))
          ? true: false;
    }    
// ===========================================================================
  }
}
MovieYears.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieYears : IWriter {
// ===========================================================================
    /**
     * Inner class to add functionality to a Chunk in a generic way.
     */
    class GenericTags : PdfPageEventHelper {
      public override void OnGenericTag(
        PdfWriter writer, Document pdfDocument, Rectangle rect, String text
    ) {
        if ("strip".Equals(text)) {
          Strip(writer.DirectContent, rect);
        }
        else if ("ellipse".Equals(text)) {
          Ellipse(writer.DirectContentUnder, rect);
        }
        else {
          CountYear(text);
        }
      }
 
      public void Strip(PdfContentByte content, Rectangle rect) {
        content.Rectangle(
          rect.Left - 1, rect.Bottom - 5f,
          rect.Width, rect.Height + 8
        );
        content.Rectangle(
          rect.Left, rect.Bottom - 2,
          rect.Width - 2, rect.Height + 2
        );
        float y1 = rect.Top + 0.5f;
        float y2 = rect.Bottom - 4;
        for (float f = rect.Left; f < rect.Right - 4; f += 5) {
          content.Rectangle(f, y1, 4f, 1.5f);
          content.Rectangle(f, y2, 4f, 1.5f);
        }
        content.EoFill();
      }
      
      public void Ellipse(PdfContentByte content, Rectangle rect) {
        content.SaveState();
        content.SetRGBColorFill(0x00, 0x00, 0xFF);
        content.Ellipse(
          rect.Left - 3f, rect.Bottom - 5f,
          rect.Right + 3f, rect.Top + 3f
        );
        content.Fill();
        content.RestoreState();
      }
 
      internal SortedDictionary<string, int> years = new SortedDictionary<string, int>();
      
      public void CountYear(String text) {
        if ( years.ContainsKey(text) ) {
          ++years[text];
        }
        else {
          years.Add(text, 1);
        }
      }
    }
/*
 * end inner class
*/    
    /**
     * Inner class to add lines when a paragraph begins and ends.
     */
    class ParagraphPositions : PdfPageEventHelper {
      public override void OnParagraph(
          PdfWriter writer, Document pdfDocument, float paragraphPosition
      ) {
        DrawLine(
          writer.DirectContent, pdfDocument.Left, 
          pdfDocument.Right, paragraphPosition - 8
        );
      }
 
      public override void OnParagraphEnd(
          PdfWriter writer, Document pdfDocument, float paragraphPosition
      ) {
          DrawLine(
            writer.DirectContent, pdfDocument.Left, 
            pdfDocument.Right, paragraphPosition - 5
          );
      }
      
      public void DrawLine(PdfContentByte cb, float x1, float x2, float y) {
        cb.MoveTo(x1, y);
        cb.LineTo(x2, y);
        cb.Stroke();
      }
    }
/*
 * end inner class
*/
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
      // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        GenericTags gevent = new GenericTags();
        writer.PageEvent = gevent;
        writer.PageEvent = new ParagraphPositions();       
        // step 3
        document.Open();
        // step 4
        Font bold = new Font(Font.FontFamily.HELVETICA, 11, Font.BOLD);
        Font italic = new Font(Font.FontFamily.HELVETICA, 11, Font.ITALIC);
        Font white = new Font(
          Font.FontFamily.HELVETICA, 12, 
          Font.BOLD | Font.ITALIC, 
          BaseColor.WHITE
        );
        Paragraph p;
        Chunk c;        
        foreach (Movie movie in PojoFactory.GetMovies(true)) {
            p = new Paragraph(22);
            c = new Chunk(String.Format("{0} ", movie.Year), bold);
            c.SetGenericTag("strip");
            p.Add(c);
            c = new Chunk(movie.MovieTitle);
            c.SetGenericTag(movie.Year.ToString());
            p.Add(c);
            c = new Chunk(
              String.Format(" ({0} minutes)  ", movie.Duration), 
              italic
            );
            p.Add(c);
            c = new Chunk("IMDB", white);
            c.SetAnchor("http://www.imdb.com/title/tt" + movie.Imdb);
            c.SetGenericTag("ellipse");
            p.Add(c);
            document.Add(p);
        }
        document.NewPage();
        writer.PageEvent = null;
        foreach (string entry in gevent.years.Keys) {
          p = new Paragraph(String.Format(
            "{0}: {1} movie(s)", entry, gevent.years[entry]
          ));
          document.Add(p);
        }
      }
    }
// ===========================================================================
  }
}
MovieHistory1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieHistory1 : IWriter {
// ===========================================================================
    /**
     * Inner class to keep track of the TOC
     * and to draw lines under ever chapter and section.
     */
    class ChapterSectionTOC : PdfPageEventHelper {
      private MovieHistory1 mh1;
      public ChapterSectionTOC(MovieHistory1 mh1) {
        this.mh1 = mh1;
      }
    
      /** List with the titles. */
      public List<Paragraph> titles = new List<Paragraph>();
      
      public override void OnChapter(PdfWriter writer, Document document,
              float position, Paragraph title) 
      {
        titles.Add(new Paragraph(title.Content, mh1.FONT[4]));
      }
 
      public override void OnChapterEnd(
        PdfWriter writer, Document document,
        float position) 
      {
        DrawLine(
          writer.DirectContent, document.Left, document.Right, position - 5
        );
      }
 
      public override void OnSection(
        PdfWriter writer, Document document,
        float position, int depth, Paragraph title) 
      {
          title = new Paragraph(title.Content, mh1.FONT[4]);
          title.IndentationLeft = 18 * depth;
          titles.Add(title);
      }
 
      public override void OnSectionEnd(
        PdfWriter writer, Document document, float position
        ) 
      {
        DrawLine(
          writer.DirectContent, document.Left, document.Right, position - 3
        );
      }
      
      public void DrawLine(
        PdfContentByte cb, float x1, float x2, float y
        ) 
      {
        cb.MoveTo(x1, y);
        cb.LineTo(x2, y);
        cb.Stroke();
      }
    }
    // end inner class
// ---------------------------------------------------------------------------
    
    /** The different epochs. */
    public readonly string[] EPOCH = { 
      "Forties", "Fifties", "Sixties", "Seventies", "Eighties",
    "Nineties", "Twenty-first Century" 
    };
    /** The fonts for the title. */
    public Font[] FONT = new Font[5];
    
    public MovieHistory1() {
      FONT[0] = new Font(Font.FontFamily.HELVETICA, 24);
      FONT[1] = new Font(Font.FontFamily.HELVETICA, 18);
      FONT[2] = new Font(Font.FontFamily.HELVETICA, 14);
      FONT[3] = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD);
      FONT[4] = new Font(Font.FontFamily.HELVETICA, 10);
    }
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // IMPORTANT: set linear page mode!
        writer.SetLinearPageMode();
        ChapterSectionTOC tevent = new ChapterSectionTOC(new MovieHistory1());
        writer.PageEvent = tevent;        
        // step 3
        document.Open();
        // step 4
        int epoch = -1;
        int currentYear = 0;
        Paragraph title = null;
        Chapter chapter = null;
        Section section = null;
        Section subsection = null;
        // add the chapters, sort by year
        foreach (Movie movie in PojoFactory.GetMovies(true)) {
          int year = movie.Year;
          if (epoch < (year - 1940) / 10) {
            epoch = (year - 1940) / 10;
            if (chapter != null) {
              document.Add(chapter);
            }
            title = new Paragraph(EPOCH[epoch], FONT[0]);
            chapter = new Chapter(title, epoch + 1);
          }
          if (currentYear < year) {
            currentYear = year;
            title = new Paragraph(
              String.Format("The year {0}", year), FONT[1]
            );
            section = chapter.AddSection(title);
            section.BookmarkTitle = year.ToString();
            section.Indentation = 30;
            section.BookmarkOpen = false;
            section.NumberStyle = Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT;
            section.Add(new Paragraph(
              String.Format("Movies from the year {0}:", year))
            );
          }
          title = new Paragraph(movie.MovieTitle, FONT[2]);
          subsection = section.AddSection(title);
          subsection.IndentationLeft = 20;
          subsection.NumberDepth = 1;
          subsection.Add(new Paragraph(
            "Duration: " + movie.Duration.ToString(), FONT[3]
          ));
          subsection.Add(new Paragraph("Director(s):", FONT[3]));
          subsection.Add(PojoToElementFactory.GetDirectorList(movie));
          subsection.Add(new Paragraph("Countries:", FONT[3]));
          subsection.Add(PojoToElementFactory.GetCountryList(movie));
        }      
        document.Add(chapter);
        // add the TOC starting on the next page
        document.NewPage();
        int toc = writer.PageNumber;
        foreach (Paragraph p in tevent.titles) {
          document.Add(p);
        }
        // always go to a new page before reordering pages.
        document.NewPage();
        // get the total number of pages that needs to be reordered
        int total = writer.ReorderPages(null);
        // change the order
        int[] order = new int[total];
        for (int i = 0; i < total; i++) {
          order[i] = i + toc;
          if (order[i] > total) {
            order[i] -= total;
          }
        }
        // apply the new order
        writer.ReorderPages(order);        
      }
    }
// ===========================================================================
  }
}
NewPage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class NewPage : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(new Paragraph("This page will NOT be followed by a blank page!"));
        document.NewPage();
        // we don't add anything to this page: newPage() will be ignored
        document.NewPage();
        document.Add(new Paragraph("This page will be followed by a blank page!"));
        document.NewPage();
        writer.PageEmpty = false;
        document.NewPage();
        document.Add(new Paragraph("The previous page was a blank page!"));
      }
    }
// ===========================================================================
  }
}
Hero1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class Hero1 : IWriter {
// ===========================================================================
    public virtual void Write(Stream stream) {
      // step 1
      Rectangle rect = new Rectangle(-1192, -1685, 1192, 1685);
      using (Document document = new Document(rect)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfContentByte content = writer.DirectContent;
        PdfTemplate template = CreateTemplate(content, rect, 4);
        content.AddTemplate(template, -1192, -1685);
        content.MoveTo(-595, 0);
        content.LineTo(595, 0);
        content.MoveTo(0, -842);
        content.LineTo(0, 842);
        content.Stroke();
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a template based on a stream of PDF syntax.
     * @param content The direct content
     * @param rect The dimension of the templare
     * @param factor A magnification factor
     * @return A PdfTemplate
     */
    public virtual PdfTemplate CreateTemplate(
      PdfContentByte content, Rectangle rect, int factor)
    {
      PdfTemplate template = content.CreateTemplate(rect.Width, rect.Height);
      template.ConcatCTM(factor, 0, 0, factor, 0, 0);
      string hero = Path.Combine(Utility.ResourceText, "hero.txt");
      if (!File.Exists(hero)) {
        throw new ArgumentException(hero + " NOT FOUND!");  
      }    
      var fi = new FileInfo(hero);
      using ( var sr = fi.OpenText() ) {
        while (sr.Peek() >= 0) {
          template.SetLiteral((char) sr.Read());
        }
      }
      return template;
    }    
// ===========================================================================
  }
}
Hero2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class Hero2 : Hero1 {
// ===========================================================================
    public override void Write(Stream stream) {
      float w = PageSize.A4.Width;
      float h = PageSize.A4.Height;
      Rectangle rect = new Rectangle(-2*w, -2*h, 2*w, 2*h);
      Rectangle crop = new Rectangle(-2 * w, h, -w, 2 * h);      
      // step 1
      using (Document document = new Document(rect)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.CropBoxSize = crop;
        // step 3
        document.Open();
        // step 4
        PdfContentByte content = writer.DirectContent;
        PdfTemplate template = CreateTemplate(content, rect, 4);
        float adjust;
        while(true) {
          content.AddTemplate(template, -2*w, -2*h);
          adjust = crop.Right + w;
          if (adjust > 2 * w) {
            adjust = crop.Bottom - h;
            if (adjust < - 2 * h)
                break;
            crop = new Rectangle(-2*w, adjust, -w, crop.Bottom);
          }
          else {
            crop = new Rectangle(crop.Right, crop.Bottom, adjust, crop.Top);
          }
          writer.CropBoxSize = crop;
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a template based on a stream of PDF syntax.
     * @param content The direct content
     * @param rect The dimension of the templare
     * @param factor A magnification factor
     * @return A PdfTemplate
     */
    public override  PdfTemplate CreateTemplate(
      PdfContentByte content, Rectangle rect, int factor
    )
    {
      PdfTemplate template = content.CreateTemplate(rect.Width, rect.Height);
      template.ConcatCTM(factor, 0, 0, factor, 0, 0);
      string hero = Path.Combine(Utility.ResourceText, "hero.txt");
      if (!File.Exists(hero)) {
        throw new ArgumentException(hero + " NOT FOUND!");
      }   
      var fi = new FileInfo(hero);
      using ( var sr = fi.OpenText() ) {
        while (sr.Peek() >= 0) {
          template.SetLiteral((char) sr.Read());
        }
      }
      return template;
    }    
// ===========================================================================
  }
}
Hero3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class Hero3 : Hero1 {
// ===========================================================================
    public override void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        Rectangle art = new Rectangle(50, 50, 545, 792);
        writer.SetBoxSize("art", art);        
        // step 3
        document.Open();
        // step 4
        PdfContentByte content = writer.DirectContent;
        PdfTemplate template = CreateTemplate(content, PageSize.A4, 1);
        content.AddTemplate(template, 0, 0);
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a template based on a stream of PDF syntax.
     * @param content The direct content
     * @param rect The dimension of the templare
     * @param factor A magnification factor
     * @return A PdfTemplate
     */
    public override PdfTemplate CreateTemplate(
      PdfContentByte content, Rectangle rect, int factor
    )
    {
      PdfTemplate template = content.CreateTemplate(rect.Width, rect.Height);
      template.ConcatCTM(factor, 0, 0, factor, 0, 0);
      string hero = Path.Combine(Utility.ResourceText, "hero.txt");
      if (!File.Exists(hero)) {
        throw new ArgumentException(hero + " NOT FOUND!");      
      }
      var fi = new FileInfo(hero);
      using ( StreamReader sr = fi.OpenText() ) {
        while (sr.Peek() >= 0) {
          template.SetLiteral((char) sr.Read());
        }
      }
      return template;
    }    
// ===========================================================================
  }
}
MovieHistory2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieHistory2 : IWriter {
// ===========================================================================
    /** Inner class to add a header and a footer. */
    class HeaderFooter : PdfPageEventHelper {
      /** Alternating phrase for the header. */
      Phrase[] header = new Phrase[2];
      /** Current page number (will be reset for every chapter). */
      int pagenumber;
      
      /**
       * Initialize one of the headers.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnOpenDocument(PdfWriter writer, Document document) {
        header[0] = new Phrase("Movie history");
      }
      
      /**
       * Initialize one of the headers, based on the chapter title;
       * reset the page number.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onChapter(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document, float,
       *      com.itextpdf.text.Paragraph)
       */
      public override void OnChapter(
        PdfWriter writer, Document document,
        float paragraphPosition, Paragraph title) 
      {
        header[1] = new Phrase(title.Content);
        pagenumber = 1;
      }
 
      /**
       * Increase the page number.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnStartPage(PdfWriter writer, Document document) {
        pagenumber++;
      }
        
      /**
       * Adds the header and the footer.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnEndPage(PdfWriter writer, Document document) {
        Rectangle rect = writer.GetBoxSize("art");
        switch(writer.PageNumber % 2) {
        case 0:
          ColumnText.ShowTextAligned(writer.DirectContent,
            Element.ALIGN_RIGHT, 
            header[0],
            rect.Right, rect.Top, 0
          );
          break;
        case 1:
          ColumnText.ShowTextAligned(
            writer.DirectContent,
            Element.ALIGN_LEFT,
            header[1],
            rect.Left, rect.Top, 0
          );
          break;
        }
        ColumnText.ShowTextAligned(
          writer.DirectContent,
          Element.ALIGN_CENTER, 
          new Phrase(String.Format("page {0}", pagenumber)),
          (rect.Left + rect.Right) / 2, 
          rect.Bottom - 18, 0
        );
      }
    }
    // end inner class
// ---------------------------------------------------------------------------
    /** The different epochs. */
    public readonly string[] EPOCH = { 
      "Forties", "Fifties", "Sixties", "Seventies", "Eighties",
    "Nineties", "Twenty-first Century" 
    };
    /** The fonts for the title. */
    public Font[] FONT = new Font[5];
    
    public MovieHistory2() {
      FONT[0] = new Font(Font.FontFamily.HELVETICA, 24);
      FONT[1] = new Font(Font.FontFamily.HELVETICA, 18);
      FONT[2] = new Font(Font.FontFamily.HELVETICA, 14);
      FONT[3] = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD);
      FONT[4] = new Font(Font.FontFamily.HELVETICA, 10);
    }
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4, 36, 36, 54, 54)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        HeaderFooter tevent = new HeaderFooter();
        writer.SetBoxSize("art", new Rectangle(36, 54, 559, 788));
        writer.PageEvent = tevent;
        // step 3
        document.Open();
        // step 4
        int epoch = -1;
        int currentYear = 0;
        Paragraph title = null;
        Chapter chapter = null;
        Section section = null;
        Section subsection = null;
        // add the chapters, sort by year
        foreach (Movie movie in PojoFactory.GetMovies(true)) {
          int year = movie.Year;
          if (epoch < (year - 1940) / 10) {
            epoch = (year - 1940) / 10;
            if (chapter != null) {
              document.Add(chapter);
            }
            title = new Paragraph(EPOCH[epoch], FONT[0]);
            chapter = new Chapter(title, epoch + 1);
          }
          if (currentYear < year) {
            currentYear = year;
            title = new Paragraph(
              String.Format("The year {0}", year), FONT[1]
            );
            section = chapter.AddSection(title);
            section.BookmarkTitle = year.ToString();
            section.Indentation = 30;
            section.BookmarkOpen = false;
            section.NumberStyle = Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT;
            section.Add(new Paragraph(
              String.Format("Movies from the year {0}:", year))
            );
          }
          title = new Paragraph(movie.MovieTitle, FONT[2]);
          subsection = section.AddSection(title);
          subsection.IndentationLeft = 20;
          subsection.NumberDepth = 1;
          subsection.Add(new Paragraph(
            "Duration: " + movie.Duration.ToString(), FONT[3]
          ));
          subsection.Add(new Paragraph("Director(s):", FONT[3]));
          subsection.Add(PojoToElementFactory.GetDirectorList(movie));
          subsection.Add(new Paragraph("Countries:", FONT[3]));
          subsection.Add(PojoToElementFactory.GetCountryList(movie));
        }      
        document.Add(chapter);
      }
    }
// ===========================================================================
  }
}
MovieCountries1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieCountries1 : IWriter {
// ===========================================================================
    /**
     * Inner class to add a table as header.
     */
    protected class TableHeader : PdfPageEventHelper {
      /** The template with the total number of pages. */
      PdfTemplate total;
      
      /** The header text. */
      public string Header { get; set; }
 
      /**
       * Creates the PdfTemplate that will hold the total number of pages.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnOpenDocument(PdfWriter writer, Document document) {
        total = writer.DirectContent.CreateTemplate(30, 16);
      }
      
      /**
       * Adds a header to every page
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnEndPage(PdfWriter writer, Document document) {
        PdfPTable table = new PdfPTable(3);
        try {
          table.SetWidths(new int[]{24, 24, 2});
          table.TotalWidth = 527;
          table.LockedWidth = true;
          table.DefaultCell.FixedHeight = 20;
          table.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
          table.AddCell(Header);
          table.DefaultCell.HorizontalAlignment = Element.ALIGN_RIGHT;
          table.AddCell(string.Format("Page {0} of", writer.PageNumber));
          PdfPCell cell = new PdfPCell(Image.GetInstance(total));
          cell.Border = Rectangle.BOTTOM_BORDER;
          table.AddCell(cell);
          table.WriteSelectedRows(0, -1, 34, 803, writer.DirectContent);
        }
        catch(DocumentException de) {
          throw de;
        }
      }
      
      /**
       * Fills out the total number of pages before the document is closed.
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnCloseDocument(PdfWriter writer, Document document) {
        ColumnText.ShowTextAligned(
          total, Element.ALIGN_LEFT,
/*
 * NewPage() already called when closing the document; subtract 1
*/
          new Phrase((writer.PageNumber - 1).ToString()),
          2, 2, 0
        );
      }
    }
// ---------------------------------------------------------------------------
    protected readonly string SQL = 
@"SELECT country, id FROM film_country 
ORDER BY country
"; 
    public virtual void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4, 36, 36, 54, 36)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        TableHeader tevent = new TableHeader();
        writer.PageEvent = tevent;
        // step 3
        document.Open();
        // step 4       
        using (var c =  AdoDB.Provider.CreateConnection()) {
          c.ConnectionString = AdoDB.CS;
          using (DbCommand cmd = c.CreateCommand()) {
            cmd.CommandText = SQL;        
            c.Open();
            using (var r = cmd.ExecuteReader()) {
              while (r.Read()) {
                tevent.Header = r["country"].ToString();
                // LINQ allows us to sort on any movie object property inline;
                // let's sort by Movie.Year, Movie.Title
                var by_year = from m in PojoFactory.GetMovies(
                  r["id"].ToString()
                )
                  orderby m.Year, m.Title
                  select m
                ;                
                foreach (Movie movie in by_year) {
                  document.Add(new Paragraph(
                    movie.MovieTitle, FilmFonts.BOLD
                  ));
                  if (!string.IsNullOrEmpty(movie.OriginalTitle)) document.Add(
                    new Paragraph(movie.OriginalTitle, FilmFonts.ITALIC)
                  );
                  document.Add(new Paragraph(
                    String.Format("Year: {0}; run length: {1} minutes",
                      movie.Year, movie.Duration
                    ), FilmFonts.NORMAL
                  ));
                  document.Add(PojoToElementFactory.GetDirectorList(movie));
                }
                document.NewPage();              
              }      
            }
          }
        }
      }
    }    
// ===========================================================================
  }
}
MovieCountries2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieCountries2 : MovieCountries1 {
// ===========================================================================
    /**
     * Inner class to add a watermark to every page.
     */
    class Watermark : PdfPageEventHelper {
      Font FONT = new Font(Font.FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));
      
      public override void OnEndPage(PdfWriter writer, Document document) {
        ColumnText.ShowTextAligned(
          writer.DirectContentUnder,
          Element.ALIGN_CENTER, new Phrase("FOOBAR FILM FESTIVAL", FONT),
          297.5f, 421, writer.PageNumber % 2 == 1 ? 45 : -45
        );
      }
    }
// ---------------------------------------------------------------------------
    public override void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4, 36, 36, 54, 36)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        TableHeader tevent = new TableHeader();
        writer.PageEvent = tevent;
        writer.PageEvent = new Watermark();
        // step 3
        document.Open();
        // step 4 
        using (var c =  AdoDB.Provider.CreateConnection()) {
          c.ConnectionString = AdoDB.CS;
          using (DbCommand cmd = c.CreateCommand()) {
            cmd.CommandText = SQL;        
            c.Open();
            using (var r = cmd.ExecuteReader()) {
              while (r.Read()) {
                tevent.Header = r["country"].ToString();
                foreach (Movie movie 
                  in PojoFactory.GetMovies(r["id"].ToString(), true)) 
                {
                  document.Add(new Paragraph(
                    movie.MovieTitle, FilmFonts.BOLD
                  ));
                  if (!string.IsNullOrEmpty(movie.OriginalTitle)) document.Add(
                    new Paragraph(movie.OriginalTitle, FilmFonts.ITALIC)
                  );
                  document.Add(new Paragraph(
                    String.Format("Year: {0}; run length: {1} minutes",
                      movie.Year, movie.Duration
                    ), FilmFonts.NORMAL
                  ));
                  document.Add(PojoToElementFactory.GetDirectorList(movie));
                }
                document.NewPage();              
              }      
            }
          }
        }
      }
    }    
// ===========================================================================
  }
}
MovieSlideShow.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter05 {
  public class MovieSlideShow : IWriter {
// ===========================================================================
    /**
     * Page event to set the transition and duration for every page.
     */
    class TransitionDuration : PdfPageEventHelper {
      public override void OnStartPage(PdfWriter writer, Document document) {
        writer.Transition = new PdfTransition(PdfTransition.DISSOLVE, 3);
        writer.Duration = 5;
      }
    }
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A5.Rotate())) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PdfVersion = PdfWriter.VERSION_1_5;
        writer.ViewerPreferences = PdfWriter.PageModeFullScreen;
        writer.PageEvent = new TransitionDuration();        
        // step 3
        document.Open();
        // step 4
        IEnumerable<Movie> movies = PojoFactory.GetMovies();
        Image img;
        PdfPCell cell;
        PdfPTable table = new PdfPTable(6);
        string RESOURCE = Utility.ResourcePosters;
        foreach (Movie movie in movies) {
          img = Image.GetInstance(Path.Combine(RESOURCE, movie.Imdb + ".jpg"));
          cell = new PdfPCell(img, true);
          cell.Border = PdfPCell.NO_BORDER;
          table.AddCell(cell);
        }
        document.Add(table);
      }
    }
// ===========================================================================
  }
}


Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now