Mega Code Archive

 
Categories / Java Tutorial / 2D Graphics
 

Demonstrate the Java 1 4 printing API

/*  * Copyright (c) 2004 David Flanagan.  All rights reserved.  * This code is from the book Java Examples in a Nutshell, 3nd Edition.  * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.  * You may study, use, and modify it for any non-commercial purpose,  * including teaching and use in open-source projects.  * You may distribute it non-commercially as long as you retain this notice.  * For a commercial use license, or to purchase the book,   * please visit http://www.davidflanagan.com/javaexamples3.  */ //package je3.print; import java.awt.Component; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.JobAttributes; import java.awt.PageAttributes; import java.awt.PrintJob; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.print.Doc; import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintException; import javax.print.PrintService; import javax.print.PrintServiceLookup; import javax.print.ServiceUI; import javax.print.SimpleDoc; import javax.print.StreamPrintService; import javax.print.StreamPrintServiceFactory; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.OrientationRequested; import javax.print.event.PrintJobAdapter; import javax.print.event.PrintJobEvent; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JOptionPane; /**  * This class extends JuliaSet2 and its print() and save() methods demonstrate  * the Java 1.4 printing API.  */ public class JuliaSet3 extends JuliaSet2 {   public JuliaSet3() {     super(-.7, -.25);   }   // This method overrides JuliaSet2.print() and demonstrates the javax.print   // printing API.   public void print() {     // Get a list of all printers that can handle Printable objects.     DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;     PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, null);     // Set some define printing attributes     PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();     printAttributes.add(OrientationRequested.LANDSCAPE); // landscape mode     printAttributes.add(Chromaticity.MONOCHROME); // print in mono     // Display a dialog that allows the user to select one of the     // available printers and to edit the default attributes     PrintService service = ServiceUI.printDialog(null, 100, 100, services, null, null,         printAttributes);     // If the user canceled, don't do anything     if (service == null)       return;     // Now call a method defined below to finish the printing     printToService(service, printAttributes);   }   // This method is like print() above but prints to a PostScript file   // instead of printing to a printer.   public void save() throws IOException {     // Find a factory object for printing Printable objects to PostScript.     DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;     String format = "application/postscript";     StreamPrintServiceFactory factory = StreamPrintServiceFactory         .lookupStreamPrintServiceFactories(flavor, format)[0];     // Ask the user to select a file and open the selected file     JFileChooser chooser = new JFileChooser();     if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)       return;     File f = chooser.getSelectedFile();     FileOutputStream out = new FileOutputStream(f);     // Obtain a PrintService that prints to that file     StreamPrintService service = factory.getPrintService(out);     // Do the printing with the method below     printToService(service, null);     // And close the output file.     out.close();   }   // Print the Julia set to the sepecifed PrintService using the specified   // attributes.   public void printToService(PrintService service, PrintRequestAttributeSet printAttributes) {     // Wrap ourselves in the PrintableComponent class defined by JuliaSet2.     String title = "Julia set for c={" + cx + "," + cy + "}";     Printable printable = new PrintableComponent(this, title);     // Now create a Doc that encapsulate the Printable object and its type     DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;     Doc doc = new SimpleDoc(printable, flavor, null);     // Java 1.1 uses PrintJob.     // Java 1.2 uses PrinterJob.     // Java 1.4 uses DocPrintJob. Create one from the service     DocPrintJob job = service.createPrintJob();     // Set up a dialog box to monitor printing status     final JOptionPane pane = new JOptionPane("Printing...", JOptionPane.PLAIN_MESSAGE);     JDialog dialog = pane.createDialog(this, "Print Status");     // This listener object updates the dialog as the status changes     job.addPrintJobListener(new PrintJobAdapter() {       public void printJobCompleted(PrintJobEvent e) {         pane.setMessage("Printing complete.");       }       public void printDataTransferCompleted(PrintJobEvent e) {         pane.setMessage("Document transfered to printer.");       }       public void printJobRequiresAttention(PrintJobEvent e) {         pane.setMessage("Check printer: out of paper?");       }       public void printJobFailed(PrintJobEvent e) {         pane.setMessage("Print job failed");       }     });     // Show the dialog, non-modal.     dialog.setModal(false);     dialog.show();     // Now print the Doc to the DocPrintJob     try {       job.print(doc, printAttributes);     } catch (PrintException e) {       // Display any errors to the dialog box       pane.setMessage(e.toString());     }   } } class JuliaSet2 extends JuliaSet1 {   public JuliaSet2() {     this(.4, .4);   } // Display a different set by default   public JuliaSet2(double cx, double cy) {     super(cx, cy);   }   // This method demonstrates the Java 1.2 printing API.   // Test it using the ShowBean program.   public void print() {     // Java 1.1 used java.awt.PrintJob.     // In Java 1.2 we use java.awt.print.PrinterJob     PrinterJob job = PrinterJob.getPrinterJob();     // Alter the default page settings to request landscape mode     PageFormat page = job.defaultPage();     page.setOrientation(PageFormat.LANDSCAPE); // landscape by default     // Tell the PrinterJob what Printable object we want to print.     // PrintableComponent is defined as an inner class below     String title = "Julia set for c={" + cx + "," + cy + "}";     Printable printable = new PrintableComponent(this, title);     job.setPrintable(printable, page);     // Call the printDialog() method to give the user a chance to alter     // the printing attributes or to cancel the printing request.     if (job.printDialog()) {       // If we get here, then the user did not cancel the print job       // So start printing, displaying a dialog for errors.       try {         job.print();       } catch (PrinterException e) {         JOptionPane.showMessageDialog(this, e.toString(), "PrinterException",             JOptionPane.ERROR_MESSAGE);       }     }   }   // This inner class implements the Printable interface for an AWT component   public static class PrintableComponent implements Printable {     Component c;     String title;     public PrintableComponent(Component c, String title) {       this.c = c;       this.title = title;     }     // This method should print the specified page number to the specified     // Graphics object, abiding by the specified page format.     // The printing system will call this method repeatedly to print all     // pages of the print job. If pagenum is greater than the last page,     // it should return NO_SUCH_PAGE to indicate that it is done. The     // printing system may call this method multiple times per page.     public int print(Graphics g, PageFormat format, int pagenum) {       // This implemenation is always a single page       if (pagenum > 0)         return Printable.NO_SUCH_PAGE;       // The Java 1.2 printing API passes us a Graphics object, but we       // can always cast it to a Graphics2D object       Graphics2D g2 = (Graphics2D) g;       // Translate to accomodate the requested top and left margins.       g2.translate(format.getImageableX(), format.getImageableY());       // Figure out how big the drawing is, and how big the page       // (excluding margins) is       Dimension size = c.getSize(); // component size       double pageWidth = format.getImageableWidth(); // Page width       double pageHeight = format.getImageableHeight(); // Page height       // If the component is too wide or tall for the page, scale it down       if (size.width > pageWidth) {         double factor = pageWidth / size.width; // How much to scale         g2.scale(factor, factor); // Adjust coordinate system         pageWidth /= factor; // Adjust page size up         pageHeight /= factor;       }       if (size.height > pageHeight) { // Do the same thing for height         double factor = pageHeight / size.height;         g2.scale(factor, factor);         pageWidth /= factor;         pageHeight /= factor;       }       // Now we know the component will fit on the page. Center it by       // translating as necessary.       g2.translate((pageWidth - size.width) / 2, (pageHeight - size.height) / 2);       // Draw a line around the outside of the drawing area and label it       g2.drawRect(-1, -1, size.width + 2, size.height + 2);       g2.drawString(title, 0, -15);       // Set a clipping region so the component can't draw outside of       // its won bounds.       g2.setClip(0, 0, size.width, size.height);       // Finally, print the component by calling its paint() method.       // This prints the background, border, and children as well.       // For swing components, if you don't want the background, border,       // and children, then call printComponent() instead.       c.paint(g);       // Tell the PrinterJob that the page number was valid       return Printable.PAGE_EXISTS;     }   } } class JuliaSet1 extends JComponent {   // These constants are hard-coded for simplicity   double x1 = -1.5, y1 = -1.5, x2 = 1.5, y2 = 1.5; // Region of complex plane   int width = 400, height = 400; // Mapped to these pixels   double cx, cy; // This complex constant defines the set we display   BufferedImage image; // The image we compute   // We compute values between 0 and 63 for each point in the complex plane.   // This array holds the color values for each of those values.   static int[] colors;   static { // Static initializer for the colors[] array.     colors = new int[64];     for (int i = 0; i < colors.length; i++) {       colors[63 - i] = (i * 4 << 16) + (i * 4 << 8) + i * 4; // grayscale       // (i*4) ^ ((i * 3)<<6) ^ ((i * 7)<<13); // crazy technicolor     }   }   // No-arg constructor with default values for cx, cy.   public JuliaSet1() {     this(-1, 0);   }   // This constructor specifies the {cx,cy} constant.   // For simplicity, the other constants remain hardcoded.   public JuliaSet1(double cx, double cy) {     this.cx = cx;     this.cy = cy;     setPreferredSize(new Dimension(width, height));     computeImage();   }   // This method computes a color value for each pixel of the image   void computeImage() {     // Create the image     image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);     // Now loop through the pixels     int i, j;     double x, y;     double dx = (x2 - x1) / width;     double dy = (y2 - y1) / height;     for (j = 0, y = y1; j < height; j++, y += dy) {       for (i = 0, x = x1; i < width; i++, x += dx) {         // For each pixel, call testPoint() to determine a value.         // Then map that value to a color and set it in the image.         // If testPoint() returns 0, the point is part of the Julia set         // and is displayed in black. If it returns 63, the point is         // displayed in white. Values in-between are displayed in         // varying shades of gray.         image.setRGB(i, j, colors[testPoint(x, y)]);       }     }   }   // This is the key method for computing Julia sets. For each point z   // in the complex plane, we repeatedly compute z = z*z + c using complex   // arithmetic. We stop iterating when the magnitude of z exceeds 2 or   // after 64 iterations. We return the number of iterations-1.   public int testPoint(double zx, double zy) {     for (int i = 0; i < colors.length; i++) {       // Compute z = z*z + c;       double newx = zx * zx - zy * zy + cx;       double newy = 2 * zx * zy + cy;       zx = newx;       zy = newy;       // Check magnitude of z and return iteration number       if (zx * zx + zy * zy > 4)         return i;     }     return colors.length - 1;   }   // This method overrides JComponent to display the julia set.   // Just scale the image to fit and draw it.   public void paintComponent(Graphics g) {     g.drawImage(image, 0, 0, getWidth(), getHeight(), this);   }   // This method demonstrates the Java 1.1 java.awt.PrintJob printing API.   // It also demonstrates the JobAttributes and PageAttributes classes   // added in Java 1.3. Display the Julia set with ShowBean and use   // the Command menu to invoke this print command.   public void print() {     // Create some attributes objects. This is Java 1.3 stuff.     // In Java 1.1, we'd use a java.util.Preferences object instead.     JobAttributes jattrs = new JobAttributes();     PageAttributes pattrs = new PageAttributes();     // Set some example attributes: monochrome, landscape mode     pattrs.setColor(PageAttributes.ColorType.MONOCHROME);     pattrs.setOrientationRequested(PageAttributes.OrientationRequestedType.LANDSCAPE);     // Print to file by default     jattrs.setDestination(JobAttributes.DestinationType.FILE);     jattrs.setFileName("juliaset.ps");     // Look up the Frame that holds this component     Component frame = this;     while (!(frame instanceof Frame))       frame = frame.getParent();     // Get a PrintJob object to print the Julia set with.     // The getPrintJob() method displays a print dialog and allows the user     // to override and modify the default JobAttributes and PageAttributes     Toolkit toolkit = this.getToolkit();     PrintJob job = toolkit.getPrintJob((Frame) frame, "JuliaSet1", jattrs, pattrs);     // We get a null PrintJob if the user clicked cancel     if (job == null)       return;     // Get a Graphics object from the PrintJob.     // We print simply by drawing to this Graphics object.     Graphics g = job.getGraphics();     // Center the image on the page     Dimension pagesize = job.getPageDimension(); // how big is page?     Dimension panesize = this.getSize(); // how big is image?     g.translate((pagesize.width - panesize.width) / 2, // center it         (pagesize.height - panesize.height) / 2);     // Draw a box around the Julia Set and label it     g.drawRect(-1, -1, panesize.width + 2, panesize.height + 2);     g.drawString("Julia Set for c={" + cx + "," + cy + "}", 0, -15);     // Set a clipping region     g.setClip(0, 0, panesize.width, panesize.height);     // Now print the component by calling its paint method     this.paint(g);     // Finally tell the printer we're done with the page.     // No output will be generated if we don't call dispose() here.     g.dispose();   } }