com.rapidminer.gui.actions.ExportPdfAction.java Source code

Java tutorial

Introduction

Here is the source code for com.rapidminer.gui.actions.ExportPdfAction.java

Source

/*
 *  RapidMiner
 *
 *  Copyright (C) 2001-2014 by RapidMiner and the contributors
 *
 *  Complete list of developers available at our web site:
 *
 *       http://rapidminer.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package com.rapidminer.gui.actions;

import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.FileOutputStream;

import javax.swing.JPanel;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import com.rapidminer.gui.RapidMinerGUI;
import com.rapidminer.gui.new_plotter.engine.jfreechart.link_and_brush.LinkAndBrushChartPanel;
import com.rapidminer.gui.new_plotter.gui.ChartConfigurationPanel;
import com.rapidminer.gui.new_plotter.templates.PlotterTemplate;
import com.rapidminer.gui.plotter.PlotterPanel;
import com.rapidminer.gui.tools.ResourceAction;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.gui.tools.dialogs.ConfirmDialog;

/** Action to create a PDF file from the given {@link Component}.
 * 
 * @author Marco Boeck
 *
 */
public class ExportPdfAction extends ResourceAction {

    private PlotterTemplate template;
    private Component component;
    private final String componentName;

    public ExportPdfAction(Component component, String componentName) {
        super(true, "export_pdf", componentName);
        this.component = component;
        this.componentName = componentName;
    }

    public ExportPdfAction(PlotterTemplate template) {
        super(true, "export_pdf", template.getChartType());
        this.componentName = template.getChartType();
        this.template = template;
    }

    private static final long serialVersionUID = 1L;

    @Override
    public void actionPerformed(ActionEvent e) {
        if (component != null) {
            createPdf(component);
            return;
        }
        if (template != null) {
            createPdf(template);
            return;
        }
    }

    /**
     * Create the PDF from a {@link Component}.
     * 
     * @param component
     */
    private void createPdf(Component component) {
        if (component == null) {
            return;
        }

        // prompt user for pdf location
        File file = promptForPdfLocation();
        if (file == null) {
            return;
        }

        try {
            // create pdf document
            Document document = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            PdfContentByte cb = writer.getDirectContent();
            createPdfViaTemplate(component, document, cb);
            document.close();
        } catch (Exception e) {
            SwingTools.showSimpleErrorMessage("cannot_export_pdf", e, e.getMessage());
        }
    }

    /**
     * Create the PDF from a {@link PlotterTemplate}.
     * 
     * @param template
     */
    private void createPdf(PlotterTemplate template) {
        if (template == null) {
            return;
        }

        // prompt user for pdf location
        File file = promptForPdfLocation();
        if (file == null) {
            return;
        }

        try {
            // create pdf document
            Document document = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            PdfContentByte cb = writer.getDirectContent();
            createPdfViaTemplate(template, document, cb);
            document.close();
        } catch (Exception e) {
            SwingTools.showSimpleErrorMessage("cannot_export_pdf", e, e.getMessage());
        }
    }

    /**
     * Prompts the user for the location of the .pdf file.
     * Will append .pdf if file does not end with it.
     * 
     * @return
     */
    private File promptForPdfLocation() {
        // prompt user for pdf location
        File file = SwingTools.chooseFile(RapidMinerGUI.getMainFrame(), "export_pdf", null, false, false,
                new String[] { "pdf" }, new String[] { "PDF" }, false);
        if (file == null) {
            return null;
        }
        if (!file.getName().endsWith(".pdf")) {
            file = new File(file.getAbsolutePath() + ".pdf");
        }
        // prompt for overwrite confirmation
        if (file.exists()) {
            int returnVal = SwingTools.showConfirmDialog("export_pdf", ConfirmDialog.YES_NO_OPTION, file.getName());
            if (returnVal == ConfirmDialog.NO_OPTION) {
                return null;
            }
        }
        return file;
    }

    /**
     * Creates a pdf showing the given {@link Component} via {@link PdfTemplate} usage.
     * @param component
     * @param document
     * @param cb
     * @throws DocumentException
     */
    private void createPdfViaTemplate(Component component, Document document, PdfContentByte cb)
            throws DocumentException {
        PdfTemplate tp = cb.createTemplate(500, PageSize.A4.getHeight() / 2);
        Graphics2D g2 = tp.createGraphics(500, PageSize.A4.getHeight() / 2);

        // special handling for charts as we only want to export the chart but not the control panel
        // chart cannot be scaled to size of component because otherwise we would break the chart aspect-ratio
        if (component.getClass().isAssignableFrom(JPanel.class)) {
            JPanel panel = (JPanel) component;
            if (panel.getLayout().getClass().isAssignableFrom(CardLayout.class)) {
                for (final Component comp : panel.getComponents()) {
                    // iterate over all card components and see if there is a chart which would require special handling
                    // if not we don't do anything in this loop and do the standard behavior at the bottom of the method
                    if (comp.isVisible() && ChartConfigurationPanel.class.isAssignableFrom(comp.getClass())) {
                        final ChartConfigurationPanel chartConfigPanel = (ChartConfigurationPanel) comp;

                        // create new LinkAndBrushChartPanel with double buffering set to false to get vector graphic export
                        // The real chart has to use double buffering for a) performance and b) zoom rectangle drawing
                        LinkAndBrushChartPanel newLaBPanel = new LinkAndBrushChartPanel(
                                chartConfigPanel.getPlotEngine().getChartPanel().getChart(),
                                chartConfigPanel.getPlotEngine().getChartPanel().getWidth(),
                                chartConfigPanel.getPlotEngine().getChartPanel().getHeight(),
                                chartConfigPanel.getPlotEngine().getChartPanel().getMinimumDrawWidth(),
                                chartConfigPanel.getPlotEngine().getChartPanel().getMinimumDrawHeight(), false,
                                false);
                        newLaBPanel.setSize(chartConfigPanel.getPlotEngine().getChartPanel().getSize());
                        newLaBPanel
                                .setOverlayList(chartConfigPanel.getPlotEngine().getChartPanel().getOverlayList());
                        AffineTransform at = new AffineTransform();
                        double factor = 500d / chartConfigPanel.getPlotEngine().getChartPanel().getWidth();
                        at.scale(factor, factor);
                        g2.transform(at);
                        newLaBPanel.print(g2);
                        g2.dispose();
                        document.add(new Paragraph(componentName));
                        document.add(Image.getInstance(tp));

                        return;
                    } else if (comp.isVisible() && PlotterPanel.class.isAssignableFrom(comp.getClass())) {
                        // special case for PlotterPanel as the Panel itself is wider than the plotter
                        // not having a special case here results in the exported image being too wide (empty space to the left)
                        final PlotterPanel plotterPanel = (PlotterPanel) comp;

                        AffineTransform at = new AffineTransform();
                        double factor = 500d / plotterPanel.getPlotterComponent().getWidth();
                        at.scale(factor, factor);
                        g2.transform(at);
                        plotterPanel.print(g2);
                        g2.dispose();
                        document.add(new Paragraph(componentName));
                        document.add(Image.getInstance(tp));

                        return;
                    }
                }
            }
        }

        AffineTransform at = new AffineTransform();
        double factor = 500d / component.getWidth();
        at.scale(factor, factor);
        g2.transform(at);
        component.print(g2);
        g2.dispose();
        document.add(new Paragraph(componentName));
        document.add(Image.getInstance(tp));
    }

    /**
     * Creates a pdf showing the given {@link PlotterTemplate} via {@link PdfTemplate} usage.
     * @param template
     * @param document
     * @param cb
     * @throws DocumentException
     */
    private void createPdfViaTemplate(PlotterTemplate template, Document document, PdfContentByte cb)
            throws DocumentException {
        PdfTemplate tp = cb.createTemplate(500, PageSize.A4.getHeight() / 2);
        Graphics2D g2 = tp.createGraphics(500, PageSize.A4.getHeight() / 2);
        AffineTransform at = new AffineTransform();
        double factor = 500d / template.getPlotEngine().getChartPanel().getWidth();
        at.scale(factor, factor);
        g2.transform(at);
        template.getPlotEngine().getChartPanel().print(g2);
        g2.dispose();
        document.add(new Paragraph(componentName));
        document.add(Image.getInstance(tp));
    }
}