Bookmarks at ListItem level with OpenPDF

Viewed 144

I am using OpenPDF as a replacement for iText. It meets most of my requirements. I was trying to add click and navigate bookmarks for List and ListItems which I am unable to. Here is what I have tried. I added an event handler hook when a paragraph is added:

public class OPBookmarkBuilder extends PdfPageEventHelper {
    public void onParagraph(PdfWriter writer, Document document, float position) {
        PdfContentByte cb = writer.getDirectContent();
        PdfDestination destination = new PdfDestination(PdfDestination.FITH, position);
        new PdfOutline(cb.getRootOutline(), destination, "Para1-bookmark");
    }
}

And when I add a List or ListItem, I am also adding a dummy paragraph so that the bookmarks get added for that paragraph like so:

public class PDFGenerator {
    public static void main(String[] args) {
        Document document = new Document();
        final PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream("testbm.pdf"));
        OPBookmarkBuilder bookmarkBuilder = new OPBookmarkBuilder();
        instance.setPageEvent(bookmarkBuilder);
        instance.setPageEvent(image);
        document.open();
        instance.setViewerPreferences(PdfWriter.PageModeUseOutlines);
        document.add(new Paragraph(....));
        List section = new Section();
        section.add(new ListItem("test1",...));
        section.add(new Table(..));
        // Add a dummy empty paragraph so that PDFOutline is added.
        document.add(new Paragraph("",...));
        section.add(new ListItem("test2",...));
        // ...
        document.add(section);
        document.close();
    }
}

The position does not move until some element is added to document. Here the problem is that unless I add the list to the document (before document.close()), the position has not moved and hence adding the dummy paragraph is adding outlines at the same destination. In the generated a PDF, on clicking the bookmarks it does not navigate to the corresponding list item. I have explored Chapters and Sections but that renders a numbered bullet which I don't want.

1 Answers

In a first step, set the local destination on the Chunk-level which assigns a static name to this destination. In a second step, create the PdfOutline by passing a PdfAction to jump to the referenced local destination with PdfAction.gotoLocalPage("label", false).

Here is a working example:

Document document = new Document(PageSize.A4);
PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream("out.pdf"));
instance.setViewerPreferences(PdfWriter.PageModeUseOutlines);
document.open();

List list = new List();
list.add(new ListItem(new Chunk(LOREM_IPSUM_A).setLocalDestination("dest1")));
list.add(new ListItem(new Chunk(LOREM_IPSUM_B).setLocalDestination("dest2")));
list.add(new ListItem(new Chunk(LOREM_IPSUM_C).setLocalDestination("dest3")));
document.add(list);

// add outline items
PdfOutline root = instance.getDirectContent().getRootOutline();
new PdfOutline(root, PdfAction.gotoLocalPage("dest1", false), "test-a");
new PdfOutline(root, PdfAction.gotoLocalPage("dest2", false), "test-b");
new PdfOutline(root, PdfAction.gotoLocalPage("dest3", false), "test-c");

document.close();

LOREM_IPSUM_A, LOREM_IPSUM_B, LOREM_IPSUM_C are just some constants with filler text.

This is how it looks in Adobe Acrobat after test-b was clicked:

result

Related