ca.sqlpower.architect.swingui.action.ExportPlaypenToPDFAction.java Source code

Java tutorial

Introduction

Here is the source code for ca.sqlpower.architect.swingui.action.ExportPlaypenToPDFAction.java

Source

/*
 * Copyright (c) 2008, SQL Power Group Inc.
 *
 * This file is part of Power*Architect.
 *
 * Power*Architect is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Power*Architect is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */
package ca.sqlpower.architect.swingui.action;

import java.awt.Font;
import java.awt.Graphics2D;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import org.apache.log4j.Logger;

import ca.sqlpower.architect.ArchitectVersion;
import ca.sqlpower.architect.swingui.ASUtils;
import ca.sqlpower.architect.swingui.ArchitectFrame;
import ca.sqlpower.architect.swingui.ArchitectSwingSession;
import ca.sqlpower.architect.swingui.PlayPen;
import ca.sqlpower.architect.swingui.PlayPenComponent;
import ca.sqlpower.architect.swingui.PlayPenContentPane;
import ca.sqlpower.swingui.SPSUtils;
import ca.sqlpower.util.MonitorableImpl;

import com.lowagie.text.Document;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;

public class ExportPlaypenToPDFAction extends ProgressAction {
    private static final Logger logger = Logger.getLogger(ExportPlaypenToPDFAction.class);

    private static final String FILE_KEY = "FILE_KEY"; //$NON-NLS-1$

    private static int OUTSIDE_PADDING = 10;

    /**
     * A snapshot of the play pen. This play pen will look exactly like the play
     * pen the last time this action was called. This play pen will also be 
     * disconnected from the model in terms of listeners so it cannot change
     * the model, just draw it.
     * 
     * <p>
     * Note that the play pen this variable is pointing at may change during
     * export if the play pen is exported again while it is currently exporting.
     */
    private PlayPen playPen;

    /**
     * Creates an action that exports the session's relational playpen to a PDF
     * file.
     * 
     * @param session
     *            The session that owns this action.
     * @param playPen
     *            The playpen to export. Could be the relational playpen or one
     *            of the OLAP playpens.
     */
    public ExportPlaypenToPDFAction(ArchitectSwingSession session, PlayPen playPen) {
        super(session, playPen, Messages.getString("ExportPlaypenToPDFAction.name"), //$NON-NLS-1$
                Messages.getString("ExportPlaypenToPDFAction.description"), null); //$NON-NLS-1$
    }

    /**
     * Creates an action that exports the frame's current session's relational playpen to a PDF
     * file.
     * 
     * @param frame
     *            The ArchitectFrame that owns the action
     */
    public ExportPlaypenToPDFAction(ArchitectFrame frame) {
        super(frame, Messages.getString("ExportPlaypenToPDFAction.name"), //$NON-NLS-1$
                Messages.getString("ExportPlaypenToPDFAction.description"), null); //$NON-NLS-1$
    }

