package com.horstmann.violet.framework; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.print.Book; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.util.ResourceBundle; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; /** * This class implements a dialog for previewing and printing a graph. */ public class PrintDialog extends JDialog { /** * Constructs a print dialog. * @param gr the graph to be printed */ public PrintDialog(Graph gr) { this.graph = gr; PrinterJob job = PrinterJob.getPrinterJob(); pageFormat = job.defaultPage(); attributes = new HashPrintRequestAttributeSet(); layoutUI(); pack(); } /** * Lays out the UI of the dialog. */ public void layoutUI() { canvas = new PrintPreviewCanvas(this); getContentPane().add(canvas, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); ResourceFactory factory = new ResourceFactory( ResourceBundle.getBundle("com.horstmann.violet.framework.EditorStrings")); JButton printButton = factory.createButton("dialog.print.print"); buttonPanel.add(printButton); printButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { setVisible(false); PrinterJob job = PrinterJob.getPrinterJob(); job.setPageable(makeBook()); if (job.printDialog(attributes)) { pageFormat = job.validatePage(pageFormat); job.print(attributes); } } catch (PrinterException e) { JOptionPane.showMessageDialog( PrintDialog.this, e); } } }); JButton moreButton = factory.createButton("dialog.print.more"); buttonPanel.add(moreButton); moreButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { scaleGraph *= Math.sqrt(2); canvas.repaint(); } }); JButton fewerButton = factory.createButton("dialog.print.fewer"); buttonPanel.add(fewerButton); fewerButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { scaleGraph /= Math.sqrt(2); canvas.repaint(); } }); JButton onePageButton = factory.createButton("dialog.print.one"); buttonPanel.add(onePageButton); onePageButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { while (getRows() * getCols() > 1) scaleGraph /= Math.sqrt(2); canvas.repaint(); } }); JButton pageSetupButton = factory.createButton("dialog.print.page"); buttonPanel.add(pageSetupButton); pageSetupButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { PrinterJob job = PrinterJob.getPrinterJob(); PageFormat newPageFormat = job.pageDialog(attributes); if (newPageFormat != null) pageFormat = newPageFormat; canvas.repaint(); } }); JButton closeButton = factory.createButton("dialog.print.close"); buttonPanel.add(closeButton); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { setVisible(false); } }); getContentPane().add(buttonPanel, BorderLayout.SOUTH); } /** * Makes a book consisting of the pages to be printed. * @return the book to be printed */ private Book makeBook() { Book book = new Book(); final int pageCount = getRows() * getCols(); Printable printable = new Printable() { public int print(Graphics g, PageFormat pf, int page) throws PrinterException { Graphics2D g2 = (Graphics2D) g; if (page > pageCount) return Printable.NO_SUCH_PAGE; g2.translate(pf.getImageableX(), pf.getImageableY()); drawPage(g2, pf, page); return Printable.PAGE_EXISTS; } public void drawPage(Graphics2D g2, PageFormat pf, int page) { int cols = getCols(); int row = page / cols; int col = page % cols; double px = pageFormat.getImageableWidth(); double py = pageFormat.getImageableHeight(); g2.clip(new Rectangle2D.Double(0, 0, px, py)); g2.translate(-col * px, -row * py); g2.scale((float) scaleGraph, (float) scaleGraph); g2.translate((float) -bounds.getX(), (float) -bounds.getY()); g2.setColor(Color.BLACK); g2.setBackground(Color.WHITE); graph.draw(g2, null); } }; book.append(printable, pageFormat, pageCount); return book; } /** * Gets the number of columns currently required for the printout * @return the number of columns (>= 1) */ int getCols() { return (int) Math.max(1, Math.ceil(bounds.getWidth() * scaleGraph / pageFormat.getImageableWidth())); } /** * Gets the number of rows currently required for the printout * @return the number of rows (>= 1) */ int getRows() { return (int) Math.max(1, Math.ceil(bounds.getHeight() * scaleGraph / pageFormat.getImageableHeight())); } PrintPreviewCanvas canvas; PageFormat pageFormat; PrintRequestAttributeSet attributes; Graph graph; Rectangle2D bounds; double scaleGraph = 1; boolean showCropMarks; }