Chapter 4: Organizing content in tables

This is a code example of iText PDF, discover more.

10th October 2015
admin-marketing

Switch code for this example

MyFirstTable.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class MyFirstTable {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/first_table.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new MyFirstTable().createPdf(RESULT);
    }
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        document.add(createFirstTable());
        // step 5
        document.close();
    }
    
    /**
     * Creates our first table
     * @return our first table
     */
    public static PdfPTable createFirstTable() {
    	// a table with three columns
        PdfPTable table = new PdfPTable(3);
        // the cell object
        PdfPCell cell;
        // we add a cell with colspan 3
        cell = new PdfPCell(new Phrase("Cell with colspan 3"));
        cell.setColspan(3);
        table.addCell(cell);
        // now we add a cell with rowspan 2
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        // we add the four remaining cells with addCell()
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }
}
ColumnWidths.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class ColumnWidths {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/column_widths.pdf";
    
    /**
     * Creates a PDF with five tables.
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfPTable table = createTable1();
        document.add(table);
        table = createTable2();
        table.setSpacingBefore(5);
        table.setSpacingAfter(5);
        document.add(table);
        table = createTable3();
        document.add(table);
        table = createTable4();
        table.setSpacingBefore(5);
        table.setSpacingAfter(5);
        document.add(table);
        table = createTable5();
        document.add(table);
        // step 5
        document.close();
    }
    
    /**
     * Creates a table; widths are set with setWidths().
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable createTable1() throws DocumentException {
        PdfPTable table = new PdfPTable(3);
        table.setWidthPercentage(288 / 5.23f);
        table.setWidths(new int[]{2, 1, 1});
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("Table 1"));
        cell.setColspan(3);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }
    
    /**
     * Creates a table; widths are set with setWidths().
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable createTable2() throws DocumentException {
        PdfPTable table = new PdfPTable(3);
        table.setTotalWidth(288);
        table.setLockedWidth(true);
        table.setWidths(new float[]{2, 1, 1});
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("Table 2"));
        cell.setColspan(3);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }
    
    /**
     * Creates a table; widths are set in the constructor.
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable createTable3() throws DocumentException {
        PdfPTable table = new PdfPTable(new float[]{ 2, 1, 1 });
        table.setWidthPercentage(55.067f);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("Table 3"));
        cell.setColspan(3);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }
    
    /**
     * Creates a table; widths are set with special setWidthPercentage() method.
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable createTable4() throws DocumentException {
        PdfPTable table = new PdfPTable(3);
        Rectangle rect = new Rectangle(523, 770);
        table.setWidthPercentage(new float[]{ 144, 72, 72 }, rect);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("Table 4"));
        cell.setColspan(3);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }
    
    /**
     * Creates a table; widths are set with setTotalWidth().
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable createTable5() throws DocumentException {
        PdfPTable table = new PdfPTable(3);
        table.setTotalWidth(new float[]{ 144, 72, 72 });
        table.setLockedWidth(true);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("Table 5"));
        cell.setColspan(3);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
        cell.setRowspan(2);
        table.addCell(cell);
        table.addCell("row 1; cell 1");
        table.addCell("row 1; cell 2");
        table.addCell("row 2; cell 1");
        table.addCell("row 2; cell 2");
        return table;
    }

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ColumnWidths().createPdf(RESULT);
    }
}
TableAlignment.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class TableAlignment extends MyFirstTable {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/table_alignment.pdf";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfPTable table = createFirstTable();
        table.setWidthPercentage(50);
        table.setHorizontalAlignment(Element.ALIGN_LEFT);
        document.add(table);
        table.setHorizontalAlignment(Element.ALIGN_CENTER);
        document.add(table);
        table.setHorizontalAlignment(Element.ALIGN_RIGHT);
        document.add(table);
        // 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 TableAlignment().createPdf(RESULT);
    }
}
MovieTextMode.java
/*
 * 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.chapter04;

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.Country;
import com.lowagie.filmfestival.Director;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class MovieTextMode {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/movie_text_mode.pdf";
    
    /**
     * 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();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Movies:"));
        List movies = PojoFactory.getMovies(connection);
        for (Movie movie : movies) {
            PdfPTable table = new PdfPTable(2);
            table.setWidths(new int[]{1, 4});
            PdfPCell cell;
            cell = new PdfPCell(new Phrase(movie.getTitle(), FilmFonts.BOLD));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setColspan(2);
            table.addCell(cell);
            if (movie.getOriginalTitle() != null) {
                cell = new PdfPCell(PojoToElementFactory.getOriginalTitlePhrase(movie));
                cell.setColspan(2);
                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                table.addCell(cell);
            }
            List directors = movie.getDirectors();
            cell = new PdfPCell(new Phrase("Directors:"));
            cell.setRowspan(directors.size());
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            table.addCell(cell);
            int count = 0;
            for (Director pojo : directors) {
                cell = new PdfPCell(PojoToElementFactory.getDirectorPhrase(pojo));
                cell.setIndent(10 * count++);
                table.addCell(cell);
            }
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
            table.addCell("Year:");
            table.addCell(String.valueOf(movie.getYear()));
            table.addCell("Run length:");
            table.addCell(String.valueOf(movie.getDuration()));
            List countries = movie.getCountries();
            cell = new PdfPCell(new Phrase("Countries:"));
            cell.setRowspan(countries.size());
            cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
            table.addCell(cell);
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
            for (Country country : countries) {
                table.addCell(country.getCountry());
            }
            document.add(table);
        }
        // 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 MovieTextMode().createPdf(RESULT);
    }
}
Spacing.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class Spacing {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/spacing.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table = new PdfPTable(2);
        table.setWidthPercentage(100);
        Phrase p = new Phrase(
            "Dr. iText or: How I Learned to Stop Worrying " +
            "and Love the Portable Document Format.");
        PdfPCell cell = new PdfPCell(p);
        table.addCell("default leading / spacing");
        table.addCell(cell);
        table.addCell("absolute leading: 20");
        cell.setLeading(20f, 0f);
        table.addCell(cell);
        table.addCell("absolute leading: 3; relative leading: 1.2");
        cell.setLeading(3f, 1.2f);
        table.addCell(cell);
        table.addCell("absolute leading: 0; relative leading: 1.2");
        cell.setLeading(0f, 1.2f);
        table.addCell(cell);
        table.addCell("no leading at all");
        cell.setLeading(0f, 0f);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase(
            "Dr. iText or: How I Learned to Stop Worrying and Love PDF"));
        table.addCell("padding 10");
        cell.setPadding(10);
        table.addCell(cell);
        table.addCell("padding 0");
        cell.setPadding(0);
        table.addCell(cell);
        table.addCell("different padding for left, right, top and bottom");
        cell.setPaddingLeft(20);
        cell.setPaddingRight(50);
        cell.setPaddingTop(0);
        cell.setPaddingBottom(5);
        table.addCell(cell);
        p = new Phrase("iText in Action Second Edition");
        table.getDefaultCell().setPadding(2);
        table.getDefaultCell().setUseAscender(false);
        table.getDefaultCell().setUseDescender(false);
        table.addCell("padding 2; no ascender, no descender");
        table.addCell(p);
        table.getDefaultCell().setUseAscender(true);
        table.getDefaultCell().setUseDescender(false);
        table.addCell("padding 2; ascender, no descender");
        table.addCell(p);
        table.getDefaultCell().setUseAscender(false);
        table.getDefaultCell().setUseDescender(true);
        table.addCell("padding 2; descender, no ascender");
        table.addCell(p);
        table.getDefaultCell().setUseAscender(true);
        table.getDefaultCell().setUseDescender(true);
        table.addCell("padding 2; ascender and descender");
        cell.setPadding(2);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        table.addCell(p);
        document.add(table);
        // step 5
        document.close();
    }
}
TableHeight.java
/*
 * 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.chapter04;

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.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class TableHeight extends MyFirstTable {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/table_height.pdf";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
        // step 1
    	Document document = new Document();
        // step 2
    	PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
    	document.open();
    	// step 4
        PdfPTable table = createFirstTable();
        document.add(new Paragraph(
            String.format("Table height before document.add(): %f",
                table.getTotalHeight())));
        document.add(new Paragraph(
            String.format("Height of the first row: %f",
                table.getRowHeight(0))));
        document.add(table);
        document.add(new Paragraph(
            String.format("Table height after document.add(): %f",
                table.getTotalHeight())));
        document.add(new Paragraph(
            String.format("Height of the first row: %f",
                table.getRowHeight(0))));
        table = createFirstTable();
        document.add(new Paragraph(
            String.format("Table height before setTotalWidth(): %f",
                table.getTotalHeight())));
        document.add(
            new Paragraph(String.format("Height of the first row: %f",
                table.getRowHeight(0))));
        table.setTotalWidth(50);
        table.setLockedWidth(true);
        document.add(
            new Paragraph(String.format("Table height after setTotalWidth(): %f",
                table.getTotalHeight())));
        document.add(new Paragraph(String.format("Height of the first row: %f",
            table.getRowHeight(0))));
        document.add(table);
        // 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 TableHeight().createPdf(RESULT);
    }
}
CellHeights.java
/*
 * 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.chapter04;

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.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class CellHeights {
    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/cell_heights.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws DocumentException, IOException {
    	// step 1
        Document document = new Document(PageSize.A5.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table = new PdfPTable(2);
        // a long phrase
        Phrase p = new Phrase(
            "Dr. iText or: How I Learned to Stop Worrying and Love PDF.");
        PdfPCell cell = new PdfPCell(p);
        // the prhase is wrapped
        table.addCell("wrap");
        cell.setNoWrap(false);
        table.addCell(cell);
        // the phrase isn't wrapped
        table.addCell("no wrap");
        cell.setNoWrap(true);
        table.addCell(cell);
        // a long phrase with newlines
        p = new Phrase(
            "Dr. iText or:\nHow I Learned to Stop Worrying\nand Love PDF.");
        cell = new PdfPCell(p);
        // the phrase fits the fixed height
        table.addCell("fixed height (more than sufficient)");
        cell.setFixedHeight(72f);
        table.addCell(cell);
        // the phrase doesn't fit the fixed height
        table.addCell("fixed height (not sufficient)");
        cell.setFixedHeight(36f);
        table.addCell(cell);
        // The minimum height is exceeded
        table.addCell("minimum height");
        cell = new PdfPCell(new Phrase("Dr. iText"));
        cell.setMinimumHeight(36f);
        table.addCell(cell);
        // The last row is extended
        table.setExtendLastRow(true);
        table.addCell("extend last row");
        table.addCell(cell);
        document.add(table);
        // step 5
        document.close();
    }
}
RotationAndColors.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

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.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;

public class RotationAndColors {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/rotation_colors.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table = new PdfPTable(4);
        table.setWidths(new int[]{ 1, 3, 3, 3 });
        table.setWidthPercentage(100);
        PdfPCell cell;
        // row 1, cell 1
        cell = new PdfPCell(new Phrase("COLOR"));
        cell.setRotation(90);
        cell.setVerticalAlignment(Element.ALIGN_TOP);
        table.addCell(cell);
        // row 1, cell 2
        cell = new PdfPCell(new Phrase("red / no borders"));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setBackgroundColor(BaseColor.RED);
        table.addCell(cell);
        // row 1, cell 3
        cell = new PdfPCell(new Phrase("green / black bottom border"));
        cell.setBorder(Rectangle.BOTTOM);
        cell.setBorderColorBottom(BaseColor.BLACK);
        cell.setBorderWidthBottom(10f);
        cell.setBackgroundColor(BaseColor.GREEN);
        table.addCell(cell);
        // row 1, cell 4
        cell = new PdfPCell(new Phrase(
                "cyan / blue top border + padding"));
        cell.setBorder(Rectangle.TOP);
        cell.setUseBorderPadding(true);
        cell.setBorderWidthTop(5f);
        cell.setBorderColorTop(BaseColor.BLUE);
        cell.setBackgroundColor(BaseColor.CYAN);
        table.addCell(cell);
        // row 2, cell 1
        cell = new PdfPCell(new Phrase("GRAY"));
        cell.setRotation(90);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.addCell(cell);
        // row 2, cell 2
        cell = new PdfPCell(new Phrase("0.6"));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setGrayFill(0.6f);
        table.addCell(cell);
        // row 2, cell 3
        cell = new PdfPCell(new Phrase("0.75"));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setGrayFill(0.75f);
        table.addCell(cell);
        // row 2, cell 4
        cell = new PdfPCell(new Phrase("0.9"));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setGrayFill(0.9f);
        table.addCell(cell);
        // row 3, cell 1
        cell = new PdfPCell(new Phrase("BORDERS"));
        cell.setRotation(90);
        cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
        table.addCell(cell);
        // row 3, cell 2
        cell = new PdfPCell(new Phrase("different borders"));
        cell.setBorderWidthLeft(16f);
        cell.setBorderWidthBottom(12f);
        cell.setBorderWidthRight(8f);
        cell.setBorderWidthTop(4f);
        cell.setBorderColorLeft(BaseColor.RED);
        cell.setBorderColorBottom(BaseColor.ORANGE);
        cell.setBorderColorRight(BaseColor.YELLOW);
        cell.setBorderColorTop(BaseColor.GREEN);
        table.addCell(cell);
        // row 3, cell 3
        cell = new PdfPCell(new Phrase("with correct padding"));
        cell.setUseBorderPadding(true);
        cell.setBorderWidthLeft(16f);
        cell.setBorderWidthBottom(12f);
        cell.setBorderWidthRight(8f);
        cell.setBorderWidthTop(4f);
        cell.setBorderColorLeft(BaseColor.RED);
        cell.setBorderColorBottom(BaseColor.ORANGE);
        cell.setBorderColorRight(BaseColor.YELLOW);
        cell.setBorderColorTop(BaseColor.GREEN);
        table.addCell(cell);
        // row 3, cell 4
        cell = new PdfPCell(new Phrase("red border"));
        cell.setBorderWidth(8f);
        cell.setBorderColor(BaseColor.RED);
        table.addCell(cell);
        document.add(table);
        // step 5
        document.close();
    }
}
MovieCompositeMode.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class MovieCompositeMode {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/movie_composite_mode.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        new MovieCompositeMode().createPdf(RESULT);
    }
    
    /**
     * 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();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Movies:"));
        java.util.List movies = PojoFactory.getMovies(connection);
        List list;
        PdfPCell cell;
        for (Movie movie : movies) {
            // a table with two columns
            PdfPTable table = new PdfPTable(new float[]{1, 7});
            table.setWidthPercentage(100);
            table.setSpacingBefore(5);
            // a cell with an image
            cell = new PdfPCell(
                Image.getInstance(String.format(RESOURCE, movie.getImdb())), true);
            cell.setBorder(PdfPCell.NO_BORDER);
            table.addCell(cell);
            cell = new PdfPCell();
            // a cell with paragraphs and lists
            Paragraph p = new Paragraph(movie.getTitle(), FilmFonts.BOLD);
            p.setAlignment(Element.ALIGN_CENTER);
            p.setSpacingBefore(5);
            p.setSpacingAfter(5);
            cell.addElement(p);
            cell.setBorder(PdfPCell.NO_BORDER);
            if (movie.getOriginalTitle() != null) {
                p = new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC);
                p.setAlignment(Element.ALIGN_RIGHT);
                cell.addElement(p);
            }
            list = PojoToElementFactory.getDirectorList(movie);
            list.setIndentationLeft(30);
            cell.addElement(list);
            p = new Paragraph(
                String.format("Year: %d", movie.getYear()), FilmFonts.NORMAL);
            p.setIndentationLeft(15);
            p.setLeading(24);
            cell.addElement(p);
            p = new Paragraph(
                String.format("Run length: %d", movie.getDuration()), FilmFonts.NORMAL);
            p.setLeading(14);
            p.setIndentationLeft(30);
            cell.addElement(p);
            list = PojoToElementFactory.getCountryList(movie);
            list.setIndentationLeft(40);
            cell.addElement(list);
            table.addCell(cell);
            // every movie corresponds with one table
            document.add(table);
            // but the result looks like one big table
        }
        // step 4
        document.close();
        // Close the database connection
        connection.close();
    }
}
XMen.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
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.PdfWriter;

public class XMen {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/x_men.pdf";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/posters/%s.jpg";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        // we'll use 4 images in this example
        Image[] img = {
                Image.getInstance(String.format(RESOURCE, "0120903")),
                Image.getInstance(String.format(RESOURCE, "0290334")),
                Image.getInstance(String.format(RESOURCE, "0376994")),
                Image.getInstance(String.format(RESOURCE, "0348150"))
        };
        // Creates a table with 6 columns
        PdfPTable table = new PdfPTable(6);
        table.setWidthPercentage(100);
        // first movie
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.getDefaultCell().setVerticalAlignment(Element.ALIGN_TOP);
        table.addCell("X-Men");
        // we wrap he image in a PdfPCell
        PdfPCell cell = new PdfPCell(img[0]);
        table.addCell(cell);
        // second movie
        table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.addCell("X2");
        // we wrap the image in a PdfPCell and let iText scale it
        cell = new PdfPCell(img[1], true);
        table.addCell(cell);
        // third movie
        table.getDefaultCell().setVerticalAlignment(Element.ALIGN_BOTTOM);
        table.addCell("X-Men: The Last Stand");
        // we add the image with addCell()
        table.addCell(img[2]);
        // fourth movie
        table.addCell("Superman Returns");
        cell = new PdfPCell();
        // we add it with addElement(); it can only take 50% of the width.
        img[3].setWidthPercentage(50);
        cell.addElement(img[3]);
        table.addCell(cell);
        // we complete the table (otherwise the last row won't be rendered)
        table.completeRow();
        document.add(table);
        document.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new XMen().createPdf(RESULT);
    }
}
NestedTable.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class NestedTable {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/nested_table.pdf";

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table = new PdfPTable(4);
        PdfPTable nested1 = new PdfPTable(2);
        nested1.addCell("1.1");
        nested1.addCell("1.2");
        PdfPTable nested2 = new PdfPTable(1);
        nested2.addCell("12.1");
        nested2.addCell("12.2");
        for (int k = 0; k < 16; ++k) {
            if (k == 1) {
                table.addCell(nested1);
            } else if (k == 12) {
                table.addCell(new PdfPCell(nested2));
            } else {
                table.addCell("cell " + k);
            }
        }
        document.add(table);
        // step 5
        document.close();
    }
}
NestedTables.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.html.WebColors;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;

public class NestedTables {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/nested_tables.pdf";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/posters/%s.jpg";
    /** Collection containing all the Images */
    public HashMap images = new HashMap();

    /**
     * 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 the database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        List 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();

    }

    /**
     * Creates a table with all the screenings of a specific day.
     * The table is composed of nested tables.
     * @param connection a database connection
     * @param day a film festival day
     * @return a table
     * @throws SQLException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfPTable getTable(DatabaseConnection connection, Date day)
        throws SQLException, DocumentException, IOException {
        // Create a table with only one column
    	PdfPTable table = new PdfPTable(1);
        table.setWidthPercentage(100f);
        // add the cell with the date
        Font f = new Font();
        f.setColor(BaseColor.WHITE);
        PdfPCell cell = new PdfPCell(new Phrase(day.toString(), f));
        cell.setBackgroundColor(BaseColor.BLACK);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        table.addCell(cell);
        // add the movies as nested tables
        List screenings = PojoFactory.getScreenings(connection, day);
        for (Screening screening : screenings) {
            table.addCell(getTable(connection, screening));
        }
        return table;
    }

    /**
     * Create a table with information about a movie.
     * @param connection a database connection
     * @param screening a Screening
     * @return a table
     * @throws DocumentException
     * @throws IOException
     */
    private PdfPTable getTable(DatabaseConnection connection, Screening screening)
        throws DocumentException, IOException {
    	// Create a table with 4 columns
        PdfPTable table = new PdfPTable(4);
        table.setWidths(new int[]{1, 5, 10, 10});
        // Get the movie
        Movie movie = screening.getMovie();
        // A cell with the title as a nested table spanning the complete row
        PdfPCell cell = new PdfPCell();
        // nesting is done with addElement() in this example
        cell.addElement(fullTitle(screening));
        cell.setColspan(4);
        cell.setBorder(PdfPCell.NO_BORDER);
        BaseColor color
            = WebColors.getRGBColor("#" + movie.getEntry().getCategory().getColor());
        cell.setBackgroundColor(color);
        table.addCell(cell);
        // empty cell
        cell = new PdfPCell();
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        table.addCell(cell);
        // cell with the movie poster
        cell = new PdfPCell(getImage(movie.getImdb()));
        cell.setBorder(PdfPCell.NO_BORDER);
        table.addCell(cell);
        // cell with the list of directors
        cell = new PdfPCell();
        cell.addElement(PojoToElementFactory.getDirectorList(movie));
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        table.addCell(cell);
        // cell with the list of countries
        cell = new PdfPCell();
        cell.addElement(PojoToElementFactory.getCountryList(movie));
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        table.addCell(cell);

        return table;
    }
    
    /**
     * Create a table with the full movie title
     * @param screening a Screening object
     * @return a table
     * @throws DocumentException
     */
    private static PdfPTable fullTitle(Screening screening)
        throws DocumentException {
        PdfPTable table = new PdfPTable(3);
        table.setWidths(new int[]{3, 15, 2});
        table.setWidthPercentage(100);
        // cell 1: location and time
        PdfPCell cell = new PdfPCell();
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setBackgroundColor(BaseColor.WHITE);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        String s = String.format("%s \u2013 %2$tH:%2$tM",
            screening.getLocation(), screening.getTime().getTime());
        cell.addElement(new Paragraph(s));
        table.addCell(cell);
        // cell 2: English and original title 
        Movie movie = screening.getMovie();
        Paragraph p = new Paragraph();
        p.add(new Phrase(movie.getMovieTitle(), FilmFonts.BOLD));
        p.setLeading(16);
        if (movie.getOriginalTitle() != null) {
            p.add(new Phrase(" (" + movie.getOriginalTitle() + ")"));
        }
        cell = new PdfPCell();
        cell.addElement(p);
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        table.addCell(cell);
        // cell 3 duration
        cell = new PdfPCell();
        cell.setBorder(PdfPCell.NO_BORDER);
        cell.setBackgroundColor(BaseColor.WHITE);
        cell.setUseAscender(true);
        cell.setUseDescender(true);
        p = new Paragraph(String.format("%d'", movie.getDuration()));
        p.setAlignment(Element.ALIGN_CENTER);
        cell.addElement(p);
        table.addCell(cell);
        return table;
    }
    
    /**
     * Create an image with a movie poster.
     * @param imdb an Internet Movie Database id
     * @return an Image
     * @throws DocumentException
     * @throws IOException
     */
    public Image getImage(String imdb) throws DocumentException, IOException {
        Image img = images.get(imdb);
        if (img == null) {
            img = Image.getInstance(String.format(RESOURCE, imdb));
            img.scaleToFit(80, 72);
            images.put(imdb, img);
        }
        return img;
    }

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, DocumentException, IOException {
        new NestedTables().createPdf(RESULT);
    }
}
HeaderFooter1.java
/*
 * 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.chapter04;

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.PojoToElementFactory;
import com.lowagie.filmfestival.Screening;
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.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;

public class HeaderFooter1 {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/header_footer_1.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 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();

    }

    /**
     * Creates a table with screenings.
     * @param connection the 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 {
    	// Create a table with 7 columns
        PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1, 3, 2 });
        table.setWidthPercentage(100f);
        table.getDefaultCell().setUseAscender(true);
        table.getDefaultCell().setUseDescender(true);
        // Add the first header row
        Font f = new Font();
        f.setColor(BaseColor.WHITE);
        PdfPCell cell = new PdfPCell(new Phrase(day.toString(), f));
        cell.setBackgroundColor(BaseColor.BLACK);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setColspan(7);
        table.addCell(cell);
        // Add the second header row twice
        table.getDefaultCell().setBackgroundColor(BaseColor.LIGHT_GRAY);
        for (int i = 0; i < 2; i++) {
            table.addCell("Location");
            table.addCell("Time");
            table.addCell("Run Length");
            table.addCell("Title");
            table.addCell("Year");
            table.addCell("Directors");
            table.addCell("Countries");
        }
        table.getDefaultCell().setBackgroundColor(null);
        // There are three special rows
        table.setHeaderRows(3);
        // One of them is a footer
        table.setFooterRows(1);
        // Now let's loop over the screenings
        List 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()));
            cell = new PdfPCell();
            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.addElement(PojoToElementFactory.getDirectorList(movie));
            table.addCell(cell);
            cell = new PdfPCell();
            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.addElement(PojoToElementFactory.getCountryList(movie));
            table.addCell(cell);
        }
        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 HeaderFooter1().createPdf(RESULT);
    }
}
HeaderFooter2.java
/*
 * 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.chapter04;

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.PojoFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class HeaderFooter2 extends HeaderFooter1 {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part1/chapter04/header_footer_2.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 days = PojoFactory.getDays(connection);
        for (Date day : days) {
            PdfPTable table = getTable(connection, day);
            table.setSplitLate(false);
            document.add(table);
            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 SQLException, DocumentException, IOException {
        new HeaderFooter2().createPdf(RESULT);
    }
}
MemoryTests.java
/*
 * 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.chapter04;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.sql.SQLException;

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
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.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class MemoryTests {

    /** The resulting report. */
    public static final String RESULT0
       = "results/part1/chapter04/test_results.txt";
    /** A resulting PDF file. */
    public static final String RESULT1
        = "results/part1/chapter04/pdfptable_without_memory_management.pdf";
    /** A resulting PDF file. */
    public static final String RESULT2
        = "results/part1/chapter04/pdfptable_with_memory_management.pdf";
    
    private boolean test;
    private long memory_use;
    private long initial_memory_use = 0l;
    private long maximum_memory_use = 0l;
    
    /** Path to the resources. */
    public static final String RESOURCE = "resources/posters/%s.jpg";
    /** 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);
    }
    
    /**
     * Create two PDFs, one without memory management, one with.
     * Write a report file to show the memory usage
     */
    public void createPdfs() {
        try {
            // the report file
            PrintWriter writer = new PrintWriter(new FileOutputStream(RESULT0));
            resetMaximum(writer);
            test = false;
            println(writer, RESULT1);
            // PDF without memory management
            createPdfWithPdfPTable(writer, RESULT1);
            resetMaximum(writer);
            test = true;
            println(writer, RESULT2);
            // PDF with memory management
            createPdfWithPdfPTable(writer, RESULT2);
            resetMaximum(writer);
            writer.flush();
            writer.close();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Creates a PDF with a table
     * @param writer the writer to our report file
     * @param filename the PDF that will be created
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    private void createPdfWithPdfPTable(Writer writer, String filename) throws IOException, DocumentException, SQLException {
        // Create a connection to the database
    	DatabaseConnection connection = new HsqldbConnection("filmfestival"); 
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        // Create a table with 2 columns
        PdfPTable table = new PdfPTable(new float[]{1, 7});
        // Mark the table as not complete
        if (test) table.setComplete(false);
        table.setWidthPercentage(100);
        java.util.List movies = PojoFactory.getMovies(connection);
        List list;
        PdfPCell cell;
        int count = 0;
        // add information about a movie
        for (Movie movie : movies) {
            table.setSpacingBefore(5);
            // add a movie poster
            cell = new PdfPCell(Image.getInstance(String.format(RESOURCE, movie.getImdb())), true);
            cell.setBorder(PdfPCell.NO_BORDER);
            table.addCell(cell);
            // add movie information
            cell = new PdfPCell();
            Paragraph p = new Paragraph(movie.getTitle(), FilmFonts.BOLD);
            p.setAlignment(Element.ALIGN_CENTER);
            p.setSpacingBefore(5);
            p.setSpacingAfter(5);
            cell.addElement(p);
            cell.setBorder(PdfPCell.NO_BORDER);
            if (movie.getOriginalTitle() != null) {
                p = new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC);
                p.setAlignment(Element.ALIGN_RIGHT);
                cell.addElement(p);
            }
            list = PojoToElementFactory.getDirectorList(movie);
            list.setIndentationLeft(30);
            cell.addElement(list);
            p = new Paragraph(String.format("Year: %d", movie.getYear()), FilmFonts.NORMAL);
            p.setIndentationLeft(15);
            p.setLeading(24);
            cell.addElement(p);
            p = new Paragraph(String.format("Run length: %d", movie.getDuration()), FilmFonts.NORMAL);
            p.setLeading(14);
            p.setIndentationLeft(30);
            cell.addElement(p);
            list = PojoToElementFactory.getCountryList(movie);
            list.setIndentationLeft(40);
            cell.addElement(list);
            table.addCell(cell);
            // insert a checkpoint every 10 movies
            if (count++ % 10 == 0) {
            	// add the incomplete table to the document
                if (test)
                    document.add(table);
                checkpoint(writer);
            }
        }
        // Mark the table as complete
        if (test) table.setComplete(true);
        // add the table to the document
        document.add(table);
        // insert a last checkpoint
        checkpoint(writer);
        // step 5
        document.close();
    }
    
    /**
     * Writes a checkpoint to the report file.
     * @param writer the writer to our report file
     */
    private void checkpoint(Writer writer) {
        memory_use = getMemoryUse();
        maximum_memory_use = Math.max(maximum_memory_use, memory_use);
        println(writer, "memory use: ", memory_use);
    }
    
    /**
     * Resets the maximum memory that is in use
     * @param writer the writer to our report file
     */
    private void resetMaximum(Writer writer) {
        println(writer, "maximum: ", maximum_memory_use);
        println(writer, "total used: ", maximum_memory_use - initial_memory_use);
        maximum_memory_use = 0l;
        initial_memory_use = getMemoryUse();
        println(writer, "initial memory use: ", initial_memory_use);
    }

    /**
     * Writes a line to our report file
     * @param writer the writer to our report file
     * @param message the message to write
     */
    private void println(Writer writer, String message) {
        try {
            writer.write(message);
            writer.write("\n");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Writes a line to our report file
     * @param writer the writer to our report file
     * @param message the message to write
     * @param l a memory value
     */
    private void println(Writer writer, String message, long l) {
        try {
            writer.write(message + l);
            writer.write("\n");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Returns the current memory use.
     * 
     * @return the current memory use
     */
    private static long getMemoryUse() {
        garbageCollect();
        garbageCollect();
        long totalMemory = Runtime.getRuntime().totalMemory();
        garbageCollect();
        garbageCollect();
        long freeMemory = Runtime.getRuntime().freeMemory();
        return (totalMemory - freeMemory);
    }
    
    /**
     * Makes sure all garbage is cleared from the memory.
     */
    private static void garbageCollect() {
        try {
            System.gc();
            Thread.sleep(100);
            System.runFinalization();
            Thread.sleep(100);
            System.gc();
            Thread.sleep(100);
            System.runFinalization();
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args) {
        MemoryTests tests = new MemoryTests();
        tests.createPdfs();
    }
}
PdfCalendar.java
/*
 * 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.chapter04;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Properties;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.pdf.draw.VerticalPositionMark;

public class PdfCalendar {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/calendar.pdf";
    /** The year for which we want to create a calendar */
    public static final int YEAR = 2011;
    /** The language code for the calendar */
    public static final String LANGUAGE = "en";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/calendar/%tm.jpg";
    /** Path to the resources. */
    public static final String SPECIAL = "resources/calendar/%d.txt";
    /** Path to the resources. */
    public static final String CONTENT = "resources/calendar/content.txt";

    /** Collection with special days */
    public static Properties specialDays = new Properties();
    /** Collection with the description of the images */
    public static Properties content = new Properties();

    /** A font that is used in the calendar */
    protected Font normal;
    /** A font that is used in the calendar */
    protected Font small;
    /** A font that is used in the calendar */
    protected Font bold;

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    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 {
        // fonts
    	BaseFont bf_normal
            = BaseFont.createFont("c://windows/fonts/arial.ttf",
                BaseFont.WINANSI, BaseFont.EMBEDDED);
        normal = new Font(bf_normal, 16);
        small = new Font(bf_normal, 8);
        BaseFont bf_bold
            = BaseFont.createFont("c://windows/fonts/arialbd.ttf",
                BaseFont.WINANSI,BaseFont.EMBEDDED);
        bold = new Font(bf_bold, 14);
        // collections
        specialDays.load(new FileInputStream(String.format(SPECIAL, YEAR)));
        content.load(new FileInputStream(CONTENT));
    }

    /**
     * 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.setTotalWidth(504);
            // add the name of the month
            table.getDefaultCell().setBackgroundColor(BaseColor.WHITE);
            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() + 18, canvas);
            document.newPage();
        }
        // step 5
        document.close();
    }

    /**
     * Draws the image of the month to the calendar.
     * @param canvas the direct content layer
     * @param calendar the month (to know which picture to use)
     * @throws DocumentException
     * @throws IOException
     */
    public void drawImageAndText(PdfContentByte canvas, Calendar calendar) throws DocumentException, IOException {
        // get the image
    	Image img = Image.getInstance(String.format(RESOURCE, calendar));
        img.scaleToFit(PageSize.A4.getHeight(), PageSize.A4.getWidth());
        img.setAbsolutePosition(
                (PageSize.A4.getHeight() - img.getScaledWidth()) / 2,
                (PageSize.A4.getWidth() - img.getScaledHeight()) / 2);
        canvas.addImage(img);
        // add metadata
        canvas.saveState();
        canvas.setCMYKColorFill(0x00, 0x00, 0x00, 0x80);
        Phrase p = new Phrase(String.format(
                "%s - \u00a9 Katharine Osborne",
                content.getProperty(String.format("%tm.jpg", calendar))), small);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, p, 5, 5, 0);
        p = new Phrase("Calendar generated using iText - example for the book iText in Action 2nd Edition", small);
        ColumnText.showTextAligned(canvas, Element.ALIGN_RIGHT, p, 839, 5, 0);
        canvas.restoreState();
    }
    
    /**
     * 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.setBackgroundColor(BaseColor.WHITE);
        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();
        cell.setPadding(3);
        // set the background color, based on the type of day
        if (isSunday(calendar))
            cell.setBackgroundColor(BaseColor.GRAY);
        else if (isSpecialDay(calendar))
            cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        else
            cell.setBackgroundColor(BaseColor.WHITE);
        // 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 for Sundays.
     * @param calendar a date
     * @return true for Sundays
     */
    public boolean isSunday(Calendar calendar) {
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return true;
        }
        return false;
    }
    
    /**
     * 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 (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
            return true;
        if (specialDays.containsKey(String.format("%1$tm%1$td", calendar)))
            return true;
        return false;
    }
}
Zhang.java
/*
 * 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.chapter04;

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.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class Zhang {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part1/chapter04/zhang.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 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));
        // step 3
        document.open();
        // step 4
        // Create a table and fill it with movies
        List movies = PojoFactory.getMovies(connection, 3);
        PdfPTable table = new PdfPTable(new float[] { 1, 5, 5, 1});
        for (Movie movie : movies) {
            table.addCell(String.valueOf(movie.getYear()));
            table.addCell(movie.getMovieTitle());
            table.addCell(movie.getOriginalTitle());
            table.addCell(String.valueOf(movie.getDuration()));
        }
        // set the total width of the table
        table.setTotalWidth(600);
        PdfContentByte canvas = writer.getDirectContent();
        // draw the first two columns on one page
        table.writeSelectedRows(0, 2, 0, -1, 236, 806, canvas);
        document.newPage();
        // draw the remaining two columns on the next page
        table.writeSelectedRows(2, -1, 0, -1, 36, 806, canvas);
        // 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 Zhang().createPdf(RESULT);
    }
}
ColumnTable.java
/*
 * 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.chapter04;

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.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;

public class ColumnTable {

    public static final String RESULT = "results/part1/chapter04/column_table.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 the database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4.rotate());
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        ColumnText column = new ColumnText(writer.getDirectContent());
        List days = PojoFactory.getDays(connection);
        // COlumn definition
        float[][] x = {
                { document.left(), document.left() + 380 },
                { document.right() - 380, document.right() }
            };
        // Loop over the festival days
        for (Date day : days) {
            // add content to the column
            column.addElement(getTable(connection, day));
            int count = 0;
            float height = 0;
            int status = ColumnText.START_COLUMN;
            // render the column as long as it has content
            while (ColumnText.hasMoreText(status)) {
            	// add the top-level header to each new page
                if (count == 0) {
                    height = addHeaderTable(
                        document, day, writer.getPageNumber());
                }
                // set the dimensions of the current column
                column.setSimpleColumn(
                    x[count][0], document.bottom(),
                    x[count][1], document.top() - height - 10);
                // render as much content as possible
                status = column.go();
                // go to a new page if you've reached the last column
                if (++count > 1) {
                    count = 0;
                    document.newPage();
                }
            }
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Add a header table to the document
     * @param document The document to which you want to add a header table
     * @param day The day that needs to be shown in the header table
     * @param page The page number that has to be shown in the header
     * @return the height of the resulting header table
     * @throws DocumentException
     */
    public float addHeaderTable(Document document, Date day, int page)
        throws DocumentException {
        PdfPTable header = new PdfPTable(3);
        header.setWidthPercentage(100);
        header.getDefaultCell().setBackgroundColor(BaseColor.BLACK);
        Font font = new Font(FontFamily.HELVETICA, 12, Font.BOLD, BaseColor.WHITE);
        Phrase p = new Phrase("Foobar Film Festival", font);
        header.addCell(p);
        header.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        p = new Phrase(day.toString(), font);
        header.addCell(p);
        header.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        p = new Phrase(String.format("page %d", page), font);
        header.addCell(p);
        document.add(header);
        return header.getTotalHeight();
    }

    /**
     * Creates a table with movie screenings for a specific day
     * @param connection a connection to the database
     * @param day a 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().setUseAscender(true);
        table.getDefaultCell().setUseDescender(true);
        table.getDefaultCell().setBackgroundColor(BaseColor.LIGHT_GRAY);
        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(2);
        table.setFooterRows(1);
        List 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;
    }

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, DocumentException, IOException {
        new ColumnTable().createPdf(RESULT);
    }
}
MyFirstTable.cs
/*
 * 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.Chapter04 {
  public class MyFirstTable : IWriter {
// ===========================================================================
    public virtual void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(CreateFirstTable());
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates our first table
     * @return our first table
     */
    public static PdfPTable CreateFirstTable() {
    // a table with three columns
      PdfPTable table = new PdfPTable(3);
      // the cell object
      PdfPCell cell;
      // we add a cell with colspan 3
      cell = new PdfPCell(new Phrase("Cell with colspan 3"));
      cell.Colspan = 3;
      table.AddCell(cell);
      // now we add a cell with rowspan 2
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      // we add the four remaining cells with addCell()
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }
// ===========================================================================
  }
}
ColumnWidths.cs
/*
 * 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.Chapter04 {
  public class ColumnWidths : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = CreateTable1();
        document.Add(table);
        table = CreateTable2();
        table.SpacingBefore = 5;
        table.SpacingAfter = 5;
        document.Add(table);
        table = CreateTable3();
        document.Add(table);
        table = CreateTable4();
        table.SpacingBefore = 5;
        table.SpacingAfter = 5;
        document.Add(table);
        table = CreateTable5();
        document.Add(table);
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table; widths are set with setWidths().
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable CreateTable1() {
      PdfPTable table = new PdfPTable(3);
      table.WidthPercentage  =288 / 5.23f;
      table.SetWidths(new int[]{2, 1, 1});
      PdfPCell cell;
      cell = new PdfPCell(new Phrase("Table 1"));
      cell.Colspan = 3;
      table.AddCell(cell);
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table; widths are set with setWidths().
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable CreateTable2() {
      PdfPTable table = new PdfPTable(3);
      table.TotalWidth = 288;
      table.LockedWidth = true;
      table.SetWidths(new float[]{2, 1, 1});
      PdfPCell cell;
      cell = new PdfPCell(new Phrase("Table 2"));
      cell.Colspan = 3;
      table.AddCell(cell);
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table; widths are set in the constructor.
     * @return a PdfPTable
     * @throws DocumentException
     */
    public static PdfPTable CreateTable3() {
      PdfPTable table = new PdfPTable(new float[]{ 2, 1, 1 });
      table.WidthPercentage = 55.067f;
      PdfPCell cell;
      cell = new PdfPCell(new Phrase("Table 3"));
      cell.Colspan = 3;
      table.AddCell(cell);
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table; widths are set with special setWidthPercentage() method.
     * @return a PdfPTable
     */
    public static PdfPTable CreateTable4() {
      PdfPTable table = new PdfPTable(3);
      Rectangle rect = new Rectangle(523, 770);
      table.SetWidthPercentage(new float[]{ 144, 72, 72 }, rect);
      PdfPCell cell;
      cell = new PdfPCell(new Phrase("Table 4"));
      cell.Colspan =3;
      table.AddCell(cell);
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table; widths are set with setTotalWidth().
     * @return a PdfPTable
     */
    public static PdfPTable CreateTable5() {
      PdfPTable table = new PdfPTable(3);
      table.SetTotalWidth(new float[]{ 144, 72, 72 });
      table.LockedWidth = true;
      PdfPCell cell;
      cell = new PdfPCell(new Phrase("Table 5"));
      cell.Colspan = 3 ;
      table.AddCell(cell);
      cell = new PdfPCell(new Phrase("Cell with rowspan 2"));
      cell.Rowspan = 2;
      table.AddCell(cell);
      table.AddCell("row 1; cell 1");
      table.AddCell("row 1; cell 2");
      table.AddCell("row 2; cell 1");
      table.AddCell("row 2; cell 2");
      return table;
    }    
// ===========================================================================
  }
}
TableAlignment.cs
/*
 * 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.Chapter04 {
  public class TableAlignment : MyFirstTable {
// ===========================================================================
    public override void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = CreateFirstTable();
        table.WidthPercentage = 50;
        table.HorizontalAlignment = Element.ALIGN_LEFT;
        document.Add(table);
        table.HorizontalAlignment = Element.ALIGN_CENTER;
        document.Add(table);
        table.HorizontalAlignment = Element.ALIGN_RIGHT;
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
MovieTextMode.cs
/*
 * 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.Chapter04 {
  public class MovieTextMode : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(new Paragraph("Movies:"));
        IEnumerable movies = PojoFactory.GetMovies();
        foreach (Movie movie in movies) {
          PdfPTable table = new PdfPTable(2);
          table.SetWidths(new int[]{1, 4});
          PdfPCell cell;
          cell = new PdfPCell(new Phrase(movie.Title, FilmFonts.BOLD));
          cell.HorizontalAlignment = Element.ALIGN_CENTER;
          cell.Colspan = 2;
          table.AddCell(cell);
          if (!string.IsNullOrEmpty(movie.OriginalTitle)) {
            cell = new PdfPCell(PojoToElementFactory.GetOriginalTitlePhrase(movie));
            cell.Colspan = 2;
            cell.HorizontalAlignment = Element.ALIGN_RIGHT;
            table.AddCell(cell);
          }
          List directors = movie.Directors;
          cell = new PdfPCell(new Phrase("Directors:"));
          cell.Rowspan = directors.Count;
          cell.VerticalAlignment = Element.ALIGN_MIDDLE;
          table.AddCell(cell);
          int count = 0;
          foreach (Director pojo in directors) {
            cell = new PdfPCell(PojoToElementFactory.GetDirectorPhrase(pojo));
            cell.Indent = (10 * count++);
            table.AddCell(cell);
          }
          table.DefaultCell.HorizontalAlignment = Element.ALIGN_RIGHT;
          table.AddCell("Year:");
          table.AddCell(movie.Year.ToString());
          table.AddCell("Run length:");
          table.AddCell(movie.Duration.ToString());
          List countries = movie.Countries;
          cell = new PdfPCell(new Phrase("Countries:"));
          cell.Rowspan = countries.Count;
          cell.VerticalAlignment = Element.ALIGN_BOTTOM;
          table.AddCell(cell);
          table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
          foreach (Country country in countries) {
            table.AddCell(country.Name);
          }
          document.Add(table);
        }        
      }
    }
// ===========================================================================
  }
}
Spacing.cs
/*
 * 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.Chapter04 {
  public class Spacing : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = new PdfPTable(2);
        table.WidthPercentage = 100;
        Phrase p = new Phrase(
          "Dr. iText or: How I Learned to Stop Worrying " +
          "and Love the Portable Document Format."
        );
        PdfPCell cell = new PdfPCell(p);
        table.AddCell("default leading / spacing");
        table.AddCell(cell);
        table.AddCell("absolute leading: 20");
        cell.SetLeading(20f, 0f);
        table.AddCell(cell);
        table.AddCell("absolute leading: 3; relative leading: 1.2");
        cell.SetLeading(3f, 1.2f);
        table.AddCell(cell);
        table.AddCell("absolute leading: 0; relative leading: 1.2");
        cell.SetLeading(0f, 1.2f);
        table.AddCell(cell);
        table.AddCell("no leading at all");
        cell.SetLeading(0f, 0f);
        table.AddCell(cell);
        cell = new PdfPCell(new Phrase(
            "Dr. iText or: How I Learned to Stop Worrying and Love PDF"));
        table.AddCell("padding 10");
        cell.Padding = 10;
        table.AddCell(cell);
        table.AddCell("padding 0");
        cell.Padding = 0;
        table.AddCell(cell);
        table.AddCell("different padding for left, right, top and bottom");
        cell.PaddingLeft = 20;
        cell.PaddingRight = 50;
        cell.PaddingTop = 0;
        cell.PaddingBottom = 5;
        table.AddCell(cell);
        p = new Phrase("iText in Action Second Edition");
        table.DefaultCell.Padding = 2;
        table.DefaultCell.UseAscender = false;
        table.DefaultCell.UseDescender = false;
        table.AddCell("padding 2; no ascender, no descender");
        table.AddCell(p);
        table.DefaultCell.UseAscender = true;
        table.DefaultCell.UseDescender = false;
        table.AddCell("padding 2; ascender, no descender");
        table.AddCell(p);
        table.DefaultCell.UseAscender = false;
        table.DefaultCell.UseDescender = true;
        table.AddCell("padding 2; descender, no ascender");
        table.AddCell(p);
        table.DefaultCell.UseAscender = true;
        table.DefaultCell.UseDescender = true;
        table.AddCell("padding 2; ascender and descender");
        cell.Padding = 2;
        cell.UseAscender = true;
        cell.UseDescender = true;
        table.AddCell(p);
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
TableHeight.cs
/*
 * 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.Chapter04 {
  public class TableHeight : MyFirstTable {
// ===========================================================================
    public override void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = CreateFirstTable();
        document.Add(new Paragraph(string.Format(
          "Table height before document.Add(): {0}",
          table.TotalHeight)
        ));
        document.Add(new Paragraph(
            string.Format("Height of the first row: {0}",
                table.GetRowHeight(0))
         ));
        document.Add(table);
        document.Add(new Paragraph(string.Format(
          "Table height after document.Add(): {0}",
          table.TotalHeight
        )));
        document.Add(new Paragraph(string.Format(
          "Height of the first row: {0}",
          table.GetRowHeight(0)
        )));
        table = CreateFirstTable();
        document.Add(new Paragraph( string.Format(
          "Table height before setTotalWidth(): {0}",
          table.TotalHeight
        )));
        document.Add(new Paragraph(string.Format(
          "Height of the first row: {0}",
          table.GetRowHeight(0)
        )));
        table.TotalWidth = 50;
        table.LockedWidth = true;
        document.Add( new Paragraph(string.Format(
          "Table height after setTotalWidth(): {0}",
          table.TotalHeight
        )));
        document.Add(new Paragraph(string.Format(
          "Height of the first row: {0}",
          table.GetRowHeight(0)
        )));
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
CellHeights.cs
/*
 * 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.Chapter04 {
  public class CellHeights : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = new PdfPTable(2);
        // a long phrase
        Phrase p = new Phrase(
          "Dr. iText or: How I Learned to Stop Worrying and Love PDF."
        );
        PdfPCell cell = new PdfPCell(p);
        // the prhase is wrapped
        table.AddCell("wrap");
        cell.NoWrap = false;
        table.AddCell(cell);
        // the phrase isn't wrapped
        table.AddCell("no wrap");
        cell.NoWrap = true;
        table.AddCell(cell);
        // a long phrase with newlines
        p = new Phrase(
            "Dr. iText or:\nHow I Learned to Stop Worrying\nand Love PDF.");
        cell = new PdfPCell(p);
        // the phrase fits the fixed height
        table.AddCell("fixed height (more than sufficient)");
        cell.FixedHeight = 72f;
        table.AddCell(cell);
        // the phrase doesn't fit the fixed height
        table.AddCell("fixed height (not sufficient)");
        cell.FixedHeight = 36f;
        table.AddCell(cell);
        // The minimum height is exceeded
        table.AddCell("minimum height");
        cell = new PdfPCell(new Phrase("Dr. iText"));
        cell.MinimumHeight = 36f;
        table.AddCell(cell);
        // The last row is extended
        table.ExtendLastRow = true;
        table.AddCell("extend last row");
        table.AddCell(cell);
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
RotationAndColors.cs
/*
 * 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.Chapter04 {
  public class RotationAndColors : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = new PdfPTable(4);
        table.SetWidths(new int[]{ 1, 3, 3, 3 });
        table.WidthPercentage = 100;
        PdfPCell cell;
        // row 1, cell 1
        cell = new PdfPCell(new Phrase("COLOR"));
        cell.Rotation = 90;
        cell.VerticalAlignment = Element.ALIGN_TOP;
        table.AddCell(cell);
        // row 1, cell 2
        cell = new PdfPCell(new Phrase("red / no borders"));
        cell.Border = Rectangle.NO_BORDER;
        cell.BackgroundColor = BaseColor.RED;
        table.AddCell(cell);
        // row 1, cell 3
        cell = new PdfPCell(new Phrase("green / black bottom border"));
        cell.Border = Rectangle.BOTTOM_BORDER;
        cell.BorderColorBottom = BaseColor.BLACK;
        cell.BorderWidthBottom = 10f;
        cell.BackgroundColor = BaseColor.GREEN;
        table.AddCell(cell);
        // row 1, cell 4
        cell = new PdfPCell(new Phrase(
          "cyan / blue top border + padding"
        ));
        cell.Border  = Rectangle.TOP_BORDER;
        cell.UseBorderPadding = true;
        cell.BorderWidthTop = 5f;
        cell.BorderColorTop = BaseColor.BLUE;
        cell.BackgroundColor = BaseColor.CYAN;
        table.AddCell(cell);
        // row 2, cell 1
        cell = new PdfPCell(new Phrase("GRAY"));
        cell.Rotation = 90;
        cell.VerticalAlignment = Element.ALIGN_MIDDLE;
        table.AddCell(cell);
        // row 2, cell 2
        cell = new PdfPCell(new Phrase("0.6"));
        cell.Border = Rectangle.NO_BORDER;
        cell.GrayFill = 0.6f;
        table.AddCell(cell);
        // row 2, cell 3
        cell = new PdfPCell(new Phrase("0.75"));
        cell.Border = Rectangle.NO_BORDER;
        cell.GrayFill = 0.75f;
        table.AddCell(cell);
        // row 2, cell 4
        cell = new PdfPCell(new Phrase("0.9"));
        cell.Border = Rectangle.NO_BORDER;
        cell.GrayFill = 0.9f;
        table.AddCell(cell);
        // row 3, cell 1
        cell = new PdfPCell(new Phrase("BORDERS"));
        cell.Rotation = 90;
        cell.VerticalAlignment = Element.ALIGN_BOTTOM;
        table.AddCell(cell);
        // row 3, cell 2
        cell = new PdfPCell(new Phrase("different borders"));
        cell.BorderWidthLeft = 16f;
        cell.BorderWidthBottom = 12f;
        cell.BorderWidthRight = 8f;
        cell.BorderWidthTop = 4f;
        cell.BorderColorLeft = BaseColor.RED;
        cell.BorderColorBottom = BaseColor.ORANGE;
        cell.BorderColorRight = BaseColor.YELLOW;
        cell.BorderColorTop = BaseColor.GREEN;
        table.AddCell(cell);
        // row 3, cell 3
        cell = new PdfPCell(new Phrase("with correct padding"));
        cell.UseBorderPadding = true;
        cell.BorderWidthLeft = 16f;
        cell.BorderWidthBottom = 12f;
        cell.BorderWidthRight = 8f;
        cell.BorderWidthTop = 4f;
        cell.BorderColorLeft = BaseColor.RED;
        cell.BorderColorBottom = BaseColor.ORANGE;
        cell.BorderColorRight = BaseColor.YELLOW;
        cell.BorderColorTop = BaseColor.GREEN;
        table.AddCell(cell);
        // row 3, cell 4
        cell = new PdfPCell(new Phrase("red border"));
        cell.BorderWidth = 8f;
        cell.BorderColor = BaseColor.RED;
        table.AddCell(cell);
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
MovieCompositeMode.cs
  /*
 * 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.Chapter04 {
  public class MovieCompositeMode : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(new Paragraph("Movies:"));
        IEnumerable movies = PojoFactory.GetMovies();
        List list;
        PdfPCell cell;
        string RESOURCE = Utility.ResourcePosters;
        foreach (Movie movie in movies) {
      // a table with two columns
          PdfPTable table = new PdfPTable(new float[]{1, 7});
          table.WidthPercentage = 100;
          table.SpacingBefore = 5;
          // a cell with an image
          cell = new PdfPCell(
            Image.GetInstance(Path.Combine(RESOURCE, movie.Imdb + ".jpg")),
            true
          );
          cell.Border = PdfPCell.NO_BORDER;
          table.AddCell(cell);
          cell = new PdfPCell();
          // a cell with paragraphs and lists
          Paragraph p = new Paragraph(movie.Title, FilmFonts.BOLD);
          p.Alignment = Element.ALIGN_CENTER;
          p.SpacingBefore = 5;
          p.SpacingAfter = 5;
          cell.AddElement(p);
          cell.Border = PdfPCell.NO_BORDER;
          if (!string.IsNullOrEmpty(movie.OriginalTitle)) {
            p = new Paragraph(movie.OriginalTitle, FilmFonts.ITALIC);
            p.Alignment = Element.ALIGN_RIGHT;
            cell.AddElement(p);
          }
          list = PojoToElementFactory.GetDirectorList(movie);
          list.IndentationLeft = 30;
          cell.AddElement(list);
          p = new Paragraph(
            string.Format("Year: {0}", movie.Year), 
            FilmFonts.NORMAL
          );
          p.IndentationLeft = 15;
          p.Leading = 24;
          cell.AddElement(p);
          p = new Paragraph(
            string.Format("Run length: {0}", movie.Duration), 
            FilmFonts.NORMAL
          );
          p.Leading = 14;
          p.IndentationLeft = 30;
          cell.AddElement(p);
          list = PojoToElementFactory.GetCountryList(movie);
          list.IndentationLeft = 40;
          cell.AddElement(list);
          table.AddCell(cell);
          // every movie corresponds with one table
          document.Add(table);
          // but the result looks like one big table
        }
      }
    }
// ===========================================================================
  }
}
XMen.cs
/*
 * 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.Chapter04 {
  public class XMen : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        string RESOURCE = Utility.ResourcePosters;
        // we'll use 4 images in this example
        Image[] img = {
          Image.GetInstance(Path.Combine(RESOURCE, "0120903.jpg")),
          Image.GetInstance(Path.Combine(RESOURCE, "0290334.jpg")),
          Image.GetInstance(Path.Combine(RESOURCE, "0376994.jpg")),
          Image.GetInstance(Path.Combine(RESOURCE, "0348150.jpg"))
        };
        // Creates a table with 6 columns
        PdfPTable table = new PdfPTable(6);
        table.WidthPercentage = 100;
        // first movie
        table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
        table.DefaultCell.VerticalAlignment = Element.ALIGN_TOP;
        table.AddCell("X-Men");
        // we wrap he image in a PdfPCell
        PdfPCell cell = new PdfPCell(img[0]);
        table.AddCell(cell);
        // second movie
        table.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE;
        table.AddCell("X2");
        // we wrap the image in a PdfPCell and let iText scale it
        cell = new PdfPCell(img[1], true);
        table.AddCell(cell);
        // third movie
        table.DefaultCell.VerticalAlignment = Element.ALIGN_BOTTOM;
        table.AddCell("X-Men: The Last Stand");
        // we add the image with addCell()
        table.AddCell(img[2]);
        // fourth movie
        table.AddCell("Superman Returns");
        cell = new PdfPCell();
        // we add it with addElement(); it can only take 50% of the width.
        img[3].WidthPercentage = 50;
        cell.AddElement(img[3]);
        table.AddCell(cell);
        // we complete the table (otherwise the last row won't be rendered)
        table.CompleteRow();
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
NestedTable.cs
/*
 * 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.Chapter04 {
  public class NestedTable : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfPTable table = new PdfPTable(4);
        PdfPTable nested1 = new PdfPTable(2);
        nested1.AddCell("1.1");
        nested1.AddCell("1.2");
        PdfPTable nested2 = new PdfPTable(1);
        nested2.AddCell("12.1");
        nested2.AddCell("12.2");
        for (int k = 0; k < 16; ++k) {
          if (k == 1) {
            table.AddCell(nested1);
          } else if (k == 12) {
            table.AddCell(new PdfPCell(nested2));
          } else {
            table.AddCell("cell " + k);
          }
        }
        document.Add(table);
      }
    }
// ===========================================================================
  }
}
NestedTables.cs
/*
 * 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.Text.RegularExpressions;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter04 {
  public class NestedTables : IWriter {
// ===========================================================================
    /** Collection containing all the Images */
    public Dictionary images = new Dictionary();
    /** Path to the resources. */
    public readonly string RESOURCE = Utility.ResourcePosters;
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        List days = PojoFactory.GetDays();
        foreach (string day in days) {
          document.Add(GetTable(day));
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------   
    /**
     * Creates a table with all the screenings of a specific day.
     * The table is composed of nested tables.
     * @param day a film festival day
     * @return a table
     */
    public PdfPTable GetTable(string day) {
      // Create a table with only one column
      PdfPTable table = new PdfPTable(1);
      table.WidthPercentage = 100f;
      // add the cell with the date
      Font f = new Font();
      f.Color = BaseColor.WHITE;
      PdfPCell cell = new PdfPCell(new Phrase(day, f));
      cell.BackgroundColor = BaseColor.BLACK;
      cell.HorizontalAlignment = Element.ALIGN_CENTER;
      table.AddCell(cell);
      // add the movies as nested tables
      List screenings = PojoFactory.GetScreenings(day);
      foreach (Screening screening in screenings) {
        table.AddCell(GetTable(screening));
      }
      return table;
    }
// ---------------------------------------------------------------------------   
    /**
     * Create a table with information about a movie.
     * @param screening a Screening
     * @return a table
     */
    private PdfPTable GetTable(Screening screening) {
      // Create a table with 4 columns
      PdfPTable table = new PdfPTable(4);
      table.SetWidths(new int[]{1, 5, 10, 10});
      // Get the movie
      Movie movie = screening.movie;
      // A cell with the title as a nested table spanning the complete row
      PdfPCell cell = new PdfPCell();
      // nesting is done with addElement() in this example
      cell.AddElement(FullTitle(screening));
      cell.Colspan = 4;
      cell.Border = PdfPCell.NO_BORDER;
      BaseColor color = WebColors.GetRGBColor(
        "#" + movie.entry.category.color
      );
      cell.BackgroundColor = color;
      table.AddCell(cell);
      // empty cell
      cell = new PdfPCell();
      cell.Border = PdfPCell.NO_BORDER;
      cell.UseAscender = true;
      cell.UseDescender = true;
      table.AddCell(cell);
      // cell with the movie poster
      cell = new PdfPCell(GetImage(movie.Imdb));
      cell.Border = PdfPCell.NO_BORDER;
      table.AddCell(cell);
      // cell with the list of directors
      cell = new PdfPCell();
      cell.AddElement(PojoToElementFactory.GetDirectorList(movie));
      cell.Border = PdfPCell.NO_BORDER;
      cell.UseAscender = true;
      cell.UseDescender = true;
      table.AddCell(cell);
      // cell with the list of countries
      cell = new PdfPCell();
      cell.AddElement(PojoToElementFactory.GetCountryList(movie));
      cell.Border = PdfPCell.NO_BORDER;
      cell.UseAscender =  true;
      cell.UseDescender = true;
      table.AddCell(cell);
      return table;
    }
// ---------------------------------------------------------------------------       
    /**
     * Create a table with the full movie title
     * @param screening a Screening object
     * @return a table
     */
    private static PdfPTable FullTitle(Screening screening) {
      PdfPTable table = new PdfPTable(3);
      table.SetWidths(new int[]{3, 15, 2});
      table.WidthPercentage = 100;
      // cell 1: location and time
      PdfPCell cell = new PdfPCell();
      cell.Border = PdfPCell.NO_BORDER;
      cell.BackgroundColor = BaseColor.WHITE;
      cell.UseAscender = true;
      cell.UseDescender = true;
      String s = string.Format(
        // "{0} \u2013 %2$tH:%2$tM",
        "{0} \u2013 {1}",
        screening.Location, 
        screening.Time.Substring(0, 5)
        // screening.Time().getTime()
      );
      cell.AddElement(new Paragraph(s));
      table.AddCell(cell);
      // cell 2: English and original title 
      Movie movie = screening.movie;
      Paragraph p = new Paragraph();
      p.Add(new Phrase(movie.MovieTitle, FilmFonts.BOLD));
      p.Leading = 16;
      if (!string.IsNullOrEmpty(movie.OriginalTitle)) {
        p.Add(new Phrase(" (" + movie.OriginalTitle + ")"));
      }
      cell = new PdfPCell();
      cell.AddElement(p);
      cell.Border = PdfPCell.NO_BORDER;
      cell.UseAscender = true;
      cell.UseDescender = true;
      table.AddCell(cell);
      // cell 3 duration
      cell = new PdfPCell();
      cell.Border = PdfPCell.NO_BORDER;
      cell.BackgroundColor = BaseColor.WHITE;
      cell.UseAscender = true;
      cell.UseDescender = true;
      // p = new Paragraph(String.format("%d'", movie.getDuration()));
      p = new Paragraph(movie.Duration.ToString() + "'");
      p.Alignment = Element.ALIGN_CENTER;
      cell.AddElement(p);
      table.AddCell(cell);
      return table;
    }
// ---------------------------------------------------------------------------       
    /**
     * Create an image with a movie poster.
     * @param imdb an Internet Movie Database id
     * @return an Image
     * @throws DocumentException
     * @throws IOException
     */
    public Image GetImage(String imdb) {
      if ( images.ContainsKey(imdb) ) {
        return images[imdb];
      }
      else {
        Image img = Image.GetInstance(Path.Combine(RESOURCE, imdb + ".jpg"));
        img.ScaleToFit(80, 72);
        images.Add(imdb, img);
        return img;
      }
    } 
// ===========================================================================
  }
}
HeaderFooter1.cs
/*
 * 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.Chapter04 {
  public class HeaderFooter1 : IWriter {
// ===========================================================================
    public virtual 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 days = PojoFactory.GetDays();
        foreach (string day in days) {
          document.Add(GetTable(day));
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a table with screenings.
     * @param day a film festival day
     * @return a table with screenings
     */
    public PdfPTable GetTable(string day) {
    // Create a table with 7 columns
      PdfPTable table = new PdfPTable(new float[] { 2, 1, 2, 5, 1, 3, 2 });
      table.WidthPercentage = 100f;
      table.DefaultCell.UseAscender = true;
      table.DefaultCell.UseDescender = true;
      // Add the first header row
      Font f = new Font();
      f.Color = BaseColor.WHITE;
      PdfPCell cell = new PdfPCell(new Phrase(day, f));
      cell.BackgroundColor = BaseColor.BLACK;
      cell.HorizontalAlignment = Element.ALIGN_CENTER;
      cell.Colspan = 7;
      table.AddCell(cell);
      // Add the second header row twice
      table.DefaultCell.BackgroundColor = BaseColor.LIGHT_GRAY;
      for (int i = 0; i < 2; i++) {
        table.AddCell("Location");
        table.AddCell("Time");
        table.AddCell("Run Length");
        table.AddCell("Title");
        table.AddCell("Year");
        table.AddCell("Directors");
        table.AddCell("Countries");
      }
      table.DefaultCell.BackgroundColor = null;
      // There are three special rows
      table.HeaderRows = 3;
      // One of them is a footer
      table.FooterRows = 1;
      // Now let's loop over the screenings
      List 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());
        cell = new PdfPCell();
        cell.UseAscender = true;
        cell.UseDescender = true;
        cell.AddElement(PojoToElementFactory.GetDirectorList(movie));
        table.AddCell(cell);
        cell = new PdfPCell();
        cell.UseAscender = true;
        cell.UseDescender = true;
        cell.AddElement(PojoToElementFactory.GetCountryList(movie));
        table.AddCell(cell);
      }
      return table;
    }    
