]> git.gag.com Git - debian/openrocket/blob - src/net/sf/openrocket/gui/print/PrintServiceDialog.java
DGP - Partial workaround for systems with no print services; simplification of the...
[debian/openrocket] / src / net / sf / openrocket / gui / print / PrintServiceDialog.java
1 /*\r
2  * PrintServiceDialog.java\r
3  *\r
4  */\r
5 package net.sf.openrocket.gui.print;\r
6 \r
7 import net.miginfocom.swing.MigLayout;\r
8 \r
9 import javax.print.DocFlavor;\r
10 import javax.print.PrintService;\r
11 import javax.print.ServiceUIFactory;\r
12 import javax.print.attribute.HashPrintRequestAttributeSet;\r
13 import javax.print.attribute.PrintRequestAttribute;\r
14 import javax.print.attribute.PrintRequestAttributeSet;\r
15 import javax.print.attribute.standard.Destination;\r
16 import javax.print.attribute.standard.Media;\r
17 import javax.print.attribute.standard.MediaSizeName;\r
18 import javax.print.attribute.standard.MediaTray;\r
19 import javax.swing.AbstractAction;\r
20 import javax.swing.ActionMap;\r
21 import javax.swing.BorderFactory;\r
22 import javax.swing.InputMap;\r
23 import javax.swing.JButton;\r
24 import javax.swing.JComboBox;\r
25 import javax.swing.JDialog;\r
26 import javax.swing.JLabel;\r
27 import javax.swing.JPanel;\r
28 import javax.swing.JTabbedPane;\r
29 import javax.swing.KeyStroke;\r
30 import javax.swing.border.EmptyBorder;\r
31 import javax.swing.event.PopupMenuEvent;\r
32 import javax.swing.event.PopupMenuListener;\r
33 import java.awt.Container;\r
34 import java.awt.Dialog;\r
35 import java.awt.event.ActionEvent;\r
36 import java.awt.event.ActionListener;\r
37 import java.awt.event.ItemEvent;\r
38 import java.awt.event.ItemListener;\r
39 import java.awt.event.WindowAdapter;\r
40 import java.awt.event.WindowEvent;\r
41 import java.util.ArrayList;\r
42 import java.util.Iterator;\r
43 import java.util.Set;\r
44 import java.util.TreeSet;\r
45 \r
46 public class PrintServiceDialog extends JDialog implements ActionListener {\r
47 \r
48     public static final int APPROVE = 1;\r
49     private JButton btnCancel, btnPrint;\r
50     private boolean pdfFlavorSupported = true;\r
51     private PrintService services[];\r
52     private int defaultServiceIndex = -1;\r
53     private int status;\r
54     private PrintRequestAttributeSet asOriginal;\r
55     private HashPrintRequestAttributeSet asCurrent;\r
56     private PrintService psCurrent;\r
57     private DocFlavor docFlavor;\r
58     private GeneralPanel pnlGeneral;\r
59     private static final String GENERAL_TAB_TITLE = "General";\r
60     private static final String PRINT_BUTTON_LABEL = "Print";\r
61     private static final String CANCEL_BUTTON_LABEL = "Cancel";\r
62 \r
63     private class MediaPanel extends JPanel\r
64             implements ItemListener {\r
65 \r
66         private static final String strTitle = "Media";\r
67         private static final String SOURCE = "Source:";\r
68         private static final String SIZE = "Size:";\r
69 \r
70         private JLabel lblSize, lblSource;\r
71         private JComboBox cbSize, cbSource;\r
72         private ArrayList<MediaSizeName> sizes;\r
73         private ArrayList sources;\r
74 \r
75         private String getMediaName(String s) {\r
76             String s1 = s.replace(' ', '-');\r
77             s1 = s1.replace('#', 'n');\r
78             return PaperSize.toDisplayable(s1);\r
79         }\r
80 \r
81         public void itemStateChanged(ItemEvent itemevent) {\r
82             Object obj = itemevent.getSource();\r
83             if (itemevent.getStateChange() == ItemEvent.SELECTED) {\r
84                 if (obj == cbSize) {\r
85                     int i = cbSize.getSelectedIndex();\r
86                     if (i >= 0 && i < sizes.size()) {\r
87                         if (cbSource.getItemCount() > 1 && cbSource.getSelectedIndex() >= 1) {\r
88                             int k = cbSource.getSelectedIndex() - 1;\r
89                             MediaTray mediatray = (MediaTray) sources.get(k);\r
90                             asCurrent.add(new MediaWrapper(mediatray));\r
91                         }\r
92                         asCurrent.add(sizes.get(i));\r
93                     }\r
94                 }\r
95                 else if (obj == cbSource) {\r
96                     int j = cbSource.getSelectedIndex();\r
97                     if (j >= 1 && j < sources.size() + 1) {\r
98                         asCurrent.remove(MediaWrapper.class);\r
99                         asCurrent.add((MediaTray) sources.get(j - 1));\r
100                     }\r
101                     else if (j == 0) {\r
102                         asCurrent.remove(MediaWrapper.class);\r
103                         if (cbSize.getItemCount() > 0) {\r
104                             int l = cbSize.getSelectedIndex();\r
105                             asCurrent.add(sizes.get(l));\r
106                         }\r
107                     }\r
108                 }\r
109             }\r
110         }\r
111 \r
112 \r
113         public void updateInfo() {\r
114             boolean flag = false;\r
115             cbSize.removeItemListener(this);\r
116             cbSize.removeAllItems();\r
117             cbSource.removeItemListener(this);\r
118             cbSource.removeAllItems();\r
119             cbSource.addItem(getMediaName("auto-select"));\r
120             sizes.clear();\r
121             sources.clear();\r
122             if (psCurrent != null && psCurrent.isAttributeCategorySupported(Media.class)) {\r
123                 flag = true;\r
124                 Object obj = null;\r
125                 try {\r
126                     obj = psCurrent.getSupportedAttributeValues(Media.class, docFlavor, asCurrent);\r
127                 }\r
128                 catch (IllegalArgumentException iae) {\r
129                     pdfFlavorSupported = false;\r
130                     //dgp\r
131                 }\r
132                 if (obj instanceof Media[]) {\r
133                     Media amedia[] = (Media[]) obj;\r
134                     Set<SortableMediaSizeName> sizeSet = new TreeSet<SortableMediaSizeName>();\r
135 \r
136                     for (int i = 0; i < amedia.length; i++) {\r
137                         Media media = amedia[i];\r
138                         if (media instanceof MediaSizeName) {\r
139                             sizeSet.add(new SortableMediaSizeName((MediaSizeName) media));\r
140                         }\r
141                         else if (media instanceof MediaTray) {\r
142                             sources.add(media);\r
143                             cbSource.addItem(getMediaName(media.toString()));\r
144                         }\r
145                     }\r
146 \r
147                     //The set eliminates duplicates.\r
148                     for (Iterator<SortableMediaSizeName> mediaSizeNameIterator = sizeSet.iterator(); mediaSizeNameIterator\r
149                             .hasNext();) {\r
150                         SortableMediaSizeName media = mediaSizeNameIterator.next();\r
151 \r
152                         sizes.add(media.getMediaSizeName());\r
153                         cbSize.addItem(media.toString());\r
154                     }\r
155 \r
156                 }\r
157             }\r
158             boolean flag1 = flag && sizes.size() > 0;\r
159             lblSize.setEnabled(flag1);\r
160             cbSize.setEnabled(flag1);\r
161             cbSource.setEnabled(false);\r
162             lblSource.setEnabled(false);\r
163             if (flag && psCurrent != null) {\r
164                 Media media = (Media) asCurrent.get(Media.class);\r
165                 boolean attributeValueSupported = false;\r
166                 try {\r
167                     attributeValueSupported = media == null ? false : psCurrent.isAttributeValueSupported(media,\r
168                                                                                                           docFlavor,\r
169                                                                                                           asCurrent);\r
170                 }\r
171                 catch (IllegalArgumentException iae) {\r
172                     pdfFlavorSupported = false;\r
173                 }\r
174                 if (media == null || !attributeValueSupported) {\r
175                     media = (Media) psCurrent.getDefaultAttributeValue(Media.class);\r
176                     if (media == null && sizes.size() > 0) {\r
177                         media = sizes.get(0);\r
178                     }\r
179                     if (media != null) {\r
180                         asCurrent.add(media);\r
181                     }\r
182                 }\r
183                 if (media != null) {\r
184                     if (media instanceof MediaSizeName) {\r
185                         MediaSizeName mediasizename = (MediaSizeName) media;\r
186                         cbSize.setSelectedIndex(sizes.indexOf(mediasizename));\r
187                     }\r
188                     else if (media instanceof MediaTray) {\r
189                         MediaTray mediatray = (MediaTray) media;\r
190                         cbSource.setSelectedIndex(sources.indexOf(mediatray) + 1);\r
191                     }\r
192                 }\r
193                 else {\r
194                     cbSize.setSelectedIndex(sizes.size() <= 0 ? -1 : 0);\r
195                     cbSource.setSelectedIndex(0);\r
196                 }\r
197                 int j = cbSize.getSelectedIndex();\r
198                 if (j >= 0 && j < sizes.size()) {\r
199                     asCurrent.add(sizes.get(j));\r
200                 }\r
201                 j = cbSource.getSelectedIndex();\r
202                 if (j >= 1 && j < sources.size() + 1) {\r
203                     asCurrent.add((MediaTray) sources.get(j - 1));\r
204                 }\r
205             }\r
206             cbSize.addItemListener(this);\r
207             cbSource.addItemListener(this);\r
208         }\r
209 \r
210         public MediaPanel() {\r
211             super(new MigLayout("fill, gap rel unrel"));\r
212             sizes = new ArrayList<MediaSizeName>();\r
213             sources = new ArrayList();\r
214             setBorder(BorderFactory.createTitledBorder(strTitle));\r
215             cbSize = new JComboBox();\r
216             cbSource = new JComboBox();\r
217             lblSize = new JLabel(SIZE, 11);\r
218             lblSize.setDisplayedMnemonic(PrintServiceDialog.getMnemonic(SIZE));\r
219             lblSize.setLabelFor(cbSize);\r
220             add(lblSize);\r
221             add(cbSize, "wrap");\r
222             lblSource = new JLabel(SOURCE, 11);\r
223             lblSource.setDisplayedMnemonic(PrintServiceDialog.getMnemonic(SOURCE));\r
224             lblSource.setLabelFor(cbSource);\r
225             add(lblSource);\r
226             add(cbSource);\r
227         }\r
228 \r
229         class SortableMediaSizeName implements Comparable {\r
230             MediaSizeName delegate;\r
231 \r
232             String displayableName;\r
233 \r
234             SortableMediaSizeName(MediaSizeName msn) {\r
235                 delegate = msn;\r
236                 displayableName = getMediaName(delegate.toString());\r
237                 if (displayableName == null) {\r
238                     displayableName = delegate.toString();\r
239                 }\r
240             }\r
241 \r
242             /**\r
243              * Returns a string value corresponding to this enumeration value.\r
244              */\r
245             @Override\r
246             public String toString() {\r
247                 return displayableName;\r
248             }\r
249 \r
250             @Override\r
251             public int compareTo(final Object o) {\r
252                 String name = displayableName;\r
253                 if (name != null) {\r
254                     return name.compareTo(o.toString());\r
255                 }\r
256                 return 1;\r
257             }\r
258 \r
259             @Override\r
260             public boolean equals(final Object o) {\r
261                 if (this == o) {\r
262                     return true;\r
263                 }\r
264                 if (o == null || getClass() != o.getClass()) {\r
265                     return false;\r
266                 }\r
267 \r
268                 final SortableMediaSizeName that = (SortableMediaSizeName) o;\r
269 \r
270                 return displayableName.equals(that.displayableName);\r
271             }\r
272 \r
273             @Override\r
274             public int hashCode() {\r
275                 return displayableName.hashCode();\r
276             }\r
277 \r
278             MediaSizeName getMediaSizeName() {\r
279                 return delegate;\r
280             }\r
281         }\r
282     }\r
283 \r
284     private class PrintServicePanel extends JPanel\r
285             implements ActionListener, ItemListener, PopupMenuListener {\r
286 \r
287         private final String strTitle = "Print Service";\r
288         private JButton btnProperties;\r
289         private JComboBox cbName;\r
290         private ServiceUIFactory uiFactory;\r
291         private boolean changedService;\r
292 \r
293         public PrintServicePanel() {\r
294             super(new MigLayout("fill, gap rel unrel"));\r
295             changedService = false;\r
296             if (psCurrent != null) {\r
297                 uiFactory = psCurrent.getServiceUIFactory();\r
298             }\r
299             setBorder(BorderFactory.createTitledBorder(strTitle));\r
300             String as[] = new String[services.length];\r
301             for (int i = 0; i < as.length; i++) {\r
302                 as[i] = services[i].getName();\r
303             }\r
304 \r
305             cbName = new JComboBox(as);\r
306             if (defaultServiceIndex != -1 && defaultServiceIndex < services.length) {\r
307                 cbName.setSelectedIndex(defaultServiceIndex);\r
308             }\r
309             cbName.addItemListener(this);\r
310             cbName.addPopupMenuListener(this);\r
311             JLabel jlabel = new JLabel(("Name:"), 11);\r
312             jlabel.setDisplayedMnemonic(PrintServiceDialog.getMnemonic("Name"));\r
313             jlabel.setLabelFor(cbName);\r
314             add(jlabel);\r
315             add(cbName);\r
316             btnProperties = PrintServiceDialog.createButton("Properties...", this);\r
317             add(btnProperties, "wrap");\r
318         }\r
319 \r
320         public void actionPerformed(ActionEvent actionevent) {\r
321             Object obj = actionevent.getSource();\r
322             if (obj == btnProperties && uiFactory != null) {\r
323                 JDialog jdialog = (JDialog) uiFactory.getUI(ServiceUIFactory.MAIN_UIROLE, "javax.swing.JDialog");\r
324                 if (jdialog != null) {\r
325                     jdialog.show();\r
326                 }\r
327                 else {\r
328                     btnProperties.setEnabled(false);\r
329                 }\r
330             }\r
331         }\r
332 \r
333         /**\r
334          * {@inheritDoc}\r
335          *\r
336          * @param itemevent  the event that indicates what changed\r
337          */\r
338         @Override\r
339         public void itemStateChanged(ItemEvent itemevent) {\r
340             if (itemevent.getStateChange() == ItemEvent.SELECTED) {\r
341                 int i = cbName.getSelectedIndex();\r
342                 if (services != null && i >= 0 && i < services.length && !services[i].equals(psCurrent)) {\r
343                     psCurrent = services[i];\r
344                     uiFactory = psCurrent.getServiceUIFactory();\r
345                     changedService = true;\r
346                     if (asOriginal != null) {\r
347                         Destination destination = (Destination) asOriginal.get(\r
348                                 Destination.class);\r
349                         if ((destination != null) && psCurrent.isAttributeCategorySupported(\r
350                                 Destination.class)) {\r
351                             asCurrent.add(destination);\r
352                         }\r
353                         else {\r
354                             asCurrent.remove(Destination.class);\r
355                         }\r
356                     }\r
357                 }\r
358             }\r
359         }\r
360 \r
361         /**\r
362          * {@inheritDoc}\r
363          *\r
364          * @param popupmenuevent\r
365          */\r
366         @Override\r
367         public void popupMenuWillBecomeVisible(PopupMenuEvent popupmenuevent) {\r
368             changedService = false;\r
369         }\r
370 \r
371         /**\r
372          * {@inheritDoc}\r
373          *\r
374          * @param popupmenuevent\r
375          */\r
376         @Override\r
377         public void popupMenuWillBecomeInvisible(PopupMenuEvent popupmenuevent) {\r
378             if (changedService) {\r
379                 changedService = false;\r
380                 updatePanels();\r
381             }\r
382         }\r
383 \r
384         /**\r
385          * {@inheritDoc}\r
386          *\r
387          * @param popupmenuevent\r
388          */\r
389         @Override\r
390         public void popupMenuCanceled(PopupMenuEvent popupmenuevent) {\r
391         }\r
392 \r
393         /**\r
394          * Modify the enablement of the properties button.\r
395          */\r
396         public void updateInfo() {\r
397             btnProperties.setEnabled(uiFactory != null);\r
398         }\r
399 \r
400     }\r
401 \r
402     /**\r
403      * The panel for general print services info.\r
404      */\r
405     private class GeneralPanel extends JPanel {\r
406 \r
407         private PrintServicePanel pnlPrintService;\r
408         private MediaPanel pnlMedia;\r
409 \r
410         public GeneralPanel() {\r
411             super(new MigLayout("fill, gap rel unrel"));\r
412             pnlPrintService = new PrintServicePanel();\r
413             add(pnlPrintService, "wrap");\r
414             pnlMedia = new MediaPanel();\r
415             add(pnlMedia, "wrap");\r
416         }\r
417 \r
418         public void updateInfo() {\r
419             pnlPrintService.updateInfo();\r
420             pnlMedia.updateInfo();\r
421         }\r
422     }\r
423 \r
424     /**\r
425      * Constructor.\r
426      *\r
427      * @param x the <i>x</i>-coordinate of the new location's\r
428      *          top-left corner in the parent's coordinate space\r
429      * @param y the <i>y</i>-coordinate of the new location's\r
430      *          top-left corner in the parent's coordinate space\r
431      * @param aPrintService  the array of installed print services\r
432      * @param defaultServiceIndex  the default service index (index into aPrintService)\r
433      * @param docflavor  the document flavor (i.e. PDF)\r
434      * @param attributeSet  the set of required attributes\r
435      * @param dialog  the parent\r
436      * @param additional  other panels to add in tabs\r
437      */\r
438     public PrintServiceDialog(int x, int y, PrintService[] aPrintService,\r
439                               int defaultServiceIndex, DocFlavor docflavor, PrintRequestAttributeSet attributeSet,\r
440                               Dialog dialog, JPanel... additional) {\r
441         super(dialog, PRINT_BUTTON_LABEL, true);\r
442         setLayout(new MigLayout("fill, gap rel unrel"));\r
443         services = aPrintService;\r
444         this.defaultServiceIndex = defaultServiceIndex;\r
445         asOriginal = attributeSet;\r
446         asCurrent = new HashPrintRequestAttributeSet(attributeSet);\r
447 \r
448         if (services != null && defaultServiceIndex < services.length && defaultServiceIndex >= 0) {\r
449             psCurrent = services[defaultServiceIndex];\r
450         }\r
451         docFlavor = docflavor;\r
452         Container container = getContentPane();\r
453         container.setLayout(new MigLayout("fill, gap rel unrel"));\r
454 //        container.setLayout(new BorderLayout());\r
455         final JTabbedPane tpTabs = new JTabbedPane();\r
456         tpTabs.setBorder(new EmptyBorder(5, 5, 5, 5));\r
457 \r
458         if (additional != null) {\r
459             for (JPanel anAdditional : additional) {\r
460                 tpTabs.add(anAdditional, anAdditional.getName(), 0);\r
461             }\r
462         }\r
463         if (psCurrent != null) {\r
464             pnlGeneral = new GeneralPanel();\r
465             tpTabs.add(GENERAL_TAB_TITLE, pnlGeneral);\r
466         }\r
467 \r
468         container.add(tpTabs, "growx");\r
469         updatePanels();\r
470 \r
471         JPanel jpanel = new JPanel(new MigLayout());\r
472         btnPrint = createExitButton(PRINT_BUTTON_LABEL, this);\r
473         jpanel.add(btnPrint, "x 300");\r
474         getRootPane().setDefaultButton(btnPrint);\r
475         btnPrint.setEnabled(pdfFlavorSupported && psCurrent != null);\r
476 \r
477         btnCancel = createExitButton(CANCEL_BUTTON_LABEL, this);\r
478         handleEscKey(btnCancel);\r
479         jpanel.add(btnCancel, "x 380");\r
480         container.add(jpanel, "South");\r
481         addWindowListener(new WindowAdapter() {\r
482             public void windowClosing(WindowEvent windowevent) {\r
483                 dispose(2);\r
484             }\r
485         }\r
486         );\r
487         setResizable(false);\r
488         setLocation(x, y);\r
489         pack();\r
490     }\r
491 \r
492     private void handleEscKey(JButton jbutton) {\r
493         AbstractAction abstractaction = new AbstractAction() {\r
494 \r
495             public void actionPerformed(ActionEvent actionevent) {\r
496                 dispose(2);\r
497             }\r
498 \r
499         };\r
500         KeyStroke keystroke = KeyStroke.getKeyStroke('\033', false);\r
501         InputMap inputmap = jbutton.getInputMap(2);\r
502         ActionMap actionmap = jbutton.getActionMap();\r
503         if (inputmap != null && actionmap != null) {\r
504             inputmap.put(keystroke, "cancel");\r
505             actionmap.put("cancel", abstractaction);\r
506         }\r
507     }\r
508 \r
509     public int getStatus() {\r
510         return status;\r
511     }\r
512 \r
513     public PrintRequestAttributeSet getAttributes() {\r
514         if (status == 1) {\r
515             return asCurrent;\r
516         }\r
517         else {\r
518             return asOriginal;\r
519         }\r
520     }\r
521 \r
522     public PrintService getPrintService() {\r
523         if (status == 1) {\r
524             return psCurrent;\r
525         }\r
526         else {\r
527             return null;\r
528         }\r
529     }\r
530 \r
531     public void dispose(int i) {\r
532         status = i;\r
533         super.dispose();\r
534     }\r
535 \r
536     public void actionPerformed(ActionEvent actionevent) {\r
537         Object obj = actionevent.getSource();\r
538         boolean flag = false;\r
539         if (obj == btnPrint) {\r
540             flag = true;\r
541             if (pnlGeneral != null) {\r
542                 asCurrent.remove(Destination.class);\r
543             }\r
544         }\r
545         dispose(flag ? 1 : 2);\r
546     }\r
547 \r
548 \r
549     private void updatePanels() {\r
550         if (pnlGeneral != null) {\r
551             pnlGeneral.updateInfo();\r
552         }\r
553     }\r
554 \r
555     private static char getMnemonic(String s) {\r
556         if (s != null && s.length() > 0) {\r
557             return s.charAt(0);\r
558         }\r
559         else {\r
560             return '\0';\r
561         }\r
562     }\r
563 \r
564     private static JButton createButton(String s, ActionListener actionlistener) {\r
565         JButton jbutton = new JButton(s);\r
566         jbutton.setMnemonic(getMnemonic(s));\r
567         jbutton.addActionListener(actionlistener);\r
568         return jbutton;\r
569     }\r
570 \r
571     private static JButton createExitButton(String s, ActionListener actionlistener) {\r
572         JButton jbutton = new JButton(s);\r
573         jbutton.addActionListener(actionlistener);\r
574         jbutton.getAccessibleContext().setAccessibleDescription(s);\r
575         return jbutton;\r
576     }\r
577 \r
578     static class MediaWrapper\r
579             implements PrintRequestAttribute {\r
580 \r
581         private Media media;\r
582 \r
583         MediaWrapper(Media theMedia) {\r
584             media = theMedia;\r
585         }\r
586 \r
587         Media getMedia() {\r
588             return media;\r
589         }\r
590 \r
591         public final Class getCategory() {\r
592             return this.getClass();\r
593         }\r
594 \r
595         public final String getName() {\r
596             return "mw";\r
597         }\r
598 \r
599         public String toString() {\r
600             return media.toString();\r
601         }\r
602 \r
603         public int hashCode() {\r
604             return media.hashCode();\r
605         }\r
606 \r
607     }\r
608 \r
609 }\r