# Tutorial: iText by Example

## Optional Content

Optional Content Groups:
Optional content is discussed in section 4.10 of the PDF Reference Manual:

> Optional Content refers to sections of content in a PDF document that can be selectively viewed or hidden by document authors or consumers. This capability is useful in items such as CAD drawings, layered artwork, maps and multi-language documents.

Graphics that can be made visible/invisible dynamically are grouped in optional content groups. Content that belongs to a certain group is visible when the group is ON and invisible when the group is OFF.
In iText, we call such groups 'layers'. You can create a PdfLayer object and when adding content to a PdfContentByte-object, we are going to specify in which layer (= Content Group) the content should be shown (or hidden).

    PdfContentByte cb = writer.getDirectContent();
    PdfLayer l = new PdfLayer("My Layer", writer);
    cb.beginLayer(l);
    // add content to 'My Layer' here
    cb.endLayer();

You can combine different PdfLayers in a PdfLayerMembership:

    PdfContentByte cb = writer.getDirectContent();
    PdfLayer l1 = new PdfLayer("Layer 1", writer);
    PdfLayer l2 = new PdfLayer("Layer 2", writer);
    PdfLayerMembership m = new PdfLayerMembership(writer);
    m.addMember(l1);
    m.addMember(l2);
    cb.beginLayer(m);
    // add content to 'Layer 1' and 'Layer 2' here
    cb.endLayer();

This is a simple example:
Example: java com.lowagie.examples.directcontent.optionalcontent.OrderedLayers
Ordering Optional Content Groups: see orderedlayers.pdf
As you see, you have a pane to your right in Acrobat Reader with all the available layers. Two of them are grouped in 'A group of two'. You can click on the eye-symbol to make a layer invisible.
Remark that we have set the PDF version to 1.5 just after creating the writer (because OCG was only introduced since version 1.5) and we have also set the Viewer Preferences to PageModeUseOC.

    writer.setPdfVersion(PdfWriter.VERSION_1_5);
    writer.setViewerPreferences(PdfWriter.PageModeUseOC);

Every writer object has a PdfOCProperties dictionary. You can get this dictonary with getOCProperties() as is done in the example above. Dictionaries are objects that are used a lot in PDF (other specific PDF objects are PdfArray, PdfString, PdfNull, PdfName, PdfNumber,...). iText creates lots of these objects behind the scenes. If you want to use the PdfOCProperties dictionary, you have a chance to get a better understanding of the iText internals (this is an euphemism meaning it's rather complex stuff). The code below gets the OC Properties from the writer, creates an ORDER-array and adds the layers l1, l2 and l3 to this order array, with l2 and l3 inside a 'group of two':

    PdfOCProperties ocp = writer.getOCProperties();
    PdfArray order = new PdfArray();
    order.add(l1.getRef());
    PdfArray group = new PdfArray();
    group.add(new PdfString("A group of two", PdfObject.TEXT_UNICODE));
    group.add(l2.getRef());
    group.add(l3.getRef());
    order.add(group);
    PdfDictionary dict = new PdfDictionary();
    dict.put(PdfName.ORDER, order);
    ocp.put(PdfName.D, d);

Just take a look at the resulting PDF to see the effect:
Example: java com.lowagie.examples.directcontent.optionalcontent.ContentGroups
Grouping Optional Content: see contentgroups.pdf
With some small changes, we can 'nest' the layers instead of grouping them:
Example: java com.lowagie.examples.directcontent.optionalcontent.NestedLayers
Nesting Optional Content: see nestedlayers.pdf
You may find all this rather elaborate and complex. I'm sorry, I've been pulling your leg in order to show how iText works. There are far more simpler ways to order, group or nest OCGs: just use the methods PdfLayer.createTitle and PdfLayer.addChild, and iText will do all the difficult work for you.
Example: java com.lowagie.examples.directcontent.optionalcontent.Automatic
Automatic grouping and nesting of Optional Content: see automatic.pdf
You might want to take a look at the other methods in class PdfLayer: PdfLayer.setZoom might be handy if you are drawing a map: you can specify between which maximum and minimum zoom factor the content should be visible. PdfLayer.setPrint if you want to add content that is intended for use in printing. PdfLayer.setOn sets the initial visibility of the layer. PdfLayer.setOnPanel sets the visibility of the layer in Acrobat's layer panel. If set to false the layer cannot be directly manipulated by the user. These methods are used in this example:
Example: java com.lowagie.examples.directcontent.optionalcontent.Layers
Zooming and radio groups: see layers.pdf
There are lots of other methods in class PdfLayer. But let's look at one final example:
Example: java com.lowagie.examples.directcontent.optionalcontent.OptionalContent
Changing the visibility using an Action: see optionalcontent.pdf
External resources for this example: pngnow.png
As you can see toggling layers can be done in the layers panel in Acrobat Reader, but you can also make an action that changes the visibility status of the layers.

    ArrayList state = new ArrayList();
    state.add("toggle");
    state.add(l1);
    state.add(l2);
    state.add(l3);
    state.add(l4);
    PdfAction action = PdfAction.setOCGstate(state, true);
    Chunk ck = new Chunk("Click here to toggle the layers").setAction(action);

The different possibilities are "ON", "OFF" or "Toggle" (see also the API for PdfAction.setOCGstate).
Go to top of the page
Amazon books:
amazon.co.uk-link