// ===========================================================================
  }
}
HeaderFooter2.cs
/*
 * 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.Chapter04 {
  public class HeaderFooter2 : HeaderFooter1 {
// ===========================================================================
    public override 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 days = PojoFactory.GetDays();
        foreach (string day in days) {
          PdfPTable table = GetTable(day);
          table.SplitLate = false;
          document.Add(table);
          document.NewPage();
        }
      }
    }
// ===========================================================================
  }
}
MemoryTests.cs
/*
 * 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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter04 {
  public class MemoryTests : IWriter {

    /** The resulting report. */
    public readonly String RESULT0 = "test_results.txt";

    /** A resulting PDF file. */
    public readonly String RESULT1
        = "pdfptable_without_memory_management.pdf";
    /** A resulting PDF file. */
    public readonly String RESULT2
        = "pdfptable_with_memory_management.pdf";
    
    private bool test;
    private long memory_use;
    private long initial_memory_use = 0l;
    private long maximum_memory_use = 0l;
    
    /** Path to the resources. */
    public readonly String RESOURCE = Utility.ResourceDirectory+"/posters/{0}.jpg";
    /** The different epochs. */
    public readonly String[] EPOCH = new [] { "Forties", "Fifties", "Sixties", "Seventies", "Eighties", "Nineties", "Twenty-first Century" };
    
    /** The fonts for the title. */
    public readonly Font[] FONT  = new []
    {
        new Font(Font.FontFamily.HELVETICA, 24),
        new Font(Font.FontFamily.HELVETICA, 18),
        new Font(Font.FontFamily.HELVETICA, 14),
        new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD)
    };
    
    
    /**
     * Creates a PDF with a table
     * @param writer the writer to our report file
     * @param filename the PDF that will be created
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    private void CreatePdfWithPdfPTable(StreamWriter writer, Stream doc) {
        // Create a connection to the database
    	//DatabaseConnection connection = new HsqldbConnection("filmfestival"); 
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter.GetInstance(document, doc);
        // step 3
        document.Open();
        // step 4
        // Create a table with 2 columns
        PdfPTable table = new PdfPTable(new float[]{1, 7});
        // Mark the table as not complete
        if (test) table.Complete = false;
        table.WidthPercentage = 100;
        IEnumerable movies = PojoFactory.GetMovies();
        List list;
        PdfPCell cell;
        int count = 0;
        // add information about a movie
        foreach (Movie movie in movies) {
            table.SpacingBefore = 5;
            // add a movie poster
            cell = new PdfPCell(Image.GetInstance(String.Format(RESOURCE, movie.Imdb)), true);
            cell.Border = PdfPCell.NO_BORDER;
            table.AddCell(cell);
            // add movie information
            cell = new PdfPCell();
            Paragraph p = new Paragraph(movie.Title, FilmFonts.BOLD);
            p.Alignment = Element.ALIGN_CENTER;
            p.SpacingBefore = 5;
            p.SpacingAfter = 5;
            cell.AddElement(p);
            cell.Border = PdfPCell.NO_BORDER;
            if (movie.OriginalTitle != null) {
                p = new Paragraph(movie.OriginalTitle, FilmFonts.ITALIC);
                p.Alignment = Element.ALIGN_RIGHT;
                cell.AddElement(p);
            }
            list = PojoToElementFactory.GetDirectorList(movie);
            list.IndentationLeft = 30;
            cell.AddElement(list);
            p = new Paragraph(String.Format("Year: %d", movie.Year), FilmFonts.NORMAL);
            p.IndentationLeft = 15;
            p.Leading = 24;
            cell.AddElement(p);
            p = new Paragraph(String.Format("Run length: %d", movie.Duration), FilmFonts.NORMAL);
            p.Leading = 14;
            p.IndentationLeft = 30;
            cell.AddElement(p);
            list = PojoToElementFactory.GetCountryList(movie);
            list.IndentationLeft = 40;
            cell.AddElement(list);
            table.AddCell(cell);
            // insert a checkpoint every 10 movies
            if (count++ % 10 == 0) {
            	// add the incomplete table to the document
                if (test)
                    document.Add(table);
                Checkpoint(writer);
            }
        }
        // Mark the table as complete
        if (test) table.Complete = true;
        // add the table to the document
        document.Add(table);
        // insert a last checkpoint
        Checkpoint(writer);
        // step 5
        document.Close();
    }
    
    /**
     * Writes a checkpoint to the report file.
     * @param writer the writer to our report file
     */
    private void Checkpoint(StreamWriter writer) {
        memory_use = GetMemoryUse();
        maximum_memory_use = Math.Max(maximum_memory_use, memory_use);
        Println(writer, "memory use: ", memory_use);
    }
    
    /**
     * Resets the maximum memory that is in use
     * @param writer the writer to our report file
     */
    private void ResetMaximum(StreamWriter writer) {
        Println(writer, "maximum: ", maximum_memory_use);
        Println(writer, "total used: ", maximum_memory_use - initial_memory_use);
        maximum_memory_use = 0l;
        GarbageCollect();
        initial_memory_use = GetMemoryUse();
        Println(writer, "initial memory use: ", initial_memory_use);
    }

    /**
     * Writes a line to our report file
     * @param writer the writer to our report file
     * @param message the message to write
     */
    private void Println(StreamWriter writer, String message) {
        try {
            writer.WriteLine(message);
            writer.WriteLine("\n");
            writer.Flush();
        } catch (IOException e) {
            Console.WriteLine(e.StackTrace);
        }
    }
    
    /**
     * Writes a line to our report file
     * @param writer the writer to our report file
     * @param message the message to write
     * @param l a memory value
     */
    private void Println(StreamWriter writer, String message, long l) {
        try {
            writer.WriteLine(message + l);
            writer.WriteLine("\n");
            writer.Flush();
        } catch (IOException e) {
            Console.WriteLine(e.StackTrace);
        }
    }
    
    /**
     * Returns the current memory use.
     * 
     * @return the current memory use
     */
    private static long GetMemoryUse() {
        return (GC.GetTotalMemory(true));
    }
    
    /**
     * Makes sure all garbage is cleared from the memory.
     */
    private static void GarbageCollect() {
        try {
            GC.Collect();
            Thread.Sleep(200);
            GC.WaitForPendingFinalizers();
            Thread.Sleep(200);
            GC.Collect();
            Thread.Sleep(200);
            GC.WaitForPendingFinalizers();
            Thread.Sleep(200);
        } catch (Exception ex) {
            Console.WriteLine(ex.StackTrace);
        }
    }

    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void Main(String[] args) {
        
    }
