Adding Chunk, Phrase, Paragraph, and List objects Part 3 (iText 5)

The Drawinterface: vertical position marks, separators, and tabs

In section 1.3.4, you learned that there are different ways to add content to a page using iText. In this topic, you’ve been using document.add(), trusting iText to put the content at the correct position in a page. But in some cases, you might want to add something extra. For instance, you might want to add a mark at the current position in the page (for example, an arrow); or you might want to draw a line from the left margin to the right margin (which is different from underlining a Chunk).

This can be achieved using DrawInterface. If you want to benefit from all the possibilities of this interface and its VerticalPositionMark implementation, you’ll need some techniques that will be explained in the next topic. For now, figure 2.8 shows classes that can be used without any further programming work.

Class diagram of DrawInterface implementations

Figure 2.8 Class diagram of DrawInterface implementations


VERTICAL POSITION MARKS

Suppose that you want to create an alphabetical list of directors, and to list the movies directed by these filmmakers that are present in the database. To this list, you want to add an arrow that indicates which directors have more than two movies in the database. You also want to indicate all the movies that were made in the year 2000 or later. See figure 2.9 for an example.

Vertical position marks

Figure 2.9 Vertical position marks

Listing 2.17 PositionedArrow.java

Listing 2.17 PositionedArrow.java

You could use Document.add() to add instances of this PositionedArrow class to the Document because it extends VerticalPositionMark, which means it also implements the Element interface. When this Element is encountered, the custom draw() method will be invoked, and this method has access to the canvas to which content is added. It also knows the coordinates defining the margins of the page, (llx, lly) and (urx, ury), as well as the current y position on the page. In the draw() method of the PositionedArrow class, listing 2.17 uses llx and urx to draw an arrow in the left or right margin of the page, and it uses the y value to position the arrow.

Observe that in this example PositionedArrow is not added directly to the Document.

You can achieve this by subclassing VerticalPositionMark.

Listing 2.18 DirectorOverview1.java

Listing 2.18 DirectorOverview1.javaListing 2.18 DirectorOverview1.java

The arrow refers to the content of a Paragraph, and it’s better to add it to the corresponding object, as is done in and . Otherwise a page break could cause the text to be on one page and the arrow on the next; that could be your intention in some situations, but that’s not the case here.

LINE SEPARATORS

When you need to draw a line, you want to know the current vertical position of the text of a page. In that situation, you can get a long way using the LineSeparator class. In O of listing 2.18, you create a line separator with the following parameters:

■ The line width—In this case, a line with a thickness of 1 pt.

■ The percentage that needs to be covered—In this case, 100 percent of the available width.

■ A color—In this case, null, meaning that the default color will be used. The alignment—This only makes sense if the percentage isn’t 100 percent.

■ The offset—In this case, 2 pt below the baseline.

If this object isn’t sufficient for your needs, you can write your own subclass of VerticalPositionMark, or your own (custom) implementation of the DrawInterface.

Listing 2.19 StarSeparator.java

Listing 2.19 StarSeparator.javaListing 2.19 StarSeparator.java

Observe that the StarSeparator object doesn’t implement the Element interface. This means you can’t add it directly to the Document. You need to wrap it in a Chunk object first.

SEPARATOR CHUNKS

Listing 2.9 applied a dirty hack using negative leading to create a line layout with a Paragraph to the left (the English movie title) and a Paragraph to the right (the original movie title). I told you that’s not the way it’s should be done. Now let’s have a look at the proper way to achieve this.

Listing 2.20 DirectorOverview2.java

Listing 2.20 DirectorOverview2.java

Listing 2.20 wraps a DottedLineSeparator in a Chunk and uses it to separate the name of a filmmaker from the number of movies they have directed. The DottedLineSeparator is a subclass of the LineSeparator, with the main difference being that it draws a dotted line instead of a solid line. You can also set the gap between the dots using the setGap() method.

Some of the VerticalPositionMarks in figure 2.10 act as separators to distribute content over a line. The name of the class no longer applies—you aren’t adding a mark at a vertical position anymore. Instead you’re using the object to separate the movie title from the year when the movie was produced. You could use multiple separators to distribute the title, the run length, and the production year: iText will look at the remaining white space for every line and distribute it equally over the number of separator Chunks.

Dotted line and other separators

Figure 2.10 Dotted line and other separators

Another way to distribute the content of a line is to use tabs.

TAB CHUNKS

Figure 2.11 shows how you can distribute the English movie title, the original title, the run length, and the year the movie was produced over one or more lines using tabs. If ordinary separator Chunks were used, the content wouldn’t have been aligned in columns.

One English movie title and its corresponding original title don’t fit in the available space. A new line is used because of the way you’ve defined the tab Chunk. If you change true into false in the tab Chunk constructors, no line break will occur; the text will overlap instead.

Chunks acting as tab positions

Figure 2.11 Chunks acting as tab positions

Listing 2.21 DirectorOverview3.java

Listing 2.21 DirectorOverview3.java

You can use any DrawInterface to create a separator or tab Chunk, and you can use these Chunks to separate content horizontally (within a paragraph) or vertically (lines between paragraphs). Now it’s time to discuss the other building blocks shown in the class diagram in figure 2.1.

Next post:

Previous post: