4 package net.sf.openrocket.gui.dialogs;
6 import net.sf.openrocket.document.OpenRocketDocument;
7 import net.sf.openrocket.gui.print.PDFPrintStreamDoc;
8 import net.sf.openrocket.gui.print.PrintUtilities;
9 import sun.print.ServiceDialog;
11 import javax.print.DocFlavor;
12 import javax.print.DocPrintJob;
13 import javax.print.PrintException;
14 import javax.print.PrintService;
15 import javax.print.PrintServiceLookup;
16 import javax.print.attribute.Attribute;
17 import javax.print.attribute.AttributeSet;
18 import javax.print.attribute.HashPrintRequestAttributeSet;
19 import javax.print.attribute.PrintRequestAttributeSet;
20 import javax.print.attribute.standard.Destination;
21 import javax.print.attribute.standard.Fidelity;
22 import javax.swing.JDialog;
23 import javax.swing.JMenu;
24 import javax.swing.JTabbedPane;
25 import java.awt.Component;
26 import java.awt.Container;
27 import java.awt.Dialog;
28 import java.awt.GraphicsConfiguration;
29 import java.awt.GraphicsDevice;
30 import java.awt.GraphicsEnvironment;
31 import java.awt.HeadlessException;
32 import java.awt.Rectangle;
33 import java.io.ByteArrayOutputStream;
36 * This class is not a dialog by inheritance, but is by delegation. It front-ends a java print dialog by
37 * augmenting it with application specific (rocket) settings.
39 public class PrintDialog {
42 * The service UI dialog.
44 private ServiceDialog dialog;
47 * A javax doc flavor specific for printing PDF documents.
49 private static final DocFlavor.INPUT_STREAM PDF = DocFlavor.INPUT_STREAM.PDF;
52 * Construct a print dialog using an Open Rocket document - which contains the rocket data to ultimately be
55 * @param orDocument the rocket container
57 public PrintDialog (OpenRocketDocument orDocument) {
58 PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
59 PrintService svc = PrintServiceLookup.lookupDefaultPrintService();
60 PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
61 attrs.add(PrintUtilities.getDefaultMedia().getMediaSizeName());
63 final PrintPanel panel = new PrintPanel(orDocument, this);
64 PrintService ps = printDialog(null, 100, 100, services, svc, PDF, attrs, panel);
66 DocPrintJob dpj = ps.createPrintJob();
68 System.err.println(attrs.size());
69 ByteArrayOutputStream baos = panel.generateReport();
70 dpj.print(new PDFPrintStreamDoc(baos, null), attrs);
72 catch (PrintException e) {
73 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
79 * Get the set of attributes from the service ui print dialog.
81 * @return a set of print attributes
83 PrintRequestAttributeSet getAttributes () {
84 return dialog.getAttributes();
88 * Get the service ui dialog. This is the actual dialog that gets displayed - we co-opt it for adding a rocket
91 * @return the Java service ui print dialog
93 JDialog getDialog () {
98 * Mimics the ServiceUI.printDialog method, but with enhancements for our own print settings tab.
100 * @param gc used to select screen. null means primary or default screen.
101 * @param x location of dialog including border in screen coordinates
102 * @param y location of dialog including border in screen coordinates
103 * @param services to be browsable, must be non-null.
104 * @param defaultService - initial PrintService to display.
105 * @param flavor - the flavor to be printed, or null.
106 * @param attributes on input is the initial application supplied preferences. This cannot be null but may be
107 * empty. On output the attributes reflect changes made by the user.
108 * @param addnl a panel to be added, as a tab, to the internal tabbed pane of the resulting print dialog
110 * @return print service selected by the user, or null if the user cancelled the dialog.
112 * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
113 * @throws IllegalArgumentException if services is null or empty, or attributes is null, or the initial PrintService
114 * is not in the list of browsable services.
116 private PrintService printDialog (GraphicsConfiguration gc,
118 PrintService[] services,
119 PrintService defaultService,
121 PrintRequestAttributeSet attributes,
123 throws HeadlessException {
124 int defaultIndex = -1;
126 if (GraphicsEnvironment.isHeadless()) {
127 throw new HeadlessException();
129 else if ((services == null) || (services.length == 0)) {
130 throw new IllegalArgumentException("services must be non-null " +
133 else if (attributes == null) {
134 throw new IllegalArgumentException("attributes must be non-null");
137 if (defaultService != null) {
138 for (int i = 0; i < services.length; i++) {
139 if (services[i].equals(defaultService)) {
145 if (defaultIndex < 0) {
146 throw new IllegalArgumentException("services must contain " +
154 Rectangle gcBounds = (gc == null) ? GraphicsEnvironment.
155 getLocalGraphicsEnvironment().getDefaultScreenDevice().
156 getDefaultConfiguration().getBounds() : gc.getBounds();
158 dialog = new ServiceDialog(gc,
161 services, defaultIndex,
164 Rectangle dlgBounds = dialog.getBounds();
166 // get union of all GC bounds
167 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
168 GraphicsDevice[] gs = ge.getScreenDevices();
169 for (GraphicsDevice g : gs) {
170 gcBounds = gcBounds.union(g.getDefaultConfiguration().getBounds());
173 // if portion of dialog is not within the gc boundary
174 if (!gcBounds.contains(dlgBounds)) {
175 // put in the center relative to parent frame/dialog
176 dialog.setLocationRelativeTo(null);
178 if (addnl != null && addnl.getTitle() != null) {
179 JTabbedPane tp = (JTabbedPane) getDescendantOfClass(JTabbedPane.class, dialog);
180 tp.add(addnl, addnl.getTitle(), 0);
181 tp.setSelectedIndex(0);
184 dialog.setVisible(true);
186 if (dialog.getStatus() == ServiceDialog.APPROVE) {
187 PrintRequestAttributeSet newas = dialog.getAttributes();
188 Class dstCategory = Destination.class;
189 Class fdCategory = Fidelity.class;
191 if (attributes.containsKey(dstCategory) &&
192 !newas.containsKey(dstCategory)) {
193 attributes.remove(dstCategory);
196 attributes.addAll(newas);
198 Fidelity fd = (Fidelity) attributes.get(fdCategory);
200 if (fd == Fidelity.FIDELITY_TRUE) {
201 removeUnsupportedAttributes(dialog.getPrintService(),
205 return dialog.getPrintService();
212 private Component getDescendantOfClass (Class c, Container cont) {
213 if (c == null || cont == null) {
216 Component[] children = (cont instanceof JMenu)
217 ? ((JMenu) cont).getMenuComponents()
218 : cont.getComponents();
219 for (int i = 0, n = children.length; i < n; i++) {
220 Component comp = children[i];
221 if (c.isInstance(comp)) {
224 comp = getDescendantOfClass(c, (Container) comp);
233 * Removes any attributes from the given AttributeSet that are unsupported by the given PrintService/DocFlavor
236 * @param ps the print service for which unsupported attributes will be determined
237 * @param flavor the document flavor; PDF in our case
238 * @param aset the set of attributes requested
240 private static void removeUnsupportedAttributes (PrintService ps,
243 AttributeSet asUnsupported = ps.getUnsupportedAttributes(flavor,
246 if (asUnsupported != null) {
247 Attribute[] usAttrs = asUnsupported.toArray();
249 for (Attribute usAttr : usAttrs) {
250 Class<? extends Attribute> category = usAttr.getCategory();
252 if (ps.isAttributeCategorySupported(category)) {
254 (Attribute) ps.getDefaultAttributeValue(category);
260 aset.remove(category);
264 aset.remove(category);