// ===========================================================================
    public void Write(Stream stream) {
        try
        {
            using (ZipFile zip = new ZipFile())
            {
                using (MemoryStream resultStream = new MemoryStream())
                {
                    using (StreamWriter sw = new StreamWriter(resultStream))
                    {
                        ResetMaximum(sw);
                        using (MemoryStream ms = new MemoryStream())
                        {
                            // step 1
                            test = false;
                            Println(sw, RESULT1);
                            // PDF without memory management
                            CreatePdfWithPdfPTable(sw, ms);
                            ResetMaximum(sw);
                            zip.AddEntry(RESULT1, ms.ToArray());
                        }
                        using (MemoryStream ms = new MemoryStream())
                        {
                            // step 2
                            test = true;
                            Println(sw, RESULT2);
                            // PDF with memory management
                            CreatePdfWithPdfPTable(sw, ms);
                            ResetMaximum(sw);
                            zip.AddEntry(RESULT2, ms.ToArray());
                        }
                        // step 3
                        zip.AddEntry(RESULT0, resultStream.ToArray());
                    }
                }
                zip.Save(stream);
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }
// ===========================================================================
  }
}
PdfCalendar.cs
/*
 * 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 System.util;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.draw;

namespace kuujinbo.iTextInAction2Ed.Chapter04 {
  public class PdfCalendar : IWriter {
// ===========================================================================
    /** The year for which we want to create a calendar */
    public const int YEAR = 2011;
    /** The language code for the calendar
     * change this to set culture-specific info
    */
    public const string LANGUAGE = "en";
    /** Path to the resources. */
    public readonly string RESOURCE = Utility.ResourceCalendar;
    /** resources file. */
    public const string CONTENT = "content.txt";

    public Properties specialDays = new Properties();
    /** Collection with the description of the images */
    public Properties content = new Properties();

    /** A font that is used in the calendar */
    protected Font normal;
    /** A font that is used in the calendar */
    protected Font small;
    /** A font that is used in the calendar */
    protected Font bold;