    /**
     *  When an action is performed on this it pops up the save dialog
     *  and requests a file to save to. When it gets that it draws the
     *  playpen to a PDF file on a seperate thread.
     */
    public boolean setup(MonitorableImpl monitor, Map<String, Object> properties) {
        monitor.setStarted(true);
        JFileChooser chooser = new JFileChooser(getSession().getRecentMenu().getMostRecentFile());
        chooser.addChoosableFileFilter(SPSUtils.PDF_FILE_FILTER);
        monitor.setJobSize(getPlaypen().getContentPane().getChildren().size());

        File file = null;
        while (true) {
            int response = chooser.showSaveDialog(getPlaypen());

            if (response != JFileChooser.APPROVE_OPTION) {
                return false;
            }
            file = chooser.getSelectedFile();
            String fileName = file.getName();

            if (!fileName.endsWith(".pdf")) { //$NON-NLS-1$
                file = new File(file.getPath() + ".pdf"); //$NON-NLS-1$
            }

            if (file.exists()) {
                response = JOptionPane.showConfirmDialog(null,
                        Messages.getString("ExportPlaypenToPDFAction.fileAlreadyExists", file.getPath()), //$NON-NLS-1$ //$NON-NLS-2$
                        Messages.getString("ExportPlaypenToPDFAction.fileAlreadyExistsDialogTitle"), //$NON-NLS-1$
                        JOptionPane.YES_NO_OPTION);
                if (response == JOptionPane.YES_OPTION) {
                    break;
                }
            } else {
                break;
            }
        }

        logger.debug("Saving to file: " + file.getName() + "(" + file.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

        properties.put(FILE_KEY, file);

        playPen = new PlayPen(getSession(), getPlaypen());

        // don't need this playpen to be interactive or respond to SQLObject changes
        playPen.destroy();

        return true;
    }

    @Override
    public void cleanUp(MonitorableImpl monitor) {
        // TODO might have to cleanup here
    }

    @Override
    public void doStuff(MonitorableImpl monitor, Map<String, Object> properties) {
        logger.debug("Creating PDF of playpen: " + getPlaypen());

        //This is the current play pen snapshot at the time of starting the worker
        //thread. This way the play pen doesn't change while it is printing.
        PlayPen pp = playPen;

        /* We translate the graphics to (OUTSIDE_PADDING, OUTSIDE_PADDING) 
         * so nothing is drawn right on the edge of the document. So
         * we multiply by 2 so we can accomodate the translate and ensure
         * nothing gets drawn outside of the document size.
         */
        final int width = pp.getBounds().width + 2 * OUTSIDE_PADDING;
        final int height = pp.getBounds().height + 2 * OUTSIDE_PADDING;
        final Rectangle ppSize = new Rectangle(width, height);

        OutputStream out = null;
        Document d = null;
        try {
            out = new BufferedOutputStream(new FileOutputStream((File) properties.get(FILE_KEY)));
            d = new Document(ppSize);

            d.addTitle(Messages.getString("ExportPlaypenToPDFAction.PdfTitle")); //$NON-NLS-1$
            d.addAuthor(System.getProperty("user.name")); //$NON-NLS-1$
            d.addCreator(Messages.getString("ExportPlaypenToPDFAction.powerArchitectVersion") //$NON-NLS-1$
                    + ArchitectVersion.APP_FULL_VERSION);

            PdfWriter writer = PdfWriter.getInstance(d, out);
            d.open();
            PdfContentByte cb = writer.getDirectContent();
            Graphics2D g = cb.createGraphicsShapes(width, height);
            // ensure a margin
            g.translate(OUTSIDE_PADDING, OUTSIDE_PADDING);
            PlayPenContentPane contentPane = pp.getContentPane();
            for (int i = 0; i < contentPane.getChildren().size(); i++) {
                PlayPenComponent ppc = contentPane.getChildren().get(i);
                if (logger.isDebugEnabled()) {
                    logger.debug("Painting component " + ppc);
                }
                g.translate(ppc.getLocation().x, ppc.getLocation().y);
                Font gFont = g.getFont();
                ppc.paint(g);
                g.setFont(gFont);
                g.translate(-ppc.getLocation().x, -ppc.getLocation().y);
                monitor.setProgress(i);
            }
            pp.paintComponent(g);
            g.dispose();
        } catch (Exception ex) {
            ASUtils.showExceptionDialog(getSession(),
                    Messages.getString("ExportPlaypenToPDFAction.couldNotExportPlaypen"), //$NON-NLS-1$
                    ex);
        } finally {
            if (d != null) {
                try {
                    d.close();
                } catch (Exception ex) {
                    ASUtils.showExceptionDialog(getSession(),
                            Messages.getString("ExportPlaypenToPDFAction.couldNotCloseDocument"), //$NON-NLS-1$
                            ex);
                }
            }
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException ex) {
                    ASUtils.showExceptionDialog(getSession(),
                            Messages.getString("ExportPlaypenToPDFAction.couldNotClosePdfFile"), //$NON-NLS-1$
                            ex);
                }
            }
        }
    }

    @Override
    public String getDialogMessage() {
        return Messages.getString("ExportPlaypenToPDFAction.creatingPdf"); //$NON-NLS-1$
    }

    @Override
    public String getButtonText() {
        return Messages.getString("ExportPlaypenToPDFAction.runInBackgroundOption"); //$NON-NLS-1$
    }
}