/*
 * [TestPrinterJob.java]
 *
 * Summary: Demonstrate use of Print using PrinterJob.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2007-07-10
 */
package com.mindprod.example;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
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.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import static java.lang.System.*;

/**
 * Demonstrate use of Print using PrinterJob.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2007-07-10
 * @since 2007-07-10
 */
public final class TestPrinterJob extends JFrame implements Printable
    {
    /**
     * constructor
     *
     * @param title label for title of frame.
     */
    @SuppressWarnings( { "SameParameterValue", "WeakerAccess" } )
    public TestPrinterJob( String title )
        {
        super( title );
        }

    /**
     * print the entire frame, including the title bar with the close widget.
     */
    private void printFrame()
        {
        // Get a PrinterJob object to manage this print.
        // Note you can't directly instantiate one since
        // PrinterJob is abstract.
        PrinterJob printerJob = PrinterJob.getPrinterJob();
        // Print this component just the way item would appear on screen.
        // The rendering of item is handled by this component's print method,
        // that works just like paint except item gets passed a printer-style
        // Graphics object instead of a screen-style and draws in higher resolution.
        printerJob.setPrintable( this );
        // pop up a dialog box for the end user to fine tune the options.
        if ( printerJob.printDialog() )
            {
            try
                {
                // render the component onto the printer or print queue.
                printerJob.print();
                }
            catch ( PrinterException e )
                {
                err.println( "Error printing: " + e );
                }
            }
        }

    /**
     * standard main method to run the test.
     *
     * @param args not used
     */
    public static void main( String[] args )
        {
        JFrame.setDefaultLookAndFeelDecorated( true );
        final TestPrinterJob jframe = new TestPrinterJob( "TestPrinterJob" );
        final Container contentPane = jframe.getContentPane();
        jframe.setSize( 215, 100 );
        // Note that jframe.setBackground is almost useless.
        // You must set the background colour of the contentPane.
        contentPane.setBackground( Color.WHITE );
        contentPane.setForeground( Color.BLUE );
        contentPane.setLayout( new BorderLayout() );
        jframe.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        final JTextArea t =
                new JTextArea(
                        "All good men\n"
                        + "should come to the aid of the party."
                );
        contentPane.add( t, BorderLayout.NORTH );
        final JButton print = new JButton( "Print" );
        print.setBorder( BorderFactory.createRaisedBevelBorder() );
        print.setFocusPainted( false );
        print.setToolTipText( "Print the page" );
        print.setFont( new Font( "Dialog", Font.BOLD, 15 ) );
        print.addActionListener( new ActionListener()
            {
            /**
             * user clicked save.
             * @param event button push event
             */
            public void actionPerformed( ActionEvent event )
                {
                jframe.printFrame();
                } // end actionPerformed
            } );
        contentPane.add( print, BorderLayout.SOUTH );
        jframe.validate();
        jframe.setVisible( true );
        }

    /**
     * Draw this component on a printer, a page at a time.  This component may be so large it could never fit on a
     * screen.
     *
     * @param gr         the context into which the page is drawn, high res for printer.
     * @param pageFormat the paper size and orientation (landscape/portrait) of the page being drawn.
     * @param pageIndex  the zero based index of the page to be drawn.
     *
     * @return Printable.PAGE_EXISTS if the page was rendered successfully or Printable.NO_SUCH_PAGE if pageIndex
     * specifies a non-existent page. This is how the engine knows when you are done.
     */
    @SuppressWarnings( { "UnnecessaryLocalVariable" } )
    public int print( Graphics gr,
                      PageFormat pageFormat,
                      int pageIndex )
        {
        // Just like Component.paint.
        // In this example we ignore hints such as landscape/portrait in pageFormat
        // If you fail to return NO_SUCH_PAGE, you will get hundreds of pages
        // spewed out of your printer.
        if ( pageIndex > 0 )
            {
            return Printable.NO_SUCH_PAGE;
            }
        // We will be called twice, using "pixels" 1/72 inch across.
        // access extended 2D graphics methods.
        final Graphics2D g2 = ( Graphics2D ) gr;
        // save original transform
        final AffineTransform origTransform = g2.getTransform();
        // "Pixels" here are huge, 1/72 inch across! even though printer is using 600 dpi pixels.
        final AffineTransform transform = origTransform;
        // apply a border on left and top of equivalent of .5 inch.
        // Our values are specified in printer pixels.  36/72 inch border.
        transform.translate( 36.0d, 36.0d );
        g2.setTransform( transform );
        // usual Frame.paint()
        paint( gr );
        // You can also use drawString, drawImage etc  instead of paint to render
        // at a low evel.
        g2.setTransform( origTransform );
        return Printable.PAGE_EXISTS;
        }
    }