// ---------------------------------------------------------------------------
    /**
     * Initializes the fonts and collections.
     */
    public PdfCalendar() {
      // fonts
    BaseFont bf_normal = BaseFont.CreateFont(
      "c://windows/fonts/arial.ttf",
        BaseFont.WINANSI, 
        BaseFont.EMBEDDED
      );
      normal = new Font(bf_normal, 16);
      small = new Font(bf_normal, 8);
      BaseFont bf_bold = BaseFont.CreateFont(
        "c://windows/fonts/arialbd.ttf",
        BaseFont.WINANSI,
        BaseFont.EMBEDDED
      );
      bold = new Font(bf_bold, 14);
      // collections
      string year_file = Path.Combine(
        Utility.ResourceCalendar, string.Format("{0}.txt", YEAR)
      );
      if (!File.Exists(year_file)) { 
        throw new ArgumentException(year_file + " NOT FOUND!");
      }
      string content_file = Path.Combine(Utility.ResourceCalendar, CONTENT);
      if (!File.Exists(content_file)) {
        throw new ArgumentException(year_file + " NOT FOUND!");
      }
      using (FileStream fs = new FileStream(
        year_file, FileMode.Open, FileAccess.Read
      ) ) {
        specialDays.Load(fs);
      }
      using (FileStream fs = new FileStream(
        content_file, FileMode.Open, FileAccess.Read
      ) ) {
        content.Load(fs);
      }      
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a PDF document.
     */
    public virtual 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;
        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
          PdfPTable table = new PdfPTable(7);
          table.TotalWidth = 504;
          // add the name of the month
          table.DefaultCell.BackgroundColor = BaseColor.WHITE;
          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 + 18, canvas);
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Draws the image of the month to the calendar.
     * @param canvas the direct content layer
     * @param dt the DateTime (to know which picture to use)
     */
    public void DrawImageAndText(PdfContentByte canvas, DateTime dt) {
      string MM = dt.ToString("MM");
      // get the image
      Image img = Image.GetInstance(Path.Combine(
        RESOURCE, MM + ".jpg"
      ));
      img.ScaleToFit(PageSize.A4.Height, PageSize.A4.Width);
      img.SetAbsolutePosition(
        (PageSize.A4.Height - img.ScaledWidth) / 2,
        (PageSize.A4.Width - img.ScaledHeight) / 2
      );
      canvas.AddImage(img);
      // add metadata
      canvas.SaveState();
      canvas.SetCMYKColorFill(0x00, 0x00, 0x00, 0x80);
      Phrase p = new Phrase(string.Format(
          "{0} - \u00a9 Katharine Osborne",
          content[string.Format("{0}.jpg", dt.ToString("MM"))]
        ),
        small
      );
      ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, p, 5, 5, 0);
      p = new Phrase(
        "Calendar generated using iText - example for the book iText in Action 2nd Edition", 
        small
      );
      ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT, p, 839, 5, 0);
      canvas.RestoreState();
    }
