Chapter 7: Making documents interactive

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

Files: 
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class NamedActions {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/named_actions.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
    	// Create a table with named actions
        Font symbol = new Font(FontFamily.SYMBOL, 20);
        PdfPTable table = new PdfPTable(4);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        Chunk first = new Chunk(String.valueOf((char)220), symbol);
        first.setAction(new PdfAction(PdfAction.FIRSTPAGE));
        table.addCell(new Phrase(first));
        Chunk previous = new Chunk(String.valueOf((char)172), symbol);
        previous.setAction(new PdfAction(PdfAction.PREVPAGE));
        table.addCell(new Phrase(previous));
        Chunk next = new Chunk(String.valueOf((char)174), symbol);
        next.setAction(new PdfAction(PdfAction.NEXTPAGE));
        table.addCell(new Phrase(next));
        Chunk last = new Chunk(String.valueOf((char)222), symbol);
        last.setAction(new PdfAction(PdfAction.LASTPAGE));
        table.addCell(new Phrase(last));
        table.setTotalWidth(120);
 
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add the table to each page
        PdfContentByte canvas;
        for (int i = 0; i < reader.getNumberOfPages(); ) {
            canvas = stamper.getOverContent(++i);
            table.writeSelectedRows(0, -1, 696, 36, canvas);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new NamedActions().manipulatePdf(MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
 
import part1.chapter02.MovieLinks1;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.SimpleNamedDestination;
 
public class LinkActions {
 
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part2/chapter07/movie_links_1.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part2/chapter07/movie_links_2.pdf";
    /** The resulting XML file. */
    public static final String RESULT3
        = "results/part2/chapter07/destinations.xml";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    protected void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
    	// Open 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
        // Add text with a local destination
        Paragraph p = new Paragraph();
        Chunk top = new Chunk("Country List", FilmFonts.BOLD);
        top.setLocalDestination("top");
        p.add(top);
        document.add(p);
        // Add text with a link to an external URL
        Chunk imdb = new Chunk("Internet Movie Database", FilmFonts.ITALIC);
        imdb.setAction(new PdfAction(new URL("http://www.imdb.com/")));
        p = new Paragraph(
            "Click on a country, and you'll get a list of movies, containing links to the ");
        p.add(imdb);
        p.add(".");
        document.add(p);
        // Add text with a remote goto
        p = new Paragraph("This list can be found in a ");
        Chunk page1 = new Chunk("separate document");
        page1.setAction(new PdfAction("movie_links_1.pdf", 1));
        p.add(page1);
        p.add(".");
        document.add(p);
        document.add(Chunk.NEWLINE);
        // Get a list with countries from the database
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT DISTINCT mc.country_id, c.country, count(*) AS c "
            + "FROM film_country c, film_movie_country mc WHERE c.id = mc.country_id "
            + "GROUP BY mc.country_id, country ORDER BY c DESC");
        // Loop over the countries
        while (rs.next()) {
            Paragraph country = new Paragraph(rs.getString("country"));
            country.add(": ");
            Chunk link = new Chunk(String.format("%d movies", rs.getInt("c")));
            link.setAction(
                PdfAction.gotoRemotePage("movie_links_1.pdf", rs.getString("country_id"), false, true));
            country.add(link);
            document.add(country);
        }
        document.add(Chunk.NEWLINE);
        // Add text with a local goto
        p = new Paragraph("Go to ");
        top = new Chunk("top");
        top.setAction(PdfAction.gotoLocalPage("top", false));
        p.add(top);
        p.add(".");
        document.add(p);
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Create an XML file with named destinations
     * @param src The path to the PDF with the destinations
     * @param dest The path to the XML file
     * @throws IOException
     */
    public void createXml(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        HashMap<String,String> map = SimpleNamedDestination.getNamedDestination(reader, false);
        SimpleNamedDestination.exportToXML(map, new FileOutputStream(dest),
                "ISO8859-1", true);
        reader.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 MovieLinks1().createPdf(RESULT1);
        LinkActions actions = new LinkActions();
        actions.createPdf(RESULT2);
        actions.createXml(RESULT1, RESULT3);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.SimpleNamedDestination;
 
import part1.chapter02.MovieLinks1;
 
public class ConcatenateNamedDestinations {
 
    /** The resulting PDF file. */
    public static String RESULT1
        = "results/part2/chapter07/concatenated_links_1.pdf";
    /** The resulting PDF file. */
    public static String RESULT2
         = "results/part2/chapter07/concatenated_links_2.pdf";
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
    	// Use previous examples to create PDF files
        new MovieLinks1().createPdf(LinkActions.RESULT1);
        new LinkActions().createPdf(LinkActions.RESULT2);
        // Create readers.
        PdfReader[] readers = {
                new PdfReader(LinkActions.RESULT2),
                new PdfReader(LinkActions.RESULT1) };
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT1));
        // step 3
        document.open();
        // step 4
        int n;
        // copy the pages of the different PDFs into one document
        for (int i = 0; i < readers.length; i++) {
            readers[i].consolidateNamedDestinations();
            n = readers[i].getNumberOfPages();
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(readers[i], ++page));
            }
        }
        // Add named destination  
        copy.addNamedDestinations(
            // from the second document
            SimpleNamedDestination.getNamedDestination(readers[1], false),
            // using the page count of the first document as offset
            readers[0].getNumberOfPages());
        // step 5
        document.close();
        readers[0].close();
        readers[1].close();
 
        // Create a reader
        PdfReader reader = new PdfReader(RESULT1);
        // Convert the remote destinations into local destinations
        reader.makeRemoteNamedDestinationsLocal();
        // Create a new PDF containing the local destinations
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(RESULT2));
        stamper.close();
        reader.close();
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableDestinations {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_destinations.pdf";
    /** The font that is used for the navigation links. */
    public static final Font SYMBOL = new Font(FontFamily.SYMBOL, 20);
    /** A list to cache all the possible actions */
    public List<PdfAction> actions;
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
    	// Create the reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create the stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Make a list with all the possible actions
        actions = new ArrayList<PdfAction>();
        PdfDestination d;
        for (int i = 0; i < n; ) {
            d = new PdfDestination(PdfDestination.FIT);
            actions.add(PdfAction.gotoLocalPage(++i, d, stamper.getWriter()));
        }
        // Add a navigation table to every page
        PdfContentByte canvas;
        for (int i = 0; i < n; ) {
            canvas = stamper.getOverContent(++i);
            createNavigationTable(i, n).writeSelectedRows(0, -1, 696, 36, canvas);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Create a table that can be used as a footer
     * @param pagenumber the page that will use the table as footer
     * @param total the total number of pages
     * @return a tabel
     */
    public PdfPTable createNavigationTable(int pagenumber, int total) {
        PdfPTable table = new PdfPTable(4);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        Chunk first = new Chunk(String.valueOf((char)220), SYMBOL);
        first.setAction(actions.get(0));
        table.addCell(new Phrase(first));
        Chunk previous = new Chunk(String.valueOf((char)172), SYMBOL);
        previous.setAction(actions.get(pagenumber - 2 < 0 ? 0 : pagenumber - 2));
        table.addCell(new Phrase(previous));
        Chunk next = new Chunk(String.valueOf((char)174), SYMBOL);
        next.setAction(actions.get(pagenumber >= total ? total - 1 : pagenumber));
        table.addCell(new Phrase(next));
        Chunk last = new Chunk(String.valueOf((char)222), SYMBOL);
        last.setAction(actions.get(total - 1));
        table.addCell(new Phrase(last));
        table.setTotalWidth(120);
        return table;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */   
    public static void main(String[] args) 
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new TimetableDestinations().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import part1.chapter01.HelloWorld;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class AddVersionChecker {
 
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/version_checker.pdf";
    /** Path to a resource. */
    public static final String RESOURCE
        = "resources/js/viewer_version.js";
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
    	// Use a previous example to create a PDF
        HelloWorld.main(args);
        // Create a reader
        PdfReader reader = new PdfReader(HelloWorld.RESULT);
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(RESULT));
        // Add some javascript
        stamper.addJavaScript(Utilities.readFileToString(RESOURCE));
        // Close the stamper
        stamper.close();
        reader.close();
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
import part1.chapter04.NestedTables;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
 
public class FindDirectors {
 
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/find_directors.pdf";
 
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/js/find_director.js";
 
    /**
     * Creates a PDF file with director names.
     * @param filename the name of the PDF file that needs to be created.
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
    	// Create a database connection and statement
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Statement stm = connection.createStatement();
    	// step 1
        Document tmp = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(tmp, baos);
        // step 3
        tmp.open();
        // step 4
        ResultSet rs = stm.executeQuery(
           "SELECT name, given_name FROM film_director ORDER BY name, given_name");
        while (rs.next()) {
            tmp.add(createDirectorParagraph(writer, rs));
        }
        // step 5
        tmp.close();
        // Close the database connection and statement
        stm.close();
        connection.close();
 
        // Create readers
        PdfReader[] readers = {
                new PdfReader(baos.toByteArray()),
                new PdfReader(NestedTables.RESULT) };
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        copy.addJavaScript(Utilities.readFileToString(RESOURCE));
        int n;
        for (int i = 0; i < readers.length; i++) {
            n = readers[i].getNumberOfPages();
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(readers[i], ++page));
            }
        }
        // step 5
        document.close();
        readers[0].close();
        readers[1].close();
    }
 
    /**
     * Creates a Phrase with the name and given name of a director
     * using different fonts.
     * @param rs the ResultSet containing director records.
     */
    public Paragraph createDirectorParagraph(PdfWriter writer, ResultSet rs)
        throws UnsupportedEncodingException, SQLException {
        String n = new String(rs.getBytes("name"), "UTF-8");
        Chunk name = new Chunk(n);
        name.setAction(PdfAction.javaScript(
                String.format("findDirector('%s');", n), writer));
        name.append(", ");
        name.append(new String(rs.getBytes("given_name"), "UTF-8"));
        return new Paragraph(name);
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        NestedTables.main(args);
        new FindDirectors().createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfWriter;
 
public class LaunchAction {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/launch_action.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
    throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph(new Chunk(
            "Click to open test.txt in Notepad.")
            .setAction(new PdfAction("c:/windows/notepad.exe",
            "test.txt", "open", "C:\\itext-core\\book\\resources\\txt")));
        document.add(p);
        // 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 LaunchAction().createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class PrintTimeTable {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/print_timetable.pdf";
 
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/js/print_page.js";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
    	// Create the reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create the stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add JavaScript
        stamper.addJavaScript(Utilities.readFileToString(RESOURCE));
        // Create a Chunk with a chained action
        PdfContentByte canvas;
        Chunk chunk = new Chunk("print this page");
        PdfAction action = PdfAction.javaScript(
            "app.alert('Think before you print!');", stamper.getWriter());
        action.next(PdfAction.javaScript(
            "printCurrentPage(this.pageNum);", stamper.getWriter()));
        action.next(new PdfAction("http://www.panda.org/savepaper/"));
        chunk.setAction(action);
        Phrase phrase = new Phrase(chunk);
        // Add this Chunk to every page
        for (int i = 0; i < n; ) {
            canvas = stamper.getOverContent(++i);
            ColumnText.showTextAligned(
                canvas, Element.ALIGN_RIGHT, phrase, 816, 18, 0);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new PrintTimeTable().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class EventsAndActions {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/events_and_actions.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
    	// Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader,
                new FileOutputStream(dest));
        // Get the writer (to add actions and annotations)
        PdfWriter writer = stamper.getWriter();
        PdfAction action = PdfAction.gotoLocalPage(2,
            new PdfDestination(PdfDestination.FIT), writer);
        writer.setOpenAction(action);
        action = PdfAction.javaScript(
            "app.alert('Think before you print');", writer);
        writer.setAdditionalAction(PdfWriter.WILL_PRINT, action);
        action = PdfAction.javaScript(
            "app.alert('Think again next time!');", writer);
        writer.setAdditionalAction(PdfWriter.DID_PRINT, action);
        action = PdfAction.javaScript(
            "app.alert('We hope you enjoy the festival');", writer);
        writer.setAdditionalAction(PdfWriter.DOCUMENT_CLOSE, action);
        action = PdfAction.javaScript(
            "app.alert('This day is reserved for people with an accreditation "
            + "or an invitation.');", writer);
        stamper.setPageAction(PdfWriter.PAGE_OPEN, action, 1);
        action = PdfAction.javaScript(
            "app.alert('You can buy tickets for all the other days');", writer);
        stamper.setPageAction(PdfWriter.PAGE_CLOSE, action, 1);
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new EventsAndActions().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
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.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.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfOutline;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.pdf.SimpleBookmark;
 
public class CreateOutlineTree {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/outline_tree.pdf";
    /** An XML representing the outline tree */
    public static final String RESULTXML
        = "results/part2/chapter07/outline_tree.xml";
    /** Pattern of the IMDB urls */
    public static final String RESOURCE
        = "http://imdb.com/title/tt%s/";
    /** JavaScript snippet. */
    public static final String INFO
        = "app.alert('Movie produced in %s; run length: %s');";
 
    /**
     * 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));
        writer.setViewerPreferences(PdfWriter.PageModeUseOutlines);
        // step 3
        document.open();
        // step 4
        PdfOutline root = writer.getRootOutline();
        PdfOutline movieBookmark;
        PdfOutline link;
        String title;
        List<Movie> movies = PojoFactory.getMovies(connection);
        for (Movie movie : movies) {
            title = movie.getMovieTitle();
            if ("3-Iron".equals(title))
                title = "\ube48\uc9d1";
            movieBookmark = new PdfOutline(root, 
                new PdfDestination(
                    PdfDestination.FITH, writer.getVerticalPosition(true)),
                title, true);
            movieBookmark.setStyle(Font.BOLD);
            link = new PdfOutline(movieBookmark,
                new PdfAction(String.format(RESOURCE, movie.getImdb())),
                "link to IMDB");
            link.setColor(BaseColor.BLUE);
            new PdfOutline(movieBookmark,
                PdfAction.javaScript(
                    String.format(INFO, movie.getYear(), movie.getDuration()), writer),
                    "instant info");
            document.add(new Paragraph(movie.getMovieTitle()));
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Creates an XML file with the bookmarks of a PDF file.
     * @param src the path to the PDF file with the bookmarks
     * @param dest the path to the XML file
     * @throws IOException
     */
    public void createXml(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader);
        SimpleBookmark.exportToXML(list,
                new FileOutputStream(dest), "ISO8859-1", true);
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args) throws IOException, DocumentException, SQLException {
        CreateOutlineTree example = new CreateOutlineTree();
        example.createPdf(RESULT);
        example.createXml(RESULT, RESULTXML);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import part1.chapter03.MovieTemplates;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class BookmarkedTimeTable {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/time_table_bookmarks.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Create a list with bookmarks
        ArrayList<HashMap<String, Object>> outlines = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> map = new HashMap<String, Object>();
        outlines.add(map);
        map.put("Title", "Calendar");
        ArrayList<HashMap<String, Object>> kids = new ArrayList<HashMap<String, Object>>();
        map.put("Kids", kids);
        int page = 1;
        List<Date> days = PojoFactory.getDays(connection);
        for (Date day : days) {
            HashMap<String, Object> kid = new HashMap<String, Object>();
            kids.add(kid);
            kid.put("Title", day.toString());
            kid.put("Action", "GoTo");
            kid.put("Page", String.format("%d Fit", page++));
        }
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.setOutlines(outlines);
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new BookmarkedTimeTable().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import part1.chapter02.MovieHistory;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.SimpleBookmark;
 
public class ConcatenateBookmarks {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/concatenated_bookmarks.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String[] src, String dest)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfCopy copy
            = new PdfCopy(document, new FileOutputStream(dest));
        // step 3
        document.open();
        // step 4
        PdfReader reader;
        int page_offset = 0;
        int n;
        // Create a list for the bookmarks
        ArrayList<HashMap<String, Object>> bookmarks = new ArrayList<HashMap<String, Object>>();
        List<HashMap<String, Object>> tmp;
        for (int i  = 0; i < src.length; i++) {
            reader = new PdfReader(src[i]);
            // merge the bookmarks
            tmp = SimpleBookmark.getBookmark(reader);
            SimpleBookmark.shiftPageNumbers(tmp, page_offset, null);
            bookmarks.addAll(tmp);
            // add the pages
            n = reader.getNumberOfPages();
            page_offset += n;
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(reader, ++page));
            }
            copy.freeReader(reader);
            reader.close();
        }
        // Add the merged bookmarks
        copy.setOutlines(bookmarks);
        // step 5
        document.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        BookmarkedTimeTable.main(args);
        MovieHistory.main(args);
        new ConcatenateBookmarks().manipulatePdf(
            new String[]{BookmarkedTimeTable.RESULT, MovieHistory.RESULT},
            RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Annotation;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_1.pdf";
    /** Pattern for an info String. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLExcception
     */
    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
        for (Movie movie : PojoFactory.getMovies(connection)) {
            document.add(new Phrase(movie.getMovieTitle()));
            document.add(new Annotation(movie.getTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration())));
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieAnnotations1 example = new MovieAnnotations1();
        example.createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations2 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_2.pdf";
    /** Pattern for an info String. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    /**
     * 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 {
    	// Open the 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
        Phrase phrase;
        Chunk chunk;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            phrase = new Phrase(movie.getMovieTitle());
            chunk = new Chunk("\u00a0");
            chunk.setAnnotation(
                PdfAnnotation.createText(writer, null, movie.getMovieTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration()),
                false, "Comment"));
            phrase.add(chunk);
            document.add(phrase);
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // 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 {
        MovieAnnotations2 example = new MovieAnnotations2();
        example.createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBoolean;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.VerticalPositionMark;
 
public class GenericAnnotations extends PdfPageEventHelper {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/generic_annotations.pdf";
    /** Possible icons. */
    public static final String[] ICONS = {
        "Comment", "Key", "Note", "Help", "NewParagraph", "Paragraph", "Insert"
    };
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setPageEvent(new GenericAnnotations());
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph();
        Chunk chunk;
        Chunk tab = new Chunk(new VerticalPositionMark());
        for (int i = 0; i < ICONS.length; i++) {
            chunk = new Chunk(ICONS[i]);
            chunk.setGenericTag(ICONS[i]);
            p.add(chunk);
            p.add(tab);
        }
        document.add(p);
        // step 5
        document.close();
    }
 
    /**
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onGenericTag(
     *      com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document,
     *      com.itextpdf.text.Rectangle, java.lang.String)
     */
    @Override
    public void onGenericTag(PdfWriter writer,
        Document document, Rectangle rect, String text) {
        PdfAnnotation annotation = new PdfAnnotation(writer,
            new Rectangle(
                rect.getRight() + 10, rect.getBottom(),
                rect.getRight() + 30, rect.getTop()));
        annotation.setTitle("Text annotation");
        annotation.put(PdfName.SUBTYPE, PdfName.TEXT);
        annotation.put(PdfName.OPEN, PdfBoolean.PDFFALSE);
        annotation.put(PdfName.CONTENTS,
            new PdfString(String.format("Icon: %s", text)));
        annotation.put(PdfName.NAME, new PdfName(text));
        writer.addAnnotation(annotation);
    }
 
}
/*
 * 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 part2.chapter07;
 
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.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.html.WebColors;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_help.pdf";
    /** A pattern for an info string. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add the annotations
        int page = 1;
        Rectangle rect;
        PdfAnnotation annotation;
        Movie movie;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                movie = screening.getMovie();
                rect = getPosition(screening);
                annotation = PdfAnnotation.createText(
                    stamper.getWriter(), rect, movie.getMovieTitle(),
                    String.format(INFO, movie.getYear(), movie.getDuration()),
                    false, "Help");
                annotation.setColor(WebColors.getRGBColor(
                    "#" + movie.getEntry().getCategory().getColor()));
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Calculates the position of a rectangle corresponding with a screening.
     * @param    screening    a screening POJO, contains a movie
     * @return    a Rectangle
     */
    protected Rectangle getPosition(Screening screening) {
        float llx, lly, urx, ury;
        long minutesAfter930 = (screening.getTime().getTime() - TIME930) / 60000l;
        llx = OFFSET_LEFT + (MINUTE * minutesAfter930);
        int location = locations.indexOf(screening.getLocation()) + 1;
        lly = OFFSET_BOTTOM + (LOCATIONS - location) * HEIGHT_LOCATION;
        urx = llx + MINUTE * screening.getMovie().getDuration();
        ury = lly + HEIGHT_LOCATION;
        Rectangle rect = new Rectangle(llx, lly, urx, ury);
        return rect;
    }
 
    /** A list containing all the locations. */
    protected List<String> locations;
 
    /** The number of locations on our time table. */
    public static final int LOCATIONS = 9;
    /** The number of time slots on our time table. */
    public static final int TIMESLOTS = 32;
    /** The "offset time" for our calendar sheets. */
    public static final long TIME930 = 30600000l;
    /** The offset to the left of our time table. */
    public static final float OFFSET_LEFT = 76;
    /** The width of our time table. */
    public static final float WIDTH = 740;
    /** The width of a time slot. */
    public static final float WIDTH_TIMESLOT = WIDTH / TIMESLOTS;
    /** The width of one minute. */
    public static final float MINUTE = WIDTH_TIMESLOT / 30f;
    /** The offset from the bottom of our time table. */
    public static final float OFFSET_BOTTOM = 36;
    /** The height of our time table */
    public static final float HEIGHT = 504;
    /** The height of a bar showing the movies at one specific location. */
    public static final float HEIGHT_LOCATION = HEIGHT / LOCATIONS;
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new TimetableAnnotations1().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.Annotation;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MoviePosters1 {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/movie_posters_1.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    /** Path to IMDB. */
    public static final String IMDB
        = "http://imdb.com/title/tt%s/";
 
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
    	DatabaseConnection connection = new HsqldbConnection("filmfestival");
    	// step 1
        Document document = new Document(PageSize.A4);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfContentByte canvas = writer.getDirectContent();
        // Create a reusable XObject
        PdfTemplate celluloid = canvas.createTemplate(595, 84.2f);
        celluloid.rectangle(8, 8, 579, 68);
        for (float f = 8.25f; f < 581; f+= 6.5f) {
            celluloid.roundRectangle(f, 8.5f, 6, 3, 1.5f);
            celluloid.roundRectangle(f, 72.5f, 6, 3, 1.5f);
        }
        celluloid.setGrayFill(0.1f);
        celluloid.eoFill();
        writer.releaseTemplate(celluloid);
        // Add the XObject ten times
        for (int i = 0; i < 10; i++) {
            canvas.addTemplate(celluloid, 0, i * 84.2f);
        }
        // Add the movie posters
        Image img;
        Annotation annotation;
        float x = 11.5f;
        float y = 769.7f;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            img = Image.getInstance(String.format(RESOURCE, movie.getImdb()));
            img.scaleToFit(1000, 60);
            img.setAbsolutePosition(x + (45 - img.getScaledWidth()) / 2, y);
            annotation = new Annotation(0, 0, 0, 0,
                String.format(IMDB, movie.getImdb()));
            img.setAnnotation(annotation);
            canvas.addImage(img);
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
            }
        }
        // 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, SQLException, DocumentException {
        new MoviePosters1().createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations2 extends TimetableAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_links.pdf";
    /** Path to IMDB. */
    public static final String IMDB
        = "http://imdb.com/title/tt%s/";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add annotations for every screening
        int page = 1;
        Rectangle rect;
        PdfAnnotation annotation;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                rect = getPosition(screening);
                annotation = PdfAnnotation.createLink(
                    stamper.getWriter(), rect, PdfAnnotation.HIGHLIGHT_INVERT,
                    new PdfAction(String.format(IMDB, screening.getMovie().getImdb())));
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.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 {
        MovieTemplates.main(args);
        new TimetableAnnotations2().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations3 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_3.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
 
    /**
     * 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
        Phrase phrase;
        Chunk chunk;
        PdfAnnotation annotation;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            phrase = new Phrase(movie.getMovieTitle());
            chunk = new Chunk("\u00a0\u00a0");
            annotation = PdfAnnotation.createFileAttachment(writer, null,
                    movie.getMovieTitle(), null,
                    String.format(RESOURCE, movie.getImdb()),
                    String.format("img_%s.jpg", movie.getImdb()));
            annotation.put(PdfName.NAME, new PdfString("Paperclip"));
            chunk.setAnnotation(annotation);
            phrase.add(chunk);
            document.add(phrase);
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // 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 {
        MovieAnnotations3 example = new MovieAnnotations3();
        example.createPdf(RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
 
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.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBorderArray;
import com.itextpdf.text.pdf.PdfBorderDictionary;
import com.itextpdf.text.pdf.PdfDashPattern;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.BaseColor;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations3 extends TimetableAnnotations1 {
    /** The resulting PDF file. */
    public static final String RESULT = "results/part2/chapter07/timetable_tickets.pdf";
    /** Path to IMDB. */
    public static final String IMDB = "http://imdb.com/title/tt%s/";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Loop over the days and screenings
        int page = 1;
        Rectangle rect;
        float top;
        PdfAnnotation annotation;
        Movie movie;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                rect = getPosition(screening);
                movie = screening.getMovie();
                // Annotation for press previews
                if (screening.isPress()) {
                    annotation = PdfAnnotation.createStamp(stamper.getWriter(),
                        rect, "Press only", "NotForPublicRelease");
                    annotation.setColor(BaseColor.BLACK);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                }
                // Annotation for screenings that are sold out
                else if (isSoldOut(screening)) {
                    top = reader.getPageSizeWithRotation(page).getTop();
                    annotation = PdfAnnotation.createLine(
                        stamper.getWriter(), rect, "SOLD OUT",
                        top - rect.getTop(), rect.getRight(),
                        top - rect.getBottom(), rect.getLeft());
                    annotation.setTitle(movie.getMovieTitle());
                    annotation.setColor(BaseColor.WHITE);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                    annotation.setBorderStyle(
                        new PdfBorderDictionary(5, PdfBorderDictionary.STYLE_SOLID));
                }
                // Annotation for screenings with tickets available
                else {
                    annotation = PdfAnnotation.createSquareCircle(
                        stamper.getWriter(), rect, "Tickets available", true);
                    annotation.setTitle(movie.getMovieTitle());
                    annotation.setColor(BaseColor.BLUE);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                    annotation.setBorder(new PdfBorderArray(0, 0, 2, new PdfDashPattern()));
                }
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Checks if the screening has been sold out.
     * @param screening a Screening POJO
     * @return true if the screening has been sold out.
     */
    public boolean isSoldOut(Screening screening) {
        if (screening.getMovie().getMovieTitle().startsWith("L"))
            return true;
        return false;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) 
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new TimetableAnnotations3().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.BaseColor;
 
public class ButtonsActions {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/save_mail_timetable.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
    	// Create a reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(dest));
        // Create pushbutton 1
        PushbuttonField saveAs =
            new PushbuttonField(stamper.getWriter(),
                new Rectangle(636, 10, 716, 30), "Save");
        saveAs.setBorderColor(BaseColor.BLACK);
        saveAs.setText("Save");
        saveAs.setTextColor(BaseColor.RED);
        saveAs.setLayout(PushbuttonField.LAYOUT_LABEL_ONLY);
        saveAs.setRotation(90);
        PdfAnnotation saveAsButton = saveAs.getField();
        saveAsButton.setAction(PdfAction.javaScript(
            "app.execMenuItem('SaveAs')", stamper.getWriter()));
        // Create pushbutton 2
        PushbuttonField mail
            = new PushbuttonField(stamper.getWriter(),
                new Rectangle(736, 10, 816, 30), "Mail");
        mail.setBorderColor(BaseColor.BLACK);
        mail.setText("Mail");
        mail.setTextColor(BaseColor.RED);
        mail.setLayout(PushbuttonField.LAYOUT_LABEL_ONLY);
        mail.setRotation(90);
        PdfAnnotation mailButton = mail.getField();
        mailButton.setAction(PdfAction.javaScript(
            "app.execMenuItem('AcroSendMail:SendMail')", stamper.getWriter()));
        // Add the annotations to every page of the document
        for (int page = 1; page <= n; page++) {
            stamper.addAnnotation(saveAsButton, page);
            stamper.addAnnotation(mailButton, page);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new ButtonsActions().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import part1.chapter04.NestedTables;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.BaseColor;
 
public class Advertisement {
 
    /** Path to a resource. */
    public static final String RESOURCE = "resources/pdfs/hero.pdf";
    /** Path to a resource. */
    public static final String IMAGE = "resources/img/close.png";
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/advertisement.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String resource, String dest)
        throws IOException, DocumentException {
    	// Create a reader for the original document
        PdfReader reader = new PdfReader(src);
        // Create a reader for the advertisement resource
        PdfReader ad = new PdfReader(resource);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Create the advertisement annotation for the menubar
        Rectangle rect = new Rectangle(400, 772, 545, 792);
        PushbuttonField button = new PushbuttonField(
            stamper.getWriter(), rect, "click");
        button.setBackgroundColor(BaseColor.RED);
        button.setBorderColor(BaseColor.RED);
        button.setFontSize(10);
        button.setText("Close this advertisement");
        button.setImage(Image.getInstance(IMAGE));
        button.setLayout(PushbuttonField.LAYOUT_LABEL_LEFT_ICON_RIGHT);
        button.setIconHorizontalAdjustment(1);
        PdfFormField menubar = button.getField();
        String js = "var f1 = getField('click'); f1.display = display.hidden;"
            + "var f2 = getField('advertisement'); f2.display = display.hidden;";
        menubar.setAction(PdfAction.javaScript(js, stamper.getWriter()));
        // Add the annotation
        stamper.addAnnotation(menubar, 1);
        // Create the advertisement annotation for the content
        rect = new Rectangle(400, 550, 545, 772);
        button = new PushbuttonField(
            stamper.getWriter(), rect, "advertisement");
        button.setBackgroundColor(BaseColor.WHITE);
        button.setBorderColor(BaseColor.RED);
        button.setText("Buy the book iText in Action 2nd edition");
        button.setTemplate(stamper.getImportedPage(ad, 1));
        button.setLayout(PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM);
        PdfFormField advertisement = button.getField();
        advertisement.setAction(
            new PdfAction("http://www.1t3xt.com/docs/book.php"));
        // Add the annotation
        stamper.addAnnotation(advertisement, 1);
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, DocumentException, IOException {
        NestedTables.main(args);
        new Advertisement().manipulatePdf(
            NestedTables.RESULT, RESOURCE, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
 
public class MoviePosters2 {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/movie_posters_2.pdf";
    /** A pattern for an info string. */
    public static final String INFO = "Movie produced in %s; run length: %s";
    /** A JavaScript snippet */
    public static final String JS1 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%1$s'); t.popupOpen = true; "
    	+ "var w = this.getField('b%1$s'); w.setFocus();";
    /** A JavaScript snippet */
    public static final String JS2 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%s'); t.popupOpen = false;";
 
    /**
     * 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 manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Loop over all the movies to add a popup annotation
        List<Movie> movies = PojoFactory.getMovies(connection);
        Image img;
        float x = 11.5f;
        float y = 769.7f;
        float llx, lly, urx, ury;
        for (Movie movie : movies) {
            img = Image.getInstance(String.format(MoviePosters1.RESOURCE, movie.getImdb()));
            img.scaleToFit(1000, 60);
            llx = x + (45 - img.getScaledWidth()) / 2;
            lly = y;
            urx = x + img.getScaledWidth();
            ury = y + img.getScaledHeight();
            addPopup(stamper, new Rectangle(llx, lly, urx, ury),
                movie.getMovieTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration()), movie.getImdb());
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
            }
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Adds a popup.
     * @param stamper the PdfStamper to which the annotation needs to be added
     * @param rect the position of the annotation
     * @param title the annotation title
     * @param contents the annotation content
     * @param imdb the IMDB number of the movie used as name of the annotation
     * @throws IOException
     * @throws DocumentException
     */
    public void addPopup(PdfStamper stamper, Rectangle rect,
        String title, String contents, String imdb)
        throws IOException, DocumentException {
    	// Create the text annotation
        PdfAnnotation text = PdfAnnotation.createText(stamper.getWriter(),
            rect, title, contents, false, "Comment");
        text.setName(String.format("IMDB%s", imdb));
        text.setFlags(PdfAnnotation.FLAGS_READONLY | PdfAnnotation.FLAGS_NOVIEW);
        // Create the popup annotation
        PdfAnnotation popup = PdfAnnotation.createPopup(stamper.getWriter(),
            new Rectangle(rect.getLeft() + 10, rect.getBottom() + 10,
                rect.getLeft() + 200, rect.getBottom() + 100), null, false);
        // Add the text annotation to the popup
        popup.put(PdfName.PARENT, text.getIndirectReference());
        // Declare the popup annotation as popup for the text
        text.put(PdfName.POPUP, popup.getIndirectReference());
        // Add both annotations
        stamper.addAnnotation(text, 1);
        stamper.addAnnotation(popup, 1);
        // Create a button field
        PushbuttonField field = new PushbuttonField(
                stamper.getWriter(), rect,
                String.format("b%s", imdb));
        PdfAnnotation widget = field.getField();
        // Show the popup onMouseEnter
        PdfAction enter = PdfAction.javaScript(
            String.format(JS1, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.E, enter);
        // Hide the popup onMouseExit
        PdfAction exit = PdfAction.javaScript(
            String.format(JS2, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.X, exit);
        // Add the button annotation
        stamper.addAnnotation(widget, 1);
 
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        MoviePosters1.main(args);
        new MoviePosters2().manipulatePdf(MoviePosters1.RESULT, RESULT);
    }
}
/*
 * 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 part2.chapter07;
 
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.Rectangle;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfAppearance;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
 
public class Calculator {
    /** The resulting PDF. */
    public static final String RESULT = "results/part2/chapter07/calculator.pdf";
    /** Path to the resource. */
    public static final String RESOURCE = "resources/js/calculator.js";
 
    /** The font that will be used in the appearances. */
    public BaseFont bf;
    /** Position of the digits */
    Rectangle[] digits = new Rectangle[10];
    /** Position of the operators. */
    Rectangle plus, minus, mult, div, equals;
    /** Position of the other annotations */
    Rectangle clearEntry, clear, result, move;
 
    /**
     * Initializes the font
     * @throws DocumentException
     * @throws IOException
     */
    public void initializeFont() throws DocumentException, IOException {
        bf = BaseFont.createFont();
    }
 
    /**
     * Initializes the rectangles for the calculator keys.
     */
    public void initializeRectangles() {
        digits[0] = createRectangle(3, 1, 1, 1);
        digits[1] = createRectangle(1, 3, 1, 1);
        digits[2] = createRectangle(3, 3, 1, 1);
        digits[3] = createRectangle(5, 3, 1, 1);
        digits[4] = createRectangle(1, 5, 1, 1);
        digits[5] = createRectangle(3, 5, 1, 1);
        digits[6] = createRectangle(5, 5, 1, 1);
        digits[7] = createRectangle(1, 7, 1, 1);
        digits[8] = createRectangle(3, 7, 1, 1);
        digits[9] = createRectangle(5, 7, 1, 1);
        plus = createRectangle(7, 7, 1, 1);
        minus = createRectangle(9, 7, 1, 1);
        mult = createRectangle(7, 5, 1, 1);
        div = createRectangle(9, 5, 1, 1);
        equals = createRectangle(7, 1, 3, 1);
        clearEntry = createRectangle(7, 9, 1, 1);
        clear = createRectangle(9, 9, 1, 1);
        result = createRectangle(1, 9, 5, 1);
        move = createRectangle(8, 3, 1, 1);
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(new Rectangle(360, 360));
        // step 2
        PdfWriter writer =
            PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        writer.addJavaScript(Utilities.readFileToString(RESOURCE));
        // step 4
        // add the keys for the digits
        for (int i = 0; i < 10; i++) {
            addPushButton(writer, digits[i],
                String.valueOf(i), "this.augment(" + i + ")");
        }
        // add the keys for the operators
        addPushButton(writer, plus, "+", "this.register('+')");
        addPushButton(writer, minus, "-", "this.register('-')");
        addPushButton(writer, mult, "x", "this.register('*')");
        addPushButton(writer, div, ":", "this.register('/')");
        addPushButton(writer, equals, "=", "this.calculateResult()");
        // add the other keys
        addPushButton(writer, clearEntry, "CE", "this.reset(false)");
        addPushButton(writer, clear, "C", "this.reset(true)");
        addTextField(writer, result, "result");
        addTextField(writer, move, "move");
        // step 5
        document.close();
    }
 
    /**
     * Add a text field.
     * @param writer the PdfWriter
     * @param rect the position of the text field
     * @param name the name of the text field
     */
    public void addTextField(PdfWriter writer, Rectangle rect, String name) {
        PdfFormField field = PdfFormField.createTextField(writer, false, false, 0);
        field.setFieldName(name);
        field.setWidget(rect, PdfAnnotation.HIGHLIGHT_NONE);
        field.setQuadding(PdfFormField.Q_RIGHT);
        field.setFieldFlags(PdfFormField.FF_READ_ONLY);
        writer.addAnnotation(field);
    }
 
    /**
     * Create a pushbutton for a key
     * @param writer the PdfWriter
     * @param rect the position of the key
     * @param btn the label for the key
     * @param script the script to be executed when the button is pushed
     */
    public void addPushButton(PdfWriter writer, Rectangle rect,
        String btn, String script) {
        float w = rect.getWidth();
        float h = rect.getHeight();
        PdfFormField pushbutton = PdfFormField.createPushButton(writer);
        pushbutton.setFieldName("btn_" + btn);
        pushbutton.setWidget(rect, PdfAnnotation.HIGHLIGHT_PUSH);
        PdfContentByte cb = writer.getDirectContent();
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_NORMAL,
                createAppearance(cb, btn, BaseColor.GRAY, w, h));
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_ROLLOVER,
                createAppearance(cb, btn, BaseColor.RED, w, h));
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_DOWN,
                createAppearance(cb, btn, BaseColor.BLUE, w, h));
        pushbutton.setAdditionalActions(PdfName.U,
                PdfAction.javaScript(script, writer));
        pushbutton.setAdditionalActions(PdfName.E, PdfAction.javaScript(
                "this.showMove('" + btn + "');", writer));
        pushbutton.setAdditionalActions(PdfName.X, PdfAction.javaScript(
                "this.showMove(' ');", writer));
        writer.addAnnotation(pushbutton);
    }
 
    /**
     * Creates an appearance for a key
     * @param cb the canvas
     * @param btn the label for the key
     * @param color the color of the key
     * @param w the width
     * @param h the height
     * @return an appearance
     */
    public PdfAppearance createAppearance(
        PdfContentByte cb, String btn, BaseColor color, float w, float h) {
        PdfAppearance app = cb.createAppearance(w, h);
        app.setColorFill(color);
        app.rectangle(2, 2, w - 4, h - 4);
        app.fill();
        app.beginText();
        app.setColorFill(BaseColor.BLACK);
        app.setFontAndSize(bf, h / 2);
        app.showTextAligned(Element.ALIGN_CENTER, btn, w / 2, h / 4, 0);
        app.endText();
        return app;
    }
 
    /**
     * Create a rectangle object for a key.
     * @param column column of the key on the key pad
     * @param row row of the key on the key pad
     * @param width width of the key
     * @param height height of the key
     * @return a rectangle defining the position of a key.
     */
    public Rectangle createRectangle(int column, int row, int width,
            int height) {
        column = column * 36 - 18;
        row = row * 36 - 18;
        return new Rectangle(column, row,
            column + width * 36, row + height * 36);
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        Calculator calc = new Calculator();
        calc.initializeFont();
        calc.initializeRectangles();
        calc.createPdf(RESULT);
    }
}
File nameRaw URLUpdated
NamedActions.javaNamedActions.java2015-10-10 2:58 pm
LinkActions.javaLinkActions.java2015-10-10 2:58 pm
ConcatenateNamedDestinations.javaConcatenateNamedDestinations.java2015-10-10 2:58 pm
TimetableDestinations.javaTimetableDestinations.java2015-10-10 2:58 pm
AddVersionChecker.javaAddVersionChecker.java2015-10-10 2:58 pm
FindDirectors.javaFindDirectors.java2015-10-10 2:58 pm
LaunchAction.javaLaunchAction.java2015-10-10 2:58 pm
PrintTimeTable.javaPrintTimeTable.java2015-10-10 2:58 pm
EventsAndActions.javaEventsAndActions.java2015-10-10 2:58 pm
CreateOutlineTree.javaCreateOutlineTree.java2015-10-10 2:58 pm
BookmarkedTimeTable.javaBookmarkedTimeTable.java2015-10-10 2:58 pm
ConcatenateBookmarks.javaConcatenateBookmarks.java2015-10-10 2:58 pm
MovieAnnotations1.javaMovieAnnotations1.java2015-10-10 2:58 pm
MovieAnnotations2.javaMovieAnnotations2.java2015-10-10 2:58 pm
GenericAnnotations.javaGenericAnnotations.java2015-10-10 2:58 pm
TimetableAnnotations1.javaTimetableAnnotations1.java2015-10-10 2:58 pm
MoviePosters1.javaMoviePosters1.java2015-10-10 2:58 pm
TimetableAnnotations2.javaTimetableAnnotations2.java2015-10-10 2:58 pm
MovieAnnotations3.javaMovieAnnotations3.java2015-10-10 2:58 pm
TimetableAnnotations3.javaTimetableAnnotations3.java2015-10-10 2:58 pm
ButtonsActions.javaButtonsActions.java2015-10-10 2:58 pm
Advertisement.javaAdvertisement.java2015-10-10 2:58 pm
MoviePosters2.javaMoviePosters2.java2015-10-10 2:58 pm
Calculator.javaCalculator.java2015-10-10 2:58 pm