2 * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
\r
4 * The program is provided "as is" without any warranty express or
\r
5 * implied, including the warranty of non-infringement and the implied
\r
6 * warranties of merchantibility and fitness for a particular purpose.
\r
7 * IBM will not be liable for any damages suffered by you as a result
\r
8 * of using the Program. In no event will IBM be liable for any
\r
9 * special, indirect or consequential damages or lost profits even if
\r
10 * IBM has been advised of the possibility of their occurrence. IBM
\r
11 * will not be liable for any third party claims against you.
\r
13 package com.ibm.richtext.print;
\r
15 import com.ibm.richtext.styledtext.MConstText;
\r
17 import com.ibm.richtext.textformat.MFormatter;
\r
19 import com.ibm.richtext.textlayout.attributes.AttributeMap;
\r
21 import java.awt.Color;
\r
22 import java.awt.Graphics;
\r
23 import java.awt.Point;
\r
24 import java.awt.Rectangle;
\r
26 import java.util.Vector;
\r
29 * This class's interface is very close to that of the JDK 1.2 Printable
\r
30 * interface, but can execute on JDK 1.1. On 1.2, this class is wrapped
\r
31 * in a real Printable. On 1.1, the PrintContext class uses this class
\r
32 * and a PrintJob for printing.
\r
34 * Note that this class paginates the text in the first call to print,
\r
35 * or to getPageCount.
\r
36 * After construction, its page size is essentially fixed. This is not
\r
37 * as flexible as the 1.2 classes allow, but it should suffice.
\r
39 final class MConstTextPrintable {
\r
41 static final String COPYRIGHT =
\r
42 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
\r
44 static final int PAGE_EXISTS = 0;
\r
45 static final int NO_SUCH_PAGE = 1;
\r
47 private MConstText fText;
\r
48 private AttributeMap fDefaultStyles;
\r
49 private Rectangle fPageRect;
\r
51 // If these two fields are null the text has not been paginated.
\r
52 private MFormatter fFormatter;
\r
53 private Vector fPageStarts;
\r
56 * Construct an MConstTextPrintable to print the given text. Each page will fit
\r
59 MConstTextPrintable(MConstText text,
\r
60 AttributeMap defaultStyles,
\r
61 Rectangle pageRect) {
\r
64 fDefaultStyles = defaultStyles;
\r
65 fPageRect = new Rectangle(pageRect);
\r
68 private static boolean emptyParagraphAtEndOfText(MConstText text) {
\r
70 if (text.length() > 0) {
\r
71 char ch = text.at(text.length()-1);
\r
72 return ch == '\n' || ch == '\u2029';
\r
79 private void paginate(Graphics graphics) {
\r
81 if (fPageStarts == null) {
\r
83 fFormatter = MFormatter.createFormatter(fText,
\r
89 fFormatter.formatToHeight(Integer.MAX_VALUE);
\r
90 fFormatter.stopBackgroundFormatting();
\r
92 fPageStarts = new Vector();
\r
94 int lineCount = fFormatter.getLineCount();
\r
95 if (emptyParagraphAtEndOfText(fText)) {
\r
100 fPageStarts.addElement(new Integer(startLine));
\r
101 int startHeight = 0;
\r
102 final int pageHeight = fPageRect.height;
\r
104 while (startLine < lineCount) {
\r
106 int nextStart = fFormatter.lineAtHeight(startHeight + pageHeight);
\r
107 fPageStarts.addElement(new Integer(nextStart));
\r
108 startHeight = fFormatter.lineGraphicStart(nextStart);
\r
109 startLine = nextStart;
\r
115 * Print the given page in the given graphics. Page numbers are
\r
116 * 0-based. The the return value indicates whether
\r
117 * the page number is valid (as in JDK 1.2). Since you can get the page count
\r
118 * directly, there's really no excuse for passing in an invalid page
\r
120 * @param graphics the Graphics to print to
\r
121 * @param pageNumber the 0-based page number. Should be nonnegative and
\r
122 * less than getPageCount()
\r
123 * @return PAGE_EXISTS if the page number is valid, or
\r
124 * NO_SUCH_PAGE otherwise
\r
126 int print(Graphics graphics, int pageNumber) {
\r
128 paginate(graphics);
\r
130 if (pageNumber < getPageCount(graphics) && pageNumber >= 0) {
\r
131 graphics.setColor(Color.black); // workaround for 1.2 printing bug
\r
132 int startLine = ((Integer)fPageStarts.elementAt(pageNumber)).intValue();
\r
133 int limitLine = ((Integer)fPageStarts.elementAt(pageNumber+1)).intValue();
\r
135 int topOfPage = fFormatter.lineGraphicStart(startLine);
\r
136 int pageHeight = fFormatter.lineGraphicStart(limitLine) - topOfPage;
\r
138 Point origin = new Point(fPageRect.x, fPageRect.y - topOfPage);
\r
139 Rectangle drawRect = new Rectangle(fPageRect);
\r
140 drawRect.height = pageHeight;
\r
142 fFormatter.draw(graphics, drawRect, origin);
\r
143 return PAGE_EXISTS;
\r
146 return NO_SUCH_PAGE;
\r
151 * Return the number of pages that can be printed.
\r
152 * @param graphics a Graphics instance representative of those
\r
153 * which will be printed into
\r
155 int getPageCount(Graphics graphics) {
\r
157 paginate(graphics);
\r
158 return fPageStarts.size() - 1;
\r