// ---------------------------------------------------------------------------   
    /**
     * 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 PdfPCell GetMonthCell(DateTime dt) {
      PdfPCell cell = new PdfPCell();
      cell.Colspan = 7;
      cell.BackgroundColor = BaseColor.WHITE;
      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 PdfPCell GetDayCell(DateTime dt) {
      PdfPCell cell = new PdfPCell();
      cell.Padding = 3;
      // set the background color, based on the type of day
      cell.BackgroundColor = IsSunday(dt)
        ? BaseColor.GRAY
        : IsSpecialDay(dt)
          ? BaseColor.LIGHT_GRAY
          : BaseColor.WHITE
      ;
      // 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 for Sundays.
     * @param dt a DateTime
     * @return true for Sundays
     */
    public bool IsSunday(DateTime dt) {
      return dt.DayOfWeek == DayOfWeek.Sunday ? true : false;
    }
//// ---------------------------------------------------------------------------       
//    /**
//     * Returns true if the date was found in a list with special days (holidays).
//     * @param calendar a date
//     * @return true for holidays
//     */
    public bool IsSpecialDay(DateTime dt) {
      return dt.DayOfWeek == DayOfWeek.Saturday
        ? true
        : specialDays.ContainsKey(dt.ToString("MMdd"))
          ? true
          : false
      ;
    }    
// ===========================================================================
  }
}
Zhang.cs
/*
 * 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.Chapter04 {
  public class Zhang : 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
        // Create a table and fill it with movies
        IEnumerable movies = PojoFactory.GetMovies(3);
        PdfPTable table = new PdfPTable(new float[] { 1, 5, 5, 1});
        foreach (Movie movie in movies) {
          table.AddCell(movie.Year.ToString());
          table.AddCell(movie.MovieTitle);
          table.AddCell(movie.OriginalTitle);
          table.AddCell(movie.Duration.ToString());
        }
        // set the total width of the table
        table.TotalWidth = 600;
        PdfContentByte canvas = writer.DirectContent;
        // draw the first three columns on one page
        table.WriteSelectedRows(0, 2, 0, -1, 236, 806, canvas);
        document.NewPage();
        // draw the next three columns on the next page
        table.WriteSelectedRows(2, -1, 0, -1, 36, 806, canvas);
      }
    }
// ===========================================================================
  }
}
ColumnTable.cs
/*
 * 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.Chapter04 {
  public class ColumnTable : IWriter {
// ===========================================================================
    public 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
        ColumnText column = new ColumnText(writer.DirectContent);
        List days = PojoFactory.GetDays();
        // COlumn definition
        float[][] x = {
          new float[] { document.Left, document.Left + 380 },
          new float[] { document.Right - 380, document.Right }
        };
        // Loop over the festival days
        foreach (string day in days) {
        // add content to the column
          column.AddElement(GetTable(day));
          int count = 0;
          float height = 0;
          // iText-ONLY, 'Initial value of the status' => 0
          // iTextSharp **DOES NOT** include this member variable
          // int status = ColumnText.START_COLUMN;
          int status = 0;
          // render the column as long as it has content
          while (ColumnText.HasMoreText(status)) {
          // add the top-level header to each new page
            if (count == 0) {
              height = AddHeaderTable(document, day, writer.PageNumber);
            }
            // set the dimensions of the current column
            column.SetSimpleColumn(
              x[count][0], document.Bottom,
              x[count][1], document.Top - height - 10
            );
            // render as much content as possible
            status = column.Go();
            // go to a new page if you've reached the last column
            if (++count > 1) {
              count = 0;
              document.NewPage();
            }
          }
          document.NewPage();
        }
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Add a header table to the document
     * @param document The document to which you want to add a header table
     * @param day The day that needs to be shown in the header table
     * @param page The page number that has to be shown in the header
     * @return the height of the resulting header table
     */
    public float AddHeaderTable(Document document, string day, int page) {
      PdfPTable header = new PdfPTable(3);
      header.WidthPercentage = 100;
      header.DefaultCell.BackgroundColor = BaseColor.BLACK;
      Font font = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD, BaseColor.WHITE);
      Phrase p = new Phrase("Foobar Film Festival", font);
      header.AddCell(p);
      header.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
      p = new Phrase(day, font);
      header.AddCell(p);
      header.DefaultCell.HorizontalAlignment = Element.ALIGN_RIGHT;
      p = new Phrase(string.Format("page {0}", page), font);
      header.AddCell(p);
      document.Add(header);
      return header.TotalHeight;
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a table with movie screenings for a specific day
     * @param connection a connection to the database
     * @param day a 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.UseAscender = true;
      table.DefaultCell.UseDescender = true;
      table.DefaultCell.BackgroundColor = BaseColor.LIGHT_GRAY;
      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 = 2;
      table.FooterRows = 1;
      List 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;
    }    
// ===========================================================================
  }
}
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