/* * PrintPanel.java */ package net.sf.openrocket.gui.dialogs; import java.awt.Color; import java.awt.Desktop; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.Iterator; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.print.PrintController; import net.sf.openrocket.gui.print.PrintSettings; import net.sf.openrocket.gui.print.PrintableContext; import net.sf.openrocket.gui.print.TemplateProperties; import net.sf.openrocket.gui.print.components.CheckTreeManager; import net.sf.openrocket.gui.print.components.RocketPrintTree; import net.sf.openrocket.gui.util.FileHelper; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.startup.Application; /** * This class isolates the Swing components used to create a panel that is added to a standard Java print dialog. */ public class PrintDialog extends JDialog implements TreeSelectionListener { private static final Logger log = LoggerFactory.getLogger(PrintDialog.class); private static final Translator trans = Application.getTranslator(); private final Desktop desktop; private final RocketPrintTree stagedTree; private final RocketPrintTree noStagedTree; private OpenRocketDocument document; private RocketPrintTree currentTree; private JButton previewButton; private JButton saveAsPDF; private JButton cancel; private double rotation = 0d; private final static SwingPreferences prefs = (SwingPreferences) Application.getPreferences(); /** * Constructor. * * @param parent the parent awt component * @param orDocument the OR rocket container * @param theRotation the angle of rocket figure rotation */ public PrintDialog(Window parent, OpenRocketDocument orDocument, double theRotation) { super(parent, trans.get("title"), ModalityType.APPLICATION_MODAL); JPanel panel = new JPanel(new MigLayout("fill, gap rel unrel")); this.add(panel); rotation = theRotation; // before any Desktop APIs are used, first check whether the API is // supported by this particular VM on this particular host if (Desktop.isDesktopSupported()) { desktop = Desktop.getDesktop(); } else { desktop = null; } document = orDocument; Rocket rocket = orDocument.getRocket(); noStagedTree = RocketPrintTree.create(rocket.getName()); noStagedTree.setShowsRootHandles(false); CheckTreeManager ctm = new net.sf.openrocket.gui.print.components.CheckTreeManager(noStagedTree); ctm.addTreeSelectionListener(this); final int stages = rocket.getStageCount(); JLabel label = new JLabel(trans.get("lbl.selectElements")); panel.add(label, "wrap unrel"); // Create the tree if (stages > 1) { stagedTree = RocketPrintTree.create(rocket.getName(), rocket.getChildren()); ctm = new CheckTreeManager(stagedTree); stagedTree.setShowsRootHandles(false); ctm.addTreeSelectionListener(this); } else { stagedTree = noStagedTree; } currentTree = stagedTree; // Add the tree to the UI final JScrollPane scrollPane = new JScrollPane(stagedTree); panel.add(scrollPane, "width 400lp, height 200lp, grow, wrap para"); // Checkboxes and buttons final JCheckBox sortByStage = new JCheckBox(trans.get("checkbox.showByStage")); sortByStage.setEnabled(stages > 1); sortByStage.setSelected(stages > 1); sortByStage.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (sortByStage.isEnabled()) { if (((JCheckBox) e.getSource()).isSelected()) { scrollPane.setViewportView(stagedTree); stagedTree.setExpandsSelectedPaths(true); currentTree = stagedTree; } else { scrollPane.setViewportView(noStagedTree); noStagedTree.setExpandsSelectedPaths(true); currentTree = noStagedTree; } } } }); panel.add(sortByStage, "aligny top, split"); panel.add(new JPanel(), "growx"); JButton settingsButton = new JButton(trans.get("printdlg.but.settings")); settingsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { PrintSettings settings = getPrintSettings(); log.debug("settings=" + settings); PrintSettingsDialog settingsDialog = new PrintSettingsDialog(PrintDialog.this, settings); settingsDialog.setVisible(true); setPrintSettings(settings); } }); panel.add(settingsButton, "wrap para"); previewButton = new JButton(trans.get("but.previewAndPrint")); previewButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { onPreview(); PrintDialog.this.setVisible(false); } }); panel.add(previewButton, "split, right, gap para"); saveAsPDF = new JButton(trans.get("printdlg.but.saveaspdf")); saveAsPDF.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (onSavePDF()) { PrintDialog.this.setVisible(false); } } }); panel.add(saveAsPDF, "right, gap para"); cancel = new JButton(trans.get("button.cancel")); cancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { PrintDialog.this.setVisible(false); } }); panel.add(cancel, "right, gap para"); expandAll(currentTree, true); if (currentTree != noStagedTree) { expandAll(noStagedTree, true); } GUIUtil.setDisposableDialogOptions(this, previewButton); } @Override public void valueChanged(final TreeSelectionEvent e) { final TreePath path = e.getNewLeadSelectionPath(); if (path != null) { previewButton.setEnabled(true); saveAsPDF.setEnabled(true); } else { previewButton.setEnabled(false); saveAsPDF.setEnabled(false); } } /** * If expand is true, expands all nodes in the tree. Otherwise, collapses all nodes in the theTree. * * @param theTree the tree to expand/contract * @param expand expand if true, contract if not */ public void expandAll(RocketPrintTree theTree, boolean expand) { TreeNode root = (TreeNode) theTree.getModel().getRoot(); // Traverse theTree from root expandAll(theTree, new TreePath(root), expand); } /** * Recursively walk a tree, and if expand is true, expands all nodes in the tree. Otherwise, collapses all nodes in * the theTree. * * @param theTree the tree to expand/contract * @param parent the node to iterate/recurse over * @param expand expand if true, contract if not */ private void expandAll(RocketPrintTree theTree, TreePath parent, boolean expand) { theTree.addSelectionPath(parent); // Traverse children TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration<?> e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); expandAll(theTree, path, expand); } } // Expansion or collapse must be done bottom-up if (expand) { theTree.expandPath(parent); } else { theTree.collapsePath(parent); } } /** * Generate a report using a temporary file. The file will be deleted upon JVM exit. * * @param settings the container of different print settings * * @return a file, populated with the "printed" output (the rocket info) * * @throws IOException thrown if the file could not be generated */ private File generateReport(PrintSettings settings) throws IOException { final File f = File.createTempFile("openrocket-", ".pdf"); f.deleteOnExit(); return generateReport(f, settings); } /** * Generate a report to a specified file. * * @param f the file to which rocket data will be written * @param settings the container of different print settings * * @return a file, populated with the "printed" output (the rocket info) * * @throws IOException thrown if the file could not be generated */ private File generateReport(File f, PrintSettings settings) throws IOException { Iterator<PrintableContext> toBePrinted = currentTree.getToBePrinted(); new PrintController().print(document, toBePrinted, new FileOutputStream(f), settings, rotation); return f; } /** * Handler for when the Preview button is clicked. */ private void onPreview() { if (desktop != null) { try { PrintSettings settings = getPrintSettings(); // TODO: HIGH: Remove UIManager, and pass settings to the actual printing methods TemplateProperties.setColors(settings); File f = generateReport(settings); desktop.open(f); } catch (IOException e) { log.error("Could not open preview.", e); JOptionPane.showMessageDialog(this, new String[] { trans.get("error.preview.desc1"), trans.get("error.preview.desc2") }, trans.get("error.preview.title"), JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(this, new String[] { trans.get("error.preview.desc1"), trans.get("error.preview.desc2") }, trans.get("error.preview.title"), JOptionPane.INFORMATION_MESSAGE); } } /** * Handler for when the "Save as PDF" button is clicked. * * @return true if the PDF was saved */ private boolean onSavePDF() { JFileChooser chooser = new JFileChooser(); chooser.setFileFilter(FileHelper.PDF_FILTER); // Select initial directory File dir = document.getFile(); if (dir != null) { dir = dir.getParentFile(); } if (dir == null) { dir = prefs.getDefaultDirectory(); } chooser.setCurrentDirectory(dir); int returnVal = chooser.showSaveDialog(this); File file = chooser.getSelectedFile(); if (returnVal == JFileChooser.APPROVE_OPTION && file != null) { file = FileHelper.ensureExtension(file, "pdf"); if (!FileHelper.confirmWrite(file, this)) { return false; } try { PrintSettings settings = getPrintSettings(); // TODO: HIGH: Remove UIManager, and pass settings to the actual printing methods TemplateProperties.setColors(settings); generateReport(file, settings); } catch (IOException e) { FileHelper.errorWriting(e, this); return false; } return true; } else { return false; } } public PrintSettings getPrintSettings() { PrintSettings settings = new PrintSettings(); Color c; c = prefs.getColor("print.template.fillColor", (java.awt.Color) null); if (c != null) { settings.setTemplateFillColor(c); } c = prefs.getColor("print.template.borderColor", (java.awt.Color) null); if (c != null) { settings.setTemplateBorderColor(c); } settings.setPaperSize(prefs.getEnum("print.paper.size", settings.getPaperSize())); settings.setPaperOrientation(prefs.getEnum("print.paper.orientation", settings.getPaperOrientation())); return settings; } public void setPrintSettings(PrintSettings settings) { prefs.putColor("print.template.fillColor", settings.getTemplateFillColor() ); prefs.putColor("print.template.borderColor", settings.getTemplateBorderColor() ); prefs.putEnum("print.paper.size", settings.getPaperSize()); prefs.putEnum("print.paper.orientation", settings.getPaperOrientation()); } }