package javacodebook.media.print.graphic;

import java.awt.*;
import java.awt.print.*;
import javax.swing.JPanel;

/**
 * Ein Panel, dass eine Grafik auf sich selbst darstellt, in der Originalgröße.
 * Die Größe des Panels wird entsprechend angepasst, kann aber größer sein
 * als die Grafik, wenn das Panel von der umgebenden Komponente größer
 * gezogen wird (z.B. in einer JScrollPane, die größer ist als die Grafik).
 * Damit das Panel ausdruck-fähig ist, implementiert es das Interface
 * java.awt.print.Printable. Die Grafik wird immer auf max. einer Seite
 * ausgedruckt.
 */
public class PrintableImagePanel extends javax.swing.JPanel implements Printable{
    //Die Grafik, die angezeigt werden soll
    private Image image;

    public PrintableImagePanel(Image image) {
        this.image = image;
        this.setBackground(Color.white);//evtl. treten sonst graue Ränder auf
    }

    /*
     * Hier wird die Grafik auf das Panel gezeichnet. Das Panel kann evtl.
     * größer sein als die Grafik, dann bleibt rechts oder unten ein grauer
     * Rand, der beim Druck nicht berücksichtigt wird.
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, image.getWidth(this), image.getHeight(this), this);
    }

    /* Es wird die Größe der Grafik als PreferredSize zurückgegeben */
    public Dimension getPreferredSize() {
        return new Dimension(image.getWidth(this), image.getHeight(this));
    }

    /* Die print-Methode aus dem Interface Printable */
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
    throws PrinterException {
        //Das Graphics-Objekt wird in ein Graphics2D-Objekt gecastet
        //um besser verarbeitet werden zu können
        Graphics2D g2 = (Graphics2D)graphics;

        //DoubleBuffering im Panel für den Druck ausschalten
        this.setDoubleBuffered(false);

        //Größe des Druckbereichs berechnen
        //Zunächst werden die Maße der Grafik ermittelt (in Pixel)
        double imageWidth  = image.getWidth(this);
        double imageHeight = image.getHeight(this);

        //Jetzt werden die Papiermaße ermittelt, die das Papierformat
        //vorgibt
        double pageWidth  = pageFormat.getImageableWidth();
        double pageHeight = pageFormat.getImageableHeight();

        double scale = 1; //Grafik kleiner als Papier: Masstab = 1
        //Ist die Grafik breiter oder höher als das Papier, so muss sie skaliert
        //werden
        if(imageWidth > pageWidth || imageHeight > pageHeight) {
            if(imageWidth/imageHeight > pageWidth/pageHeight)
                //Grafik auf Papierbreite skalieren
                scale = pageWidth/imageWidth;
            else
                //Grafik auf Papierhöhe skalieren
                scale = pageHeight/imageHeight;
        }

        //Da die Voreinstellung beim Druck gerne "Seite 1 - 9999"
        //lautet, werden die vielen Leerseiten hier weggelassen.
        if(pageIndex > 0)
            return Printable.NO_SUCH_PAGE;

        //Der zu druckende Grafikbereich wird in die linke obere
        //Ecke des Druckbereichs der Papierseite verschoben, damit
        //werden die Seitenränder berücksichtigt
        g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        //Evtl. nötige Skalierung durchführen
        g2.scale(scale, scale);
        //Grafikbereich für den Druck neu zeichnen
        paint(g2);

        //DoubleBuffering in der EditorPane wieder einschalten
        this.setDoubleBuffered(true);
        //Dem Druckjob mitteilen, dass eine Seite für den Druck
        //existiert
        return Printable.PAGE_EXISTS;
    }

}
