JClass PageLayout

PreviousNextIndex

2

Creating a Document

Building Page Templates   Applying Page Templates  Creating a Printer

Creating a Document   Controlling Flow

In Basic Steps for Creating a JClass PageLayout Document, in Chapter 1, we outlined the five basic steps necessary to create the simplest document. In this chapter, we build on that foundation, giving you the specific information you need to make each of those steps.


2.1 Building Page Templates

In A Simple JClass PageLayout Program, in Chapter 1, you saw a JClass PageLayout program that outputs a single line of text to a printed page. Before you can flow content into a document, you need a page template that defines how the page is laid out. Page templates specify:

JClass PageLayout templates are written in the Extensible Markup Language (XML). The templates use a common Document Type Definition (DTD) that is built into the JClass PageLayout API. The DTD defines the tags and attributes used to specify the appearance of the page templates. It is located in com/klg/jclass/xml-dtd/JCPageTemplate.dtd.

For an introduction to XML, refer to:
http://www.javaworld.com/javaworld/jw-04-1999/jw-04-xml.html. There are many guides that provide a more comprehensive examination of XML, such as The XML Handbook, by Charles Goldfarb and Paul Prescod.

JClass PageLayout provides default page templates for most standard page types. For the sake of simplicity, the Hello, World program uses a default page template, as follows:

  doc = new JCDocument(printer, JCDocument.BLANK_8p5x11);

The following table lists and describes the default page templates available to you.

Default Template

Description

Blank_8p5x11

Creates a blank (no headers or footers) page of standard US Letter size.

Blank_8p5x14

Creates a blank (no headers or footers) page of standard US Legal size.

Blank_11x17

Creates a blank (no headers or footers) page of standard Tabloid size.

Blank_A3

Creates a blank (no headers or footers) page of standard ISO A3 size.

Blank_A4

Creates a blank (no headers or footers) page of standard ISO A4 size.

Blank_A5

Creates a blank (no headers or footers) page of standard ISO A5 size.

Unlike the introductory example in the previous chapter, most applications require more than one type of output page. If your application requires custom output pages, the template must provide a definition for each type of page.

2.1.1 A Sample Template

The following is an XML document you could use to define an 8.5 x 11 (US Letter) page template that, unlike the standard template Blank_8p5x11, includes headers and footers.

<?xml version="1.0"?>
<!DOCTYPE JCPAGETEMPLATE SYSTEM "JCPageTemplate.dtd">
<JCPAGETEMPLATE TITLE="8p5x11">
  <PAGE NAME="8p5x11" UNIT="inches">
    <LOCATION X="0" Y="0"/>
    <SIZE WIDTH="8.5" HEIGHT="11"/>
    <FRAME NAME="header" UNIT="inches" COLOR="grey">
      <LOCATION X="1" Y="0.25"/>
      <SIZE WIDTH="6.5" HEIGHT="0.75"/>
    </FRAME>
    <FRAME NAME="body" UNIT="inches">
      <LOCATION X="1" Y="1"/>
      <SIZE WIDTH="6.5" HEIGHT="9"/>
      <COLUMN COUNT="2"/>
    </FRAME>
    <FRAME NAME="footer" UNIT="inches" COLOR="pink">
      <LOCATION X="1" Y="10.25"/>
      <SIZE WIDTH="6.5" HEIGHT="0.75"/>
    </FRAME>
    <FLOWFRAME NAME="body"/>
    <FLOWPAGE NAME="8p5x11"/>
    <FLOWSECTION NAME="8p5x11"/>
  </PAGE>
</JCPAGETEMPLATE>

2.1.2 The Template DTD

The structure of JClass PageLayout templates is defined in an XML Document Type Definition (DTD) stored as a String in JCPageTemplate. We reprint it here to give you an idea of the hierarchy of elements in an XML template. For a complete description of the elements used in a JClass PageLayout template, refer to Template Elements and Attributes, in Chapter 2.

Please note that the order of the attributes and child elements of each element is fixed; the order shown in the example below must be used.

<!-- DTD for JClass PageLayout Templates -->
<!ELEMENT JCPAGETEMPLATE (PAGE+)>
<!ATTLIST JCPAGETEMPLATE TITLE CDATA #IMPLIED>

<!ELEMENT PAGE (LOCATION,SIZE,FRAME+,FLOWFRAME*,FLOWPAGE,FLOWSECTION)>
<!ATTLIST PAGE NAME CDATA #REQUIRED
  UNIT (inches|points|cm|cms|centimeters|centimetres) "inches"
  COLOR CDATA #IMPLIED
  ORIENTATION (automatic|portrait|landscape) "automatic"
  FIRST (True|true|TRUE|False|false|FALSE) "false">

<!ELEMENT FRAME (LOCATION,SIZE,BORDER?,COLUMN?,MARGIN?)>
<!ATTLIST FRAME NAME CDATA #REQUIRED
  UNIT (inches|points|cm|cms|centimeters|centimetres) "inches"
  COLOR CDATA #IMPLIED>

<!ELEMENT LOCATION EMPTY>
<!ATTLIST LOCATION X CDATA #REQUIRED
                  Y CDATA #REQUIRED>

<!ELEMENT SIZE EMPTY>
<!ATTLIST SIZE WIDTH CDATA #REQUIRED
              HEIGHT CDATA #REQUIRED>

<!ELEMENT BORDER EMPTY>
<!ATTLIST BORDER TYPE (blank|broken|dashed|double|none|plain|regular|single) "blank"
  COLOR CDATA "black"
  THICKNESS CDATA #IMPLIED>

<!ELEMENT COLUMN EMPTY>
<!ATTLIST COLUMN COUNT CDATA #REQUIRED
  SPACING CDATA #IMPLIED>

<!ELEMENT MARGIN EMPTY>
<!ATTLIST MARGIN TOP CDATA #REQUIRED
                RIGHT CDATA #REQUIRED
                LEFT CDATA #REQUIRED
                BOTTOM CDATA #REQUIRED>

<!ELEMENT FLOWFRAME EMPTY>
<!ATTLIST FLOWFRAME NAME CDATA #REQUIRED>

<!ELEMENT FLOWPAGE EMPTY>
<!ATTLIST FLOWPAGE NAME CDATA #REQUIRED>

<!ELEMENT FLOWSECTION EMPTY>
<!ATTLIST FLOWSECTION NAME CDATA #REQUIRED>

2.1.3 Template Elements and Attributes

The following table describes the elements and attributes used to define a page template.

Please note that the order of the attributes and child elements of each element is fixed; the order shown in the table below and in Section 2.1.2, The Template DTD, must be used.

Element

Attributes

Child Elements

<JCPAGETEMPLATE>

TITLE: An optional attribute that names this page template.

<PAGE>

<PAGE>

NAME: Required. The name of this page type, referenced by other page definitions using the <FLOWPAGE> tag.

UNIT: The unit of measurement used to plot out this page. Choose from inches, points, cm, cms, centimetres, and centimeters. The default is inches.

COLOR: Optional. Specifies a default background color for this page using hexadecimal notation or a color from com.klg.jclass.util.swing.

JCSwingTypeConverter.

ORIENTATION: Choose from automatic, portrait, and landscape.

FIRST: A Boolean attribute that indicates whether or not this page template is used for the first page in the document. The default is false.

<LOCATION>, <SIZE>, <FRAME>+, <FLOWFRAME>*, <FLOWPAGE>, <FLOWSECTION>

<FRAME>

NAME: Required. The name of this frame type, referenced by other page definitions using the <FLOWFRAME> tag.

UNIT: The unit of measurement used to plot out this frame. Choose from inches, points, cm, cms, centimetres, and centimeters. The default is inches.

COLOR: Optional. Specifies a default background color for this frame using hexadecimal notation or a color from com.klg.jclass.util.swing.

JCSwingTypeConverter.

<LOCATION>, <SIZE>, <BORDER>?, <COLUMN>?,
<MARGIN>?

<LOCATION>

X: Required. Specifies the distance of the page or frame from the left-hand page edge.

Y: Required. Specifies the distance of the page or frame from the top of the page.

None.

<SIZE>

WIDTH: Required. Specifies the width of the page or frame, measured in the units defined by the <UNIT> tag.

HEIGHT: Required. Specifies the height of the page or frame, measured in the units defined by the <UNIT> tag.

None.

<BORDER>

TYPE: Specifies the style used to draw a frame border. Choose from blank, broken, dashed, double, none, plain, regular, or single. The default is blank.

COLOR: Specifies the border color using either hexadecimal notation or a color from java.awt.Color. The default is black.

THICKNESS: Optional. Specifies the border width in pixels. The default is 0.1.

None.

<COLUMN>

COUNT: Required. Specifies the number of columns in the frame.

SPACING: Optional. Specifies the amount of space left between columns, measured in the units defined by the <UNIT> tag.

None.

<MARGIN>

TOP: Required. Specifies the top margin.

RIGHT: Required. Specifies the right margin.

LEFT: Required. Specifies the left margin.

BOTTOM: Required. Specifies the bottom margin.

None.

<FLOWFRAME>

NAME: Required. Specifies the name of a frame to be added to the sequence of frames to which the document will flow content.

None.

<FLOWPAGE>

NAME: Required. Specifies the name of the page to which the flow is to progress when a new page is begun.

None.

<FLOWSECTION>

NAME: Required. Specifies the name of the page to which the flow is to progress when a new section is begun.

None.

+ Required and repeatable.
* Optional and repeatable.
? Optional and non-repeatable.


2.2 Applying Page Templates

After writing your own XML page template, you can apply it to your document by loading it either as an internal String or an external XML file. The following table describes the various JCPageTemplate methods you can use to apply templates.

Method

Explanation

importTemplates(JCDocument
doc, File xmlfile)

Reads from java.io.File to import an XML template and apply it to the specified JCDocument.

importTemplates(JCDocument
doc, Reader reader)

Reads from java.io.Reader to import an XML template and apply it to the specified JCDocument.

importTemplates(JCDocument
doc, InputSource input)

Reads from org.xml.sax.InputSource to import an XML template and apply it to the specified JCDocument.

loadTemplates(File xmlfile)

Reads from java.io.File to load the XML template without applying it to a specific document.

loadTemplates(Reader reader)

Reads from java.io.Reader to load the XML template without applying it to a specific document.

loadTemplates(InputSource
input)

Reads from org.xml.sax.InputSource to load the XML template without applying it to a specific document.

2.2.1 Loading External XML Files

Users of JClass PageLayout will need to include the JAR files jaxp.jar and crimson.jar1 in their CLASSPATH. These files replace the now obsolete parser.jar and xml.jar from earlier releases. They are distributed in the JCLASS_HOME/lib directory along with the JClass PageLayout JAR file.

The following example uses java.io.File to load the external XML file 8p5x11.xml as a template.

  JCDocument document = null;
  try {
    document = new JCDocument(printer, JCPageTemplate.loadTemplates
      (new java.io.File("8p5x11.xml")));
  }
  catch (Exception e) {
    System.err.println("Error loading template = " + e);
    System.exit(1);
  }

2.2.2 Loading XML Strings

The following example uses java.io.StringReader to load an XML template that is defined as a String (template) earlier in the program.

  JCDocument document = null;
  try {
    document = new JCDocument(printer, JCPageTemplate.loadTemplates
      (new StringReader(template)));
  }
  catch (Exception e) {
    System.err.println("Error loading template = " + e);
    System.exit(1);
  }


2.3 Creating a Printer

Now that the page templates are defined, the next step is to instantiate the Printer object that defines the type of print output produced.

  // Open the output file
  try {
    outfile = new FileOutputStream("test.pdf");
  }
  catch (FileNotFoundException e) {
    System.out.println("Could not open file");
    return;
  }

  // Create a PDF printer
  printer = new JCPDFPrinter(outfile);

This example creates a printer object which uses PostScript fonts, lays out the flow, and generates a PDF (Adobe Portable Document Format) file (test.pdf) when the document is printed.

Other printer types include JCHTMLPrinter, JCPostScriptPrinter and JCPCLPrinter, which create output in Adobe's PostScript and the Hewlett-Packard Printer Control Language (PCL), respectively. Using JCAWTPrinter, you can print to the system printer. JCAWTScreenPrinter is used for printing to a screen, which can be used with JCAWTPreviewer for print preview mode. For more information on printing, refer to Printing Options, in Chapter 7.


2.4 Creating a Document

The JCDocument object holds the JCPage and JCFrame objects into which text and images are flowed. In the Hello, World example, we defined the JCDocument as follows:

  JCDocument document = new JCDocument(printer,
    JCDocument.BLANK_8p5X11);

When you instantiate a new JCDocument, you can specify the printer to which you want to send its output, along with the name of the standard template it is to use as shown in the code line above, or by using the JCPageTemplate.loadTemplates() method and passing a list of page templates. For information on defining a printer, refer to Creating a Printer, in Chapter 2. For information on standard templates, refer to Building Page Templates, in Chapter 2.


2.5 Controlling Flow

In cases where text is to flow from frame to frame, the page template specifies the basic flow of text within a document. Template Elements and Attributes, in Chapter 2, describes how to use FlowFrameList to direct the flow of text through frames, FlowPageTemplate to direct the flow of text to the next page, and FlowSectionTemplate to direct the flow of text after a section break.

At times, you may want to advance the flow before it reaches the end of the current frame or page. For example, on a title page, you may want to flow the text containing the document title into a frame you've named Title, then advance the flow to print the author's name into another frame you've named Author.

Because you need to use JCFrame methods when you want to render text and images independently from the flow, these methods are extremely important to the text flow of your layout. When you want to direct the flow through frames and pages, use JCFlow methods.

2.5.1 Frame Methods

Use JCFrame methods when you want to render content that is not part of the main flow. For example, the information contained in header and footer frames is rendered separately from the contents of the body frame. Until new instructions are given, information printed into the header frame of a template page will recur. For more information, refer to Headers and Footers, in Chapter 6.

Content is not added directly into the JCFrame's render list; rather, content is appended to a current line until a complete line is built or the current line is flushed. The current line always begins as zero height - no assumption is made about the attributes of the elements that will subsequently be added to it. Thus, the current line will always fit immediately following the just-completed previous line, even if there is virtually no space available at the end of a frame. As content is added to the current line, its size will be adjusted to fit the new elements. If an element is added to the line which makes the line too tall for the available space, then the frame will attempt a newColumn() action. In a case where the newColumn() action succeeds, the elements of the current line are mapped to their new positions and the flow continues. In the remainder of cases where there is no following column, the frame throws an EndOfFrameException. For more information on exceptions, please see Exceptions, in Chapter 5.

JCFrame methods cease rendering information when the content reaches the bottom of a frame, since they are not part of the flow. When the frame runs out of room, an EndOfFrameException is thrown.

JCFrame Method

Description

newColumn()

Generates a column break and advances the text to the next column in the specified frame. Throws an EndOfFrameException in the last (only) column of a frame.

newLine()

Ends the current line and transfers the flow to a new line. Throws an EndOfFrameException if there is not enough room to print the text.

print()

Renders the specified content to this frame. Throws an EndOfFrameException if there is not enough room to print the text.

2.5.2 Flow Methods

When a JCFlow object is instantiated for a document, it generates the document's first page. This first page will normally have one or more flow frames, and the first of these will be initialized as the current frame. Once a current frame has been initialized, all flow content is passed to that frame until the frame becomes full.

Note: If the first page does not have a flow frame, successive pages will be generated until a flow frame is discovered.

You create the flow by instantiating a JCFlow object, passing in a JCDocument as a parameter. The passed-in JCDocument is the only one that may be associated with the JCFlow object. Note that there can be only one JCDocument object per JCFlow; also, the JCDocument object must be the one passed to the JCFlow in the constructor.

The template page's FlowFrameList, FlowPageTemplate, and FlowSectionTemplate attributes control the order by which the flow progresses through frames and pages. To control flow beyond the standard sequence specified by the templates, the program needs to call JCFlow methods. The following table describes the methods used to control flow.

JCFlow Method

Description

print()

Renders the specified content to the flow.

newLine()

Ends the current line and begins a new line.

newParagraph()

Begins a new paragraph.

newColumn()

Advances the text flow to the top of the next column, in the next frame if necessary.

newFrame()

Advances the text flow to the next frame, generating a new page if necessary.

newPage()

Creates a new page based on the current page's FlowPageTemplate, and directs the flow to the first frame of the new page's FlowFrameList.

newSection()

Creates a new page based on the current page's FlowSectionTemplate, and directs the flow to the first frame of the new page's FlowFrameList.

2.5.3 A Flow Programming Example

The following example of flow programming comes from sample.java, which you can find in the /examples/pagelayout/ folder of your JClass PageLayout installation directory.

// Flow simple text into the document
// while occasionally changing the text style.

flow.setCurrentTextStyle(normal);
normal.setFontStyle(Font.BOLD | Font.ITALIC);
flow.print("Hello, world!");
flow.newParagraph();
normal.setFontStyle(Font.PLAIN);

flow.print("This is a simple ");
normal.setFontStyle(Font.BOLD | Font.ITALIC);
flow.print("JClass PageLayout ");
normal.setFontStyle(Font.PLAIN);
flow.print("example which does a number of different things.");
flow.newParagraph();

// talk about headers and footers
flow.setCurrentTextStyle(heading);
flow.print("Headers and Footers");
flow.newParagraph();
flow.setCurrentTextStyle(normal);
flow.print("First off, what we have done is set up a simple page
    with a ");
normal.setFontStyle(Font.ITALIC);
flow.print("header");
normal.setFontStyle(Font.PLAIN);
flow.print(" and a ");
normal.setFontStyle(Font.ITALIC);
flow.print("footer");
normal.setFontStyle(Font.PLAIN);
flow.print(". The header contains a right justified title and the ");
flow.print("footer contains a centered macro that prints the
    current ");
flow.print("page number.");

2.5.4 Typical Content Flow Sequence

Several events are normally involved in adding content to the flow. These events are listed below.

  1. The application declares the addition of a text String to the flow, calling JCFlow.print (String).
  2. JCFlow.print() passes the String and the current JCTextStyle to the corresponding JCFrame.print(JCTextStyle, String) method.
  3. JCFrame.print() encapsulates the String object in a StringRender object, using the JCTextStyle to supply formatting information and font metrics information from the current Graphics (provided by the JCPrinter).
  4. JCFrame.flowPrint() is called with the new StringRender object. flowPrint() determines the amount of available space (subject to tab position and alignment, indentation and margin) on the current line to see whether the String will fit. If the text is too long to fit, flowPrint() will attempt to split off part of the String to fit into the available space.
  5. The text, or the portion of it that fits on the line, is added to the current line in memory, and any required adjustments are made to the height of the line and its baseline. (If the text is larger than previous elements on the line more space will be needed. Similarly, if the text is in superior subscript mode, then that may increase the height of the line.)
  6. If the line has been made too high to fit in the amount of vertical space currently available, then the action is abandoned and the current line is stored in a EndOfFrameException object which is thrown to be caught by the JCFlow action.
  7. If the line fits, but not all (or none) of the text was added to the line, the current line is pasted into the frame and a new line is begun. The remaining text is printed into the new line.
  8. If an EndOfFrameException is thrown, it is caught in the JCFlow.print() method, which will then find the next flow frame and pass to it the current line of text which did not fit, followed by any other pending content.

Please note that the same sequence is followed for embedded objects, except that it is not possible to split them; thus, if embedded objects do not fit on the current line, they are handed in their entirety to the following line.

1You may substitute for crimson.jar any parser that is compliant with Sun's JAXP 1.1 specification. See Sun's JAXP documentation for more information:


PreviousNextIndex