KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bluej > editor > moe > MoePrinter


1 // Copyright (c) 2000, 2005 BlueJ Group, Deakin University
2
//
3
// This software is made available under the terms of the "MIT License"
4
// A copy of this license is included with this source distribution
5
// in "license.txt" and is also available at:
6
// http://www.opensource.org/licenses/mit-license.html
7
// Any queries should be directed to Michael Kolling mik@bluej.org
8

9 package bluej.editor.moe;
10
11 import java.awt.Color JavaDoc;
12 import java.awt.print.*;
13 import java.awt.Graphics JavaDoc;
14 import java.awt.Font JavaDoc;
15 import java.awt.FontMetrics JavaDoc;
16 import java.awt.print.PrinterJob JavaDoc;
17 import javax.swing.text.*;
18
19 import java.util.*;
20 import java.text.DateFormat JavaDoc;
21
22 import bluej.utility.Debug;
23 import bluej.utility.Utility;
24 import bluej.Config;
25
26
27 /**
28  * Class to handle printing for the MoeEditor.
29  * This borrows ideas and some source code from Andrew Weiland's Print example
30  * at http://www.wam.umd.edu/~aweiland/Print.java. Which no longer exists..
31  * @author Bruce Quig
32  * @version $ Id: $
33  */

34 public class MoePrinter
35 {
36
37     static final String JavaDoc CONTINUED_LABEL = Config.getString("editor.printer.continued");
38     private final int HEADER_SPACE = 30;
39     private final int FOOTER_SPACE = 20;
40     private final int PADDING = 5;
41     private final char TAB_CHAR = '\t';
42     
43     private Book pages = new Book(); // This holds each page
44

45     private static int titleFontSize = Config.getDefaultPropInteger("bluej.fontsize.printTitle", 14);
46     private static int footerFontSize = Config.getDefaultPropInteger("bluej.fontsize.printInfo", 10);
47     private static Font JavaDoc titleFont = new Font JavaDoc("SansSerif", Font.BOLD, titleFontSize);
48     private static Font JavaDoc smallTitleFont = new Font JavaDoc("SansSerif", Font.BOLD, 10);
49     private static Font JavaDoc footerFont = new Font JavaDoc("SansSerif", Font.ITALIC, 9);
50      
51     private String JavaDoc className;
52     private int tabSize = Config.getPropInteger("bluej.editor.tabsize", 4);
53
54     /**
55      * Default constructor
56      */

57     public MoePrinter()
58     {
59         // nothing yet
60
}
61
62     /**
63      * Prints the document. This method produces a copy of the document
64      * as a List of Strings and delegates the printing to a printText method.
65      *
66      * @returns true if it was not cancelled.
67      */

68     public boolean printDocument(PrinterJob JavaDoc printJob, PlainDocument document, String JavaDoc className,
69                                  Font JavaDoc font, PageFormat format)
70     {
71         List lines = new ArrayList();
72
73         this.className = className;
74         // extract tabsize attribute from document and assign to tabSize attribute
75
Integer JavaDoc tabSizeAsInteger = (Integer JavaDoc)document.getProperty(PlainDocument.tabSizeAttribute);
76         if(tabSizeAsInteger != null)
77             tabSize = tabSizeAsInteger.intValue();
78
79         try{
80             // read lock the document while reading to avoid any subsequent edits
81
// unlikely to happen due to the speed at which the document is read
82
document.readLock();
83
84             // Get Root element of the document
85
Element root = document.getDefaultRootElement();
86             //get the number of lines (i.e. child elements)
87
int count = root.getElementCount();
88             Segment segment = new Segment();
89             // Get each line element, get its text and put it in the string list
90
for (int i = 0; i < count; i++) {
91                 Element lineElement = (Element)root.getElement(i);
92                 try {
93                     document.getText(lineElement.getStartOffset(),
94                                      lineElement.getEndOffset() - lineElement.getStartOffset(),
95                                      segment);
96                     lines.add(removeNewLines(segment.toString()));
97                 } catch(BadLocationException ble) {
98                     Debug.reportError("Exception thrown accessing document text: " + ble);
99                 }
100             }
101         }
102         // make sure that read lock is removed
103
finally {
104             document.readUnlock();
105         }
106
107         return printText(printJob, lines, font, format);
108     }
109
110
111     /**
112      * Remove newline and carriage return characters from the end
113      * of this string. This is needed to fix a printing bug with
114      * the handling of newline characters on some printers
115      */

116     private String JavaDoc removeNewLines(String JavaDoc line)
117     {
118         int length = line.length();
119         char lastChar = (length > 0 ? line.charAt(line.length()-1) : ' ');
120
121         while((lastChar == '\n') || (lastChar == '\r')) {
122             
123             line = line.substring(0, line.length()-1);
124             length = line.length();
125             lastChar = (length > 0 ? line.charAt(line.length()-1) : ' ');
126         }
127         return line;
128     }
129
130
131     /**
132      * Prints the text. It sets paper size (at present) and paginates text
133      * into a pageable Book for printing.
134      *
135      * @returns true if it was not cancelled.
136      */

137     private synchronized boolean printText(PrinterJob JavaDoc job, List text, Font JavaDoc font, PageFormat format)
138     {
139         try {
140             pages = paginateText(text, format, font);
141
142             // set the book pageable so the printjob knows
143
// we are printing more than one page (maybe)
144
job.setPageable(pages);
145             job.print();
146                 
147                 return true;
148         }
149         catch (Exception JavaDoc e) {
150             // should it be an error dialog?
151
Debug.reportError("Exception thrown during printing: " + e);
152             e.printStackTrace();
153             return false;
154         }
155     }
156
157
158     /**
159      * The pagination method. Paginate the text onto Printable page objects.
160      * This includes wrapping long lines of text.
161      */

162     private Book paginateText(List text, PageFormat pageFormat, Font JavaDoc font)
163     {
164         Book book = new Book();
165         int currentLine = 0; // line I am currently reading
166
int pageNum = 1; // page #
167

168         // height of text area of a page
169
int height = (int)pageFormat.getImageableHeight() - (HEADER_SPACE + FOOTER_SPACE);
170
171         // number of lines on a page
172
int linesPerPage = height / (font.getSize() + 2);
173         wrapLines(text, pageFormat, font);
174
175         // set number of pages
176
int numberOfPages = ((int)(text.size() / linesPerPage)) + 1;
177
178         List pageText; // one page of text
179

180         ListIterator li = text.listIterator();
181         while ( pageNum <= numberOfPages) {
182             pageText = new ArrayList();
183
184             for (int lineCount = 0; li.hasNext() && lineCount < linesPerPage; lineCount++) {
185                 pageText.add(li.next());
186                 currentLine++; //bq needed?
187
}
188         
189             // create a new page object with the text and add it to the book
190
book.append(new MoePage(pageText, font), pageFormat);
191             pageNum++; // increase the page number I am on
192
}
193         return book; // return the completed book
194
}
195
196
197     /**
198      * Wraps lines so that long lines of text outside of print page dimensions for a
199      * given page format and font are printed as a new line. This method iterates
200      * through each line of text, calculates if there is an overlap and inserts
201      * overlapping text on the next line.
202      */

203     private void wrapLines(List text, PageFormat format, Font JavaDoc font)
204     {
205         // code to wrap lines of text for printing
206
// get a line, get its length, do some font metrics,
207
StyleContext context = new StyleContext();
208         FontMetrics JavaDoc fontMetrics = context.getFontMetrics(font);
209         int maxWidth = (int)format.getImageableWidth() - (PADDING * 2);
210         int fontWidth = fontMetrics.charWidth('m');
211         int chars = maxWidth / fontWidth;
212
213         for(ListIterator li = text.listIterator(); li.hasNext(); ) {
214             String JavaDoc currentLine = Utility.convertTabsToSpaces((String JavaDoc)li.next(), tabSize);
215             li.set(currentLine);
216             int currentLineLength = currentLine.length();
217             int width = fontMetrics.stringWidth(currentLine);
218             
219             // if line needs to be wrapped
220
if(width > maxWidth) {
221                 int indexOfLine = li.previousIndex();
222                 // remove original
223
li.remove();
224                 double iterations = (currentLineLength / chars) + 1;
225                 for(int begin = 0, end = 0; iterations > 0; iterations--, begin += chars) {
226                     if(begin + chars < currentLineLength)
227                         end = begin + chars;
228                     else
229                         end = currentLineLength;
230                     String JavaDoc newSubString = currentLine.substring(begin, end);
231                     if(newSubString.length() != 0)
232                         li.add(newSubString);
233                 }
234             }
235         }
236     }
237
238
239     /* An inner class that defines one page of text based
240      * on data about the PageFormat etc. from the book defined
241      * in the parent class
242      */

243     class MoePage implements Printable
244     {
245         private List text; // the text for the page
246
private Font JavaDoc font;
247
248         MoePage(List text, Font JavaDoc font)
249         {
250             this.text = text; // set the page's text
251
this.font = font; // set the page's font
252
}
253
254         /**
255          * Method that implements Printable interface.
256          *
257          */

258         public int print(Graphics JavaDoc g, PageFormat pageFormat, int pageIndex) throws PrinterException
259         {
260             // the printing part
261
int position;
262             g.setFont(this.font); // Set the font
263
g.setColor(Color.black); // set color
264

265             // get co-ordinates for frame
266
int xPosition = (int)pageFormat.getImageableX();
267             int yPosition = (int)pageFormat.getImageableY();
268             int width = (int)pageFormat.getImageableWidth();
269             int height = (int)pageFormat.getImageableHeight();
270
271             // print a header
272
printHeader(g, pageIndex, xPosition, yPosition, width, HEADER_SPACE);
273
274             // print main text area
275
int textYPosition = yPosition + HEADER_SPACE;
276             int textXPosition = xPosition + PADDING;
277             g.drawRect(xPosition, textYPosition, width, height - (HEADER_SPACE + FOOTER_SPACE));
278             // print the text
279
for(ListIterator li = text.listIterator(); li.hasNext(); ) {
280                 position = textYPosition + (this.font.getSize() + 2) * (li.nextIndex() + 1);
281                 String JavaDoc line = (String JavaDoc)li.next();
282                 if(line.length() == 0) // workaround for strange problem on Mac:
283
line = " "; // trying to print empty lines throws exception
284
g.drawString(line, textXPosition, position);
285             }
286
287             // print footer
288
int footerYPosition = yPosition + height - FOOTER_SPACE;
289             printFooter(g, xPosition, footerYPosition, width, FOOTER_SPACE);
290     
291             return Printable.PAGE_EXISTS; // print the page
292
}
293
294         /**
295          * Prints a header box on a page, including a title and page number.
296          */

297         private void printHeader(Graphics JavaDoc g, int pageIndex, int xPos, int yPos, int width, int height)
298         {
299             // draw title box
300
g.setColor(Color.lightGray);
301             g.fillRect(xPos, yPos, width, height);
302             g.setColor(Color.black); // set color
303
g.drawRect(xPos, yPos, width, height);
304             int titleYPos = yPos + HEADER_SPACE - this.font.getSize() + 2;
305             Font JavaDoc currentFont = null;
306             String JavaDoc title = "Class " + className;
307
308             // print class name on left
309
// if first page make title bigger
310
if(pageIndex == 0)
311                 g.setFont(titleFont);
312             else {
313                 // don't add (continued) if there is no definition
314
if(!"".equals(CONTINUED_LABEL)
315                    && !"editor.printer.continued".equals(CONTINUED_LABEL))
316                     title = title + " (" + CONTINUED_LABEL + ")";
317                 g.setFont(smallTitleFont);
318             }
319             // print class name
320
g.drawString(title, xPos + PADDING, titleYPos);
321
322             // set to smaller title font for page number
323
g.setFont(smallTitleFont);
324             FontMetrics JavaDoc pfm = g.getFontMetrics(smallTitleFont);
325             // print page number on right
326
String JavaDoc pageInfo = (pageIndex + 1) + "/" + pages.getNumberOfPages();
327             int pageInfoX = xPos + width - PADDING - pfm.stringWidth(pageInfo);
328             g.drawString(pageInfo, pageInfoX, titleYPos);
329             g.setFont(font);
330
331         }
332
333         /**
334          * Prints a footer box on a page that shows the print date.
335          */

336         private void printFooter(Graphics JavaDoc g, int xPos, int yPos, int width, int height)
337         {
338             // set up font and text position
339
g.setFont(footerFont);
340             FontMetrics JavaDoc pfm = g.getFontMetrics(footerFont);
341             int footerTextYPos = yPos + FOOTER_SPACE - this.font.getSize() + 2;
342         
343             // package name not shown at present
344
//g.drawString("Package: " + className, xPos + PADDING, footerTextYPos);
345

346             // print date on right
347
Date today = new Date();
348             DateFormat JavaDoc dateFormat = DateFormat.getDateTimeInstance();
349             String JavaDoc date = dateFormat.format(today);
350             int pageInfoX = xPos + width - PADDING - pfm.stringWidth(date);
351             g.drawString(date, pageInfoX, footerTextYPos);
352             //set font back to original
353
g.setFont(font);
354
355         }
356     
357     }
358 }
359
360
361
362
Popular Tags