Java Examples In A Nutshell (3rd Edition) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Examples In A Nutshell (3rd Edition) [Electronic resources] - نسخه متنی

O'Reilly Media, Inc

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








13.4 Printing Multipage Text Documents


The printing examples
we've seen so far print GUI components on a single
page. Printing multipage documents is more interesting, but also
trickier, because we have to decide where to place the page breaks.
Example 13-4 shows how this can be done. This
HardcopyWriter class is a custom
java.io.Writer stream that uses the Java 1.1
Printing API to print the characters sent through it, inserting line
breaks and page breaks as necessary.

The
HardcopyWriter class includes two demonstration
programs as inner classes. The first, PrintFile,
reads a specified text file and prints it by sending its contents to
a HardcopyWriter stream. The second,
Demo, prints a demonstration page that shows off
the font and tabbing capabilities of the class, as shown in Figure 13-4.


Figure 13-4. Demonstration page printed by HardcopyWriter


Example 13-4 is long but worth studying. In addition
to demonstrating the Java 1.1 Printing API again, it shows an
approach to paginating a text document. It is also a useful example
of a custom Writer stream.

Example 13-4. HardcopyWriter.java

package je3.print;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
import java.util.*;
/**
* A character output stream that sends output to a printer.
**/
public class HardcopyWriter extends Writer {
// These are the instance variables for the class
protected PrintJob job; // The PrintJob object in use
protected Graphics page;// Graphics object for current page
protected String jobname; // The name of the print job
protected int fontsize; // Point size of the font
protected String time; // Current time (appears in header)
protected Dimension pagesize; // Size of the page (in dots)
protected int pagedpi; // Page resolution in dots per inch
protected Font font, headerfont; // Body font and header font
protected FontMetrics metrics; // Metrics for the body font
protected FontMetrics headermetrics; // Metrics for the header font
protected int x0, y0;// Upper-left corner inside margin
protected int width, height; // Size (in dots) inside margins
protected int headery; // Baseline of the page header
protected int charwidth; // The width of each character
protected int lineheight; // The height of each line
protected int lineascent; // Offset of font baseline
protected int chars_per_line; // Number of characters per line
protected int lines_per_page; // Number of lines per page
protected int charnum = 0, linenum = 0;
// Current column and line position
protected int pagenum = 0; // Current page number
// A field to save state between invocations of the write( ) method
private boolean last_char_was_return = false;
// A static variable that holds user preferences between print jobs
protected static Properties printprops = new Properties( );
/**
* The constructor for this class has a bunch of arguments:
* The frame argument is required for all printing in Java.
* The jobname appears left justified at the top of each printed page.
* The font size is specified in points, as on-screen font sizes are.
* The margins are specified in inches (or fractions of inches).
**/
public HardcopyWriter(Frame frame, String jobname, int fontsize,
double leftmargin, double rightmargin,
double topmargin, double bottommargin)
throws HardcopyWriter.PrintCanceledException
{
// Get the PrintJob object with which we'll do all the printing.
// The call is synchronized on the static printprops object, which
// means that only one print dialog can be popped up at a time.
// If the user clicks Cancel in the print dialog, throw an exception.
Toolkit toolkit = frame.getToolkit( ); // get Toolkit from Frame
synchronized(printprops) {
job = toolkit.getPrintJob(frame, jobname, printprops);
}
if (job == null)
throw new PrintCanceledException("User cancelled print request");
pagesize = job.getPageDimension( ); // query the page size
pagedpi = job.getPageResolution( ); // query the page resolution
// Bug Workaround:
// On Windows, getPageDimension( ) and getPageResolution don't work, so
// we've got to fake them.
if (System.getProperty("os.name").regionMatches(true,0,"windows",0,7)){
// Use screen dpi, which is what the PrintJob tries to emulate
pagedpi = toolkit.getScreenResolution( );
// Assume a 8.5" x 11" page size. A4 paper users must change this.
pagesize = new Dimension((int)(8.5 * pagedpi), 11*pagedpi);
// We also have to adjust the fontsize. It is specified in points,
// (1 point = 1/72 of an inch) but Windows measures it in pixels.
fontsize = fontsize * pagedpi / 72;
}
// Compute coordinates of the upper-left corner of the page.
// I.e. the coordinates of (leftmargin, topmargin). Also compute
// the width and height inside of the margins.
x0 = (int)(leftmargin * pagedpi);
y0 = (int)(topmargin * pagedpi);
width = pagesize.width - (int)((leftmargin + rightmargin) * pagedpi);
height = pagesize.height - (int)((topmargin + bottommargin) * pagedpi);
// Get body font and font size
font = new Font("Monospaced", Font.PLAIN, fontsize);
metrics = frame.getFontMetrics(font);
lineheight = metrics.getHeight( );
lineascent = metrics.getAscent( );
charwidth = metrics.charWidth('0'); // Assumes a monospaced font!
// Now compute the number of columns and lines
// that will fit inside the margins
chars_per_line = width / charwidth;
lines_per_page = height / lineheight;
// Get header font information
// And compute baseline of page header: 1/8" above the top margin
headerfont = new Font("SansSerif", Font.ITALIC, fontsize);
headermetrics = frame.getFontMetrics(headerfont);
headery = y0 - (int)(0.125 * pagedpi) -
headermetrics.getHeight( ) + headermetrics.getAscent( );
// Compute the date/time string to display in the page header
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.SHORT);
df.setTimeZone(TimeZone.getDefault( ));
time = df.format(new Date( ));
this.jobname = jobname; // save name
this.fontsize = fontsize; // save font size
}
/**
* This is the write( ) method of the stream. All Writer subclasses
* implement this. All other versions of write( )
are variants of this one
**/
public void write(char[ ] buffer, int index, int len) {
synchronized(this.lock) { // For thread safety
// Loop through all the characters passed to us
for(int i = index; i < index + len; i++) {
// If we haven't begun a page (or a new page), do that now.
if (page == null) newpage( );
// If the character is a line terminator, then begin new line,
// unless it is a \n immediately after a \r.
if (buffer[i] == '\n') {
if (!last_char_was_return) newline( );
continue;
}
if (buffer[i] == '\r') {
newline( );
last_char_was_return = true;
continue;
}
else last_char_was_return = false;
// If it's some other non-printing character, ignore it.
if (Character.isWhitespace(buffer[i]) &&
!Character.isSpaceChar(buffer[i]) && (buffer[i] != '\t'))
continue;
// If no more characters will fit on the line, start new line.
if (charnum >= chars_per_line) {
newline( );
// Also start a new page, if necessary
if (page == null) newpage( );
}
// Now print the character:
// If it is a space, skip one space, without output.
// If it is a tab, skip the necessary number of spaces.
// Otherwise, print the character.
// It is inefficient to draw only one character at a time, but
// because our FontMetrics don't match up exactly to what the
// printer uses, we need to position each character individually
if (Character.isSpaceChar(buffer[i])) charnum++;
else if (buffer[i] == '\t') charnum += 8 - (charnum % 8);
else {
page.drawChars(buffer, i, 1,
x0 + charnum * charwidth,
y0 + (linenum*lineheight) + lineascent);
charnum++;
}
}
}
}
/**
* This is the flush( ) method that all Writer
subclasses must implement.
* There is no way to flush a PrintJob without
prematurely printing the
* page, so we don't do anything.
**/
public void flush( ) { /* do nothing */ }
/**
* This is the close( ) method that
all Writer subclasses must implement.
* Print the pending page (if any) and terminate the PrintJob.
*/
public void close( ) {
synchronized(this.lock) {
if (page != null) page.dispose( ); // Send page to the printer
job.end( ); // Terminate the job
}
}
/**
* Set the font style. The argument should be one of the font style
* constants defined by the java.awt.Font class. All subsequent output
* will be in that style. This method relies on all styles of the
* Monospaced font having the same metrics.
**/
public void setFontStyle(int style) {
synchronized (this.lock) {
// Try to set a new font, but restore current one if it fails
Font current = font;
try { font = new Font("Monospaced", style, fontsize); }
catch (Exception e) { font = current; }
// If a page is pending, set the new font. Otherwise newpage( ) will
if (page != null) page.setFont(font);
}
}
/** End the current page. Subsequent output will be on a new page. */
public void pageBreak( ) { synchronized(this.lock) { newpage( ); } }
/** Return the number of columns of characters that fit on the page */
public int getCharactersPerLine( ) { return this.chars_per_line; }
/** Return the number of lines that fit on a page */
public int getLinesPerPage( ) { return this.lines_per_page; }
/** This internal method begins a new line */
protected void newline( ) {
charnum = 0; // Reset character number to 0
linenum++; // Increment line number
if (linenum >= lines_per_page) { // If we've reached the end of page
page.dispose( ); // send page to printer
page = null; // but don't start a new page yet.
}
}
/** This internal method begins a new page and prints the header. */
protected void newpage( ) {
page = job.getGraphics( ); // Begin the new page
linenum = 0; charnum = 0; // Reset line and char number
pagenum++; // Increment page number
page.setFont(headerfont); // Set the header font.
page.drawString(jobname, x0, headery); // Print job name left justified
String s = "- " + pagenum + " -"; // Print the page # centered.
int w = headermetrics.stringWidth(s);
page.drawString(s, x0 + (this.width - w)/2, headery);
w = headermetrics.stringWidth(time); // Print date right justified
page.drawString(time, x0 + width - w, headery);
// Draw a line beneath the header
int y = headery + headermetrics.getDescent( ) + 1;
page.drawLine(x0, y, x0+width, y);
// Set the basic monospaced font for the rest of the page.
page.setFont(font);
}
/**
* This is the exception class that the HardcopyWriter constructor
* throws when the user clicks "Cancel" in the print dialog box.
**/
public static class PrintCanceledException extends Exception {
public PrintCanceledException(String msg) { super(msg); }
}
/**
* A program that prints the specified file using HardcopyWriter
**/
public static class PrintFile {
public static void main(String[ ] args) {
try {
if (args.length != 1)
throw new IllegalArgumentException("Wrong # of arguments");
FileReader in = new FileReader(args[0]);
HardcopyWriter out = null;
Frame f = new Frame("PrintFile: " + args[0]);
f.setSize(200, 50);
f.show( );
try {
out = new HardcopyWriter(f, args[0], 10, .5, .5, .5, .5);
}
catch (HardcopyWriter.PrintCanceledException e) {
System.exit(0);
}
f.setVisible(false);
char[ ] buffer = new char[4096];
int numchars;
while((numchars = in.read(buffer)) != -1)
out.write(buffer, 0, numchars);
in.close( );
out.close( );
}
catch (Exception e) {
System.err.println(e);
System.err.println("Usage: " +
"java HardcopyWriter$PrintFile <filename>");
System.exit(1);
}
System.exit(0);
}
}
/**
* A program that prints a demo page using HardcopyWriter
**/
public static class Demo extends Frame implements ActionListener {
/** The main method of the program. Create a test window */
public static void main(String[ ] args) {
Frame f = new Demo( );
f.show( );
}
// Buttons used in this program
protected Button print, quit;
/** Constructor for the test program's window. */
public Demo( ) {
super("HardcopyWriter Test"); // Call frame constructor
Panel p = new Panel( ); // Add a panel to the frame
this.add(p, "Center"); // Center it
p.setFont(new Font("SansSerif", // Set a default font
Font.BOLD, 18));
print = new Button("Print Test Page"); // Create a Print button
quit = new Button("Quit"); // Create a Quit button
print.addActionListener(this); // Specify that we'll handle
quit.addActionListener(this); // button presses
p.add(print); // Add the buttons to panel
p.add(quit);
this.pack( ); // Set the frame size
}
/** Handle the button presses */
public void actionPerformed(ActionEvent e) {
Object o = e.getSource( );
if (o == quit) System.exit(0);
else if (o == print) printDemoPage( );
}
/** Print the demo page */
public void printDemoPage( ) {
// Create a HardcopyWriter, using a 10 point font and 3/4" margins.
HardcopyWriter hw;
try { hw=new HardcopyWriter(this, "Demo Page",10,.75,.75,.75,.75);}
catch (HardcopyWriter.PrintCanceledException e) { return; }
// Send output to it through a PrintWriter stream
PrintWriter out = new PrintWriter(hw);
// Figure out the size of the page
int rows = hw.getLinesPerPage( ), cols = hw.getCharactersPerLine( );
// Mark upper-left and upper-right corners
out.print("+"); // upper-left corner
for(int i=0;i<cols-2;i++) out.print(" "); // space over
out.print("+"); // upper-right corner
// Display a title
hw.setFontStyle(Font.BOLD + Font.ITALIC);
out.println("\n\t\tHardcopy Writer Demo Page\n\n");
// Demonstrate font styles
hw.setFontStyle(Font.BOLD);
out.println("Font Styles:");
int[ ] styles = { Font.PLAIN, Font.BOLD,
Font.ITALIC, Font.ITALIC+Font.BOLD };
for(int i = 0; i < styles.length; i++) {
hw.setFontStyle(styles[i]);
out.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz");
out.println("1234567890!@#$%^&*( )[ ]{ }<>,.?:;+-=/\\`'\"_~|");
}
hw.setFontStyle(Font.PLAIN);
out.println("\n");
// Demonstrate tab stops
hw.setFontStyle(Font.BOLD);
out.println("Tab Stops:");
hw.setFontStyle(Font.PLAIN);
out.println(" 1 2 3 4 5");
out.println("012345678901234567890123456789012345678901234567890");
out.println("^\t^\t^\t^\t^\t^\t^");
out.println("\n");
// Output some information about page dimensions and resolution
hw.setFontStyle(Font.BOLD);
out.println("Dimensions:");
hw.setFontStyle(Font.PLAIN);
out.println("\tResolution: " + hw.pagedpi + " dots per inch");
out.println("\tPage width (pixels): " + hw.pagesize.width);
out.println("\tPage height (pixels): " + hw.pagesize.height);
out.println("\tWidth inside margins (pixels): " + hw.width);
out.println("\tHeight inside margins (pixels): " + hw.height);
out.println("\tCharacters per line: " + cols);
out.println("\tLines per page: " + rows);
// Skip down to the bottom of the page
for(int i = 0; i < rows-30; i++) out.println( );
// And mark the lower-left and lower-right
out.print("+"); // lower-left
for(int i=0;i<cols-2;i++) out.print(" "); // space-over
out.print("+"); // lower-right
// Close the output stream, forcing the page to be printed
out.close( );
}
}
}


/ 285