4 package net.sf.openrocket.gui.dialogs;
6 import java.awt.Desktop;
7 import java.awt.Window;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 import java.util.Enumeration;
14 import java.util.Iterator;
16 import javax.swing.JButton;
17 import javax.swing.JCheckBox;
18 import javax.swing.JDialog;
19 import javax.swing.JFileChooser;
20 import javax.swing.JLabel;
21 import javax.swing.JOptionPane;
22 import javax.swing.JPanel;
23 import javax.swing.JScrollPane;
24 import javax.swing.event.TreeSelectionEvent;
25 import javax.swing.event.TreeSelectionListener;
26 import javax.swing.filechooser.FileFilter;
27 import javax.swing.tree.TreeNode;
28 import javax.swing.tree.TreePath;
30 import net.miginfocom.swing.MigLayout;
31 import net.sf.openrocket.document.OpenRocketDocument;
32 import net.sf.openrocket.gui.main.ExceptionHandler;
33 import net.sf.openrocket.gui.print.PrintController;
34 import net.sf.openrocket.gui.print.PrintSettings;
35 import net.sf.openrocket.gui.print.PrintableContext;
36 import net.sf.openrocket.gui.print.TemplateProperties;
37 import net.sf.openrocket.gui.print.components.CheckTreeManager;
38 import net.sf.openrocket.gui.print.components.RocketPrintTree;
39 import net.sf.openrocket.l10n.Translator;
40 import net.sf.openrocket.logging.LogHelper;
41 import net.sf.openrocket.rocketcomponent.Rocket;
42 import net.sf.openrocket.startup.Application;
43 import net.sf.openrocket.util.GUIUtil;
44 import net.sf.openrocket.util.Prefs;
47 * This class isolates the Swing components used to create a panel that is added to a standard Java print dialog.
49 public class PrintDialog extends JDialog implements TreeSelectionListener {
51 private static final LogHelper log = Application.getLogger();
52 private static final Translator trans = Application.getTranslator();
54 private final Desktop desktop;
56 private final RocketPrintTree stagedTree;
57 private final RocketPrintTree noStagedTree;
58 private OpenRocketDocument document;
59 private RocketPrintTree currentTree;
61 private JButton previewButton;
62 private JButton saveAsPDF;
63 private JButton cancel;
68 * @param orDocument the OR rocket container
70 public PrintDialog(Window parent, OpenRocketDocument orDocument) {
71 super(parent, trans.get("title"), ModalityType.APPLICATION_MODAL);
74 JPanel panel = new JPanel(new MigLayout("fill, gap rel unrel"));
78 // before any Desktop APIs are used, first check whether the API is
79 // supported by this particular VM on this particular host
80 if (Desktop.isDesktopSupported()) {
81 desktop = Desktop.getDesktop();
86 document = orDocument;
87 Rocket rocket = orDocument.getRocket();
89 noStagedTree = RocketPrintTree.create(rocket.getName());
90 noStagedTree.setShowsRootHandles(false);
91 CheckTreeManager ctm = new net.sf.openrocket.gui.print.components.CheckTreeManager(noStagedTree);
92 ctm.addTreeSelectionListener(this);
94 final int stages = rocket.getStageCount();
97 JLabel label = new JLabel(trans.get("lbl.selectElements"));
98 panel.add(label, "wrap unrel");
102 stagedTree = RocketPrintTree.create(rocket.getName(), rocket.getChildren());
103 ctm = new CheckTreeManager(stagedTree);
104 stagedTree.setShowsRootHandles(false);
105 ctm.addTreeSelectionListener(this);
107 stagedTree = noStagedTree;
109 currentTree = stagedTree;
111 // Add the tree to the UI
112 final JScrollPane scrollPane = new JScrollPane(stagedTree);
113 panel.add(scrollPane, "width 400lp, height 200lp, grow, wrap para");
116 // Checkboxes and buttons
117 final JCheckBox sortByStage = new JCheckBox(trans.get("checkbox.showByStage"));
118 sortByStage.setEnabled(stages > 1);
119 sortByStage.setSelected(stages > 1);
120 sortByStage.addActionListener(new ActionListener() {
122 public void actionPerformed(ActionEvent e) {
123 if (sortByStage.isEnabled()) {
124 if (((JCheckBox) e.getSource()).isSelected()) {
125 scrollPane.setViewportView(stagedTree);
126 stagedTree.setExpandsSelectedPaths(true);
127 currentTree = stagedTree;
130 scrollPane.setViewportView(noStagedTree);
131 noStagedTree.setExpandsSelectedPaths(true);
132 currentTree = noStagedTree;
137 panel.add(sortByStage, "aligny top, split");
140 panel.add(new JPanel(), "growx");
143 JButton settingsButton = new JButton(trans.get("printdlg.but.settings"));
144 settingsButton.addActionListener(new ActionListener() {
146 public void actionPerformed(ActionEvent e) {
147 PrintSettings settings = Prefs.getPrintSettings();
148 log.debug("settings=" + settings);
149 PrintSettingsDialog settingsDialog = new PrintSettingsDialog(PrintDialog.this, settings);
150 settingsDialog.setVisible(true);
151 Prefs.setPrintSettings(settings);
154 panel.add(settingsButton, "wrap para");
157 previewButton = new JButton(trans.get("but.previewAndPrint"));
158 previewButton.addActionListener(new ActionListener() {
160 public void actionPerformed(ActionEvent e) {
162 PrintDialog.this.setVisible(false);
165 panel.add(previewButton, "split, right, gap para");
168 saveAsPDF = new JButton(trans.get("printdlg.but.saveaspdf"));
169 saveAsPDF.addActionListener(new ActionListener() {
171 public void actionPerformed(ActionEvent e) {
173 PrintDialog.this.setVisible(false);
177 panel.add(saveAsPDF, "right, gap para");
180 cancel = new JButton(trans.get("button.cancel"));
181 cancel.addActionListener(new ActionListener() {
183 public void actionPerformed(ActionEvent e) {
184 PrintDialog.this.setVisible(false);
187 panel.add(cancel, "right, gap para");
190 expandAll(currentTree, true);
191 if (currentTree != noStagedTree) {
192 expandAll(noStagedTree, true);
196 GUIUtil.setDisposableDialogOptions(this, previewButton);
202 public void valueChanged(final TreeSelectionEvent e) {
203 final TreePath path = e.getNewLeadSelectionPath();
205 previewButton.setEnabled(true);
206 saveAsPDF.setEnabled(true);
208 previewButton.setEnabled(false);
209 saveAsPDF.setEnabled(false);
214 * If expand is true, expands all nodes in the tree. Otherwise, collapses all nodes in the theTree.
216 * @param theTree the tree to expand/contract
217 * @param expand expand if true, contract if not
219 public void expandAll(RocketPrintTree theTree, boolean expand) {
220 TreeNode root = (TreeNode) theTree.getModel().getRoot();
221 // Traverse theTree from root
222 expandAll(theTree, new TreePath(root), expand);
226 * Recursively walk a tree, and if expand is true, expands all nodes in the tree. Otherwise, collapses all nodes in
229 * @param theTree the tree to expand/contract
230 * @param parent the node to iterate/recurse over
231 * @param expand expand if true, contract if not
233 private void expandAll(RocketPrintTree theTree, TreePath parent, boolean expand) {
234 theTree.addSelectionPath(parent);
236 TreeNode node = (TreeNode) parent.getLastPathComponent();
237 if (node.getChildCount() >= 0) {
238 for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
239 TreeNode n = (TreeNode) e.nextElement();
240 TreePath path = parent.pathByAddingChild(n);
241 expandAll(theTree, path, expand);
244 // Expansion or collapse must be done bottom-up
246 theTree.expandPath(parent);
248 theTree.collapsePath(parent);
255 * Generate a report using a temporary file. The file will be deleted upon JVM exit.
257 * @param paper the name of the paper size
259 * @return a file, populated with the "printed" output (the rocket info)
261 * @throws IOException thrown if the file could not be generated
263 private File generateReport(PrintSettings settings) throws IOException {
264 final File f = File.createTempFile("openrocket-", ".pdf");
266 return generateReport(f, settings);
270 * Generate a report to a specified file.
272 * @param f the file to which rocket data will be written
273 * @param paper the name of the paper size
275 * @return a file, populated with the "printed" output (the rocket info)
277 * @throws IOException thrown if the file could not be generated
279 private File generateReport(File f, PrintSettings settings) throws IOException {
280 Iterator<PrintableContext> toBePrinted = currentTree.getToBePrinted();
281 new PrintController().print(document, toBePrinted, new FileOutputStream(f), settings);
287 * Handler for when the Preview button is clicked.
289 private void onPreview() {
290 if (desktop != null) {
292 PrintSettings settings = Prefs.getPrintSettings();
293 // TODO: HIGH: Remove UIManager, and pass settings to the actual printing methods
294 TemplateProperties.setColors(settings);
295 File f = generateReport(settings);
297 } catch (IOException e) {
298 log.error("Could not open preview.", e);
299 JOptionPane.showMessageDialog(this, new String[] {
300 trans.get("error.preview.desc1"),
301 trans.get("error.preview.desc2") },
302 trans.get("error.preview.title"),
303 JOptionPane.ERROR_MESSAGE);
306 JOptionPane.showMessageDialog(this, new String[] {
307 trans.get("error.preview.desc1"),
308 trans.get("error.preview.desc2") },
309 trans.get("error.preview.title"),
310 JOptionPane.INFORMATION_MESSAGE);
315 * Handler for when the "Save as PDF" button is clicked.
317 * @return true if the PDF was saved
319 private boolean onSavePDF() {
321 JFileChooser chooser = new JFileChooser();
322 // Note: source for ExampleFileFilter can be found in FileChooserDemo,
323 // under the demo/jfc directory in the Java 2 SDK, Standard Edition.
324 FileFilter filter = new FileFilter() {
326 //Accept all directories and all pdf files.
328 public boolean accept(File f) {
331 return f.getName().toLowerCase().endsWith(".pdf");
334 //The description of this filter
336 public String getDescription() {
337 return trans.get("filetypes.pdf");
340 chooser.setFileFilter(filter);
341 int returnVal = chooser.showSaveDialog(this);
342 if (returnVal == JFileChooser.APPROVE_OPTION) {
345 String fname = chooser.getSelectedFile().getCanonicalPath();
346 if (!getExtension(fname).equals("pdf")) {
347 fname = fname + ".pdf";
349 File f = new File(fname);
350 PrintSettings settings = Prefs.getPrintSettings();
351 // TODO: HIGH: Remove UIManager, and pass settings to the actual printing methods
352 TemplateProperties.setColors(settings);
353 generateReport(f, settings);
354 } catch (IOException e) {
355 ExceptionHandler.handleErrorCondition(e);
364 * Get the extension of a file.
366 private static String getExtension(String s) {
368 int i = s.lastIndexOf('.');
370 if (i > 0 && i < s.length() - 1) {
371 ext = s.substring(i + 1).toLowerCase();
373 return ext != null ? ext : "";