Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/print/ServiceDialog.java
41153 views
1
/*
2
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.print;
27
28
import java.awt.BorderLayout;
29
import java.awt.Color;
30
import java.awt.Component;
31
import java.awt.Container;
32
import java.awt.Dialog;
33
import java.awt.FlowLayout;
34
import java.awt.Frame;
35
import java.awt.GraphicsConfiguration;
36
import java.awt.GridBagLayout;
37
import java.awt.GridBagConstraints;
38
import java.awt.GridLayout;
39
import java.awt.Insets;
40
import java.awt.Toolkit;
41
import java.awt.Window;
42
import java.awt.event.ActionEvent;
43
import java.awt.event.ActionListener;
44
import java.awt.event.FocusEvent;
45
import java.awt.event.FocusListener;
46
import java.awt.event.ItemEvent;
47
import java.awt.event.ItemListener;
48
import java.awt.event.WindowEvent;
49
import java.awt.event.WindowAdapter;
50
import java.awt.print.PrinterJob;
51
import java.io.File;
52
import java.io.FilePermission;
53
import java.io.IOException;
54
import java.net.URI;
55
import java.net.URL;
56
import java.text.DecimalFormat;
57
import java.util.Locale;
58
import java.util.ResourceBundle;
59
import java.util.Vector;
60
import javax.print.*;
61
import javax.print.attribute.*;
62
import javax.print.attribute.standard.*;
63
import javax.swing.*;
64
import javax.swing.border.Border;
65
import javax.swing.border.EmptyBorder;
66
import javax.swing.border.TitledBorder;
67
import javax.swing.event.ChangeEvent;
68
import javax.swing.event.ChangeListener;
69
import javax.swing.event.DocumentEvent;
70
import javax.swing.event.DocumentListener;
71
import javax.swing.event.PopupMenuEvent;
72
import javax.swing.event.PopupMenuListener;
73
import javax.swing.text.NumberFormatter;
74
import sun.print.SunPageSelection;
75
import java.awt.event.KeyEvent;
76
import java.net.URISyntaxException;
77
import java.lang.reflect.Field;
78
import java.net.MalformedURLException;
79
80
/**
81
* A class which implements a cross-platform print dialog.
82
*
83
* @author Chris Campbell
84
*/
85
@SuppressWarnings("serial") // Superclass is not serializable across versions
86
public class ServiceDialog extends JDialog implements ActionListener {
87
88
/**
89
* Waiting print status (user response pending).
90
*/
91
public static final int WAITING = 0;
92
93
/**
94
* Approve print status (user activated "Print" or "OK").
95
*/
96
public static final int APPROVE = 1;
97
98
/**
99
* Cancel print status (user activated "Cancel");
100
*/
101
public static final int CANCEL = 2;
102
103
private static final String strBundle = "sun.print.resources.serviceui";
104
private static final Insets panelInsets = new Insets(6, 6, 6, 6);
105
private static final Insets compInsets = new Insets(3, 6, 3, 6);
106
107
private static ResourceBundle messageRB;
108
private JTabbedPane tpTabs;
109
private JButton btnCancel, btnApprove;
110
private PrintService[] services;
111
private int defaultServiceIndex;
112
private PrintRequestAttributeSet asOriginal;
113
private HashPrintRequestAttributeSet asCurrent;
114
private PrintService psCurrent;
115
private DocFlavor docFlavor;
116
private int status;
117
118
private ValidatingFileChooser jfc;
119
120
private GeneralPanel pnlGeneral;
121
private PageSetupPanel pnlPageSetup;
122
private AppearancePanel pnlAppearance;
123
124
private boolean isAWT = false;
125
static {
126
initResource();
127
}
128
129
130
/**
131
* Constructor for the "standard" print dialog (containing all relevant
132
* tabs)
133
*/
134
public ServiceDialog(GraphicsConfiguration gc,
135
int x, int y,
136
PrintService[] services,
137
int defaultServiceIndex,
138
DocFlavor flavor,
139
PrintRequestAttributeSet attributes,
140
Window window)
141
{
142
super(window, getMsg("dialog.printtitle"), Dialog.DEFAULT_MODALITY_TYPE, gc);
143
initPrintDialog(x, y, services, defaultServiceIndex,
144
flavor, attributes);
145
}
146
147
/**
148
* Initialize print dialog.
149
*/
150
void initPrintDialog(int x, int y,
151
PrintService[] services,
152
int defaultServiceIndex,
153
DocFlavor flavor,
154
PrintRequestAttributeSet attributes)
155
{
156
this.services = services;
157
this.defaultServiceIndex = defaultServiceIndex;
158
this.asOriginal = attributes;
159
this.asCurrent = new HashPrintRequestAttributeSet(attributes);
160
this.psCurrent = services[defaultServiceIndex];
161
this.docFlavor = flavor;
162
SunPageSelection pages =
163
(SunPageSelection)attributes.get(SunPageSelection.class);
164
if (pages != null) {
165
isAWT = true;
166
}
167
168
if (attributes.get(DialogOwner.class) != null) {
169
DialogOwner owner = (DialogOwner)attributes.get(DialogOwner.class);
170
/* When the ServiceDialog is constructed the caller of the
171
* constructor checks for this attribute and if it specifies a
172
* window then it will use that in the constructor instead of
173
* inferring one from keyboard focus.
174
* In this case the owner of the dialog is the same as that
175
* specified in the attribute and we do not need to set the
176
* on top property
177
*/
178
if ((getOwner() == null) || (owner.getOwner() != getOwner())) {
179
try {
180
setAlwaysOnTop(true);
181
} catch (SecurityException e) {
182
}
183
}
184
}
185
Container c = getContentPane();
186
c.setLayout(new BorderLayout());
187
188
tpTabs = new JTabbedPane();
189
tpTabs.setBorder(new EmptyBorder(5, 5, 5, 5));
190
191
String gkey = getMsg("tab.general");
192
int gmnemonic = getVKMnemonic("tab.general");
193
pnlGeneral = new GeneralPanel();
194
tpTabs.add(gkey, pnlGeneral);
195
tpTabs.setMnemonicAt(0, gmnemonic);
196
197
String pkey = getMsg("tab.pagesetup");
198
int pmnemonic = getVKMnemonic("tab.pagesetup");
199
pnlPageSetup = new PageSetupPanel();
200
tpTabs.add(pkey, pnlPageSetup);
201
tpTabs.setMnemonicAt(1, pmnemonic);
202
203
String akey = getMsg("tab.appearance");
204
int amnemonic = getVKMnemonic("tab.appearance");
205
pnlAppearance = new AppearancePanel();
206
tpTabs.add(akey, pnlAppearance);
207
tpTabs.setMnemonicAt(2, amnemonic);
208
209
c.add(tpTabs, BorderLayout.CENTER);
210
211
updatePanels();
212
213
JPanel pnlSouth = new JPanel(new FlowLayout(FlowLayout.TRAILING));
214
btnApprove = createExitButton("button.print", this);
215
pnlSouth.add(btnApprove);
216
getRootPane().setDefaultButton(btnApprove);
217
btnCancel = createExitButton("button.cancel", this);
218
handleEscKey(btnCancel);
219
pnlSouth.add(btnCancel);
220
c.add(pnlSouth, BorderLayout.SOUTH);
221
222
addWindowListener(new WindowAdapter() {
223
public void windowClosing(WindowEvent event) {
224
dispose(CANCEL);
225
}
226
});
227
228
getAccessibleContext().setAccessibleDescription(getMsg("dialog.printtitle"));
229
setResizable(false);
230
setLocation(x, y);
231
pack();
232
}
233
234
/**
235
* Constructor for the solitary "page setup" dialog
236
*/
237
public ServiceDialog(GraphicsConfiguration gc,
238
int x, int y,
239
PrintService ps,
240
DocFlavor flavor,
241
PrintRequestAttributeSet attributes,
242
Window window)
243
{
244
super(window, getMsg("dialog.pstitle"), Dialog.DEFAULT_MODALITY_TYPE, gc);
245
initPageDialog(x, y, ps, flavor, attributes);
246
}
247
248
/**
249
* Initialize "page setup" dialog
250
*/
251
void initPageDialog(int x, int y,
252
PrintService ps,
253
DocFlavor flavor,
254
PrintRequestAttributeSet attributes)
255
{
256
this.psCurrent = ps;
257
this.docFlavor = flavor;
258
this.asOriginal = attributes;
259
this.asCurrent = new HashPrintRequestAttributeSet(attributes);
260
261
if (attributes.get(DialogOwner.class) != null) {
262
/* See comments in same block in initPrintDialog */
263
DialogOwner owner = (DialogOwner)attributes.get(DialogOwner.class);
264
if ((getOwner() == null) || (owner.getOwner() != getOwner())) {
265
try {
266
setAlwaysOnTop(true);
267
} catch (SecurityException e) {
268
}
269
}
270
}
271
272
Container c = getContentPane();
273
c.setLayout(new BorderLayout());
274
275
pnlPageSetup = new PageSetupPanel();
276
c.add(pnlPageSetup, BorderLayout.CENTER);
277
278
pnlPageSetup.updateInfo();
279
280
JPanel pnlSouth = new JPanel(new FlowLayout(FlowLayout.TRAILING));
281
btnApprove = createExitButton("button.ok", this);
282
pnlSouth.add(btnApprove);
283
getRootPane().setDefaultButton(btnApprove);
284
btnCancel = createExitButton("button.cancel", this);
285
handleEscKey(btnCancel);
286
pnlSouth.add(btnCancel);
287
c.add(pnlSouth, BorderLayout.SOUTH);
288
289
addWindowListener(new WindowAdapter() {
290
public void windowClosing(WindowEvent event) {
291
dispose(CANCEL);
292
}
293
});
294
295
getAccessibleContext().setAccessibleDescription(getMsg("dialog.pstitle"));
296
setResizable(false);
297
setLocation(x, y);
298
pack();
299
}
300
301
/**
302
* Performs Cancel when Esc key is pressed.
303
*/
304
private void handleEscKey(JButton btnCancel) {
305
@SuppressWarnings("serial") // anonymous class
306
Action cancelKeyAction = new AbstractAction() {
307
public void actionPerformed(ActionEvent e) {
308
dispose(CANCEL);
309
}
310
};
311
KeyStroke cancelKeyStroke =
312
KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE, 0);
313
InputMap inputMap =
314
btnCancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
315
ActionMap actionMap = btnCancel.getActionMap();
316
317
if (inputMap != null && actionMap != null) {
318
inputMap.put(cancelKeyStroke, "cancel");
319
actionMap.put("cancel", cancelKeyAction);
320
}
321
}
322
323
324
/**
325
* Returns the current status of the dialog (whether the user has selected
326
* the "Print" or "Cancel" button)
327
*/
328
public int getStatus() {
329
return status;
330
}
331
332
/**
333
* Returns an AttributeSet based on whether or not the user cancelled the
334
* dialog. If the user selected "Print" we return their new selections,
335
* otherwise we return the attributes that were passed in initially.
336
*/
337
public PrintRequestAttributeSet getAttributes() {
338
if (status == APPROVE) {
339
return asCurrent;
340
} else {
341
return asOriginal;
342
}
343
}
344
345
/**
346
* Returns a PrintService based on whether or not the user cancelled the
347
* dialog. If the user selected "Print" we return the user's selection
348
* for the PrintService, otherwise we return null.
349
*/
350
public PrintService getPrintService() {
351
if (status == APPROVE) {
352
return psCurrent;
353
} else {
354
return null;
355
}
356
}
357
358
/**
359
* Sets the current status flag for the dialog and disposes it (thus
360
* returning control of the parent frame back to the user)
361
*/
362
public void dispose(int status) {
363
this.status = status;
364
365
super.dispose();
366
}
367
368
public void actionPerformed(ActionEvent e) {
369
Object source = e.getSource();
370
boolean approved = false;
371
372
if (source == btnApprove) {
373
approved = true;
374
375
if (pnlGeneral != null) {
376
if (pnlGeneral.isPrintToFileRequested()) {
377
approved = showFileChooser();
378
} else {
379
asCurrent.remove(Destination.class);
380
}
381
}
382
}
383
384
dispose(approved ? APPROVE : CANCEL);
385
}
386
387
/**
388
* Displays a JFileChooser that allows the user to select the destination
389
* for "Print To File"
390
*/
391
private boolean showFileChooser() {
392
Class<Destination> dstCategory = Destination.class;
393
394
Destination dst = (Destination)asCurrent.get(dstCategory);
395
if (dst == null) {
396
dst = (Destination)asOriginal.get(dstCategory);
397
if (dst == null) {
398
dst = (Destination)psCurrent.getDefaultAttributeValue(dstCategory);
399
// "dst" should not be null. The following code
400
// is only added to safeguard against a possible
401
// buggy implementation of a PrintService having a
402
// null default Destination.
403
if (dst == null) {
404
try {
405
dst = new Destination(new URI("file:out.prn"));
406
} catch (URISyntaxException e) {
407
}
408
}
409
}
410
}
411
412
File fileDest;
413
if (dst != null) {
414
try {
415
fileDest = new File(dst.getURI());
416
} catch (Exception e) {
417
// all manner of runtime exceptions possible
418
fileDest = new File("out.prn");
419
}
420
} else {
421
fileDest = new File("out.prn");
422
}
423
424
ValidatingFileChooser jfc = new ValidatingFileChooser();
425
jfc.setApproveButtonText(getMsg("button.ok"));
426
jfc.setDialogTitle(getMsg("dialog.printtofile"));
427
jfc.setDialogType(JFileChooser.SAVE_DIALOG);
428
jfc.setSelectedFile(fileDest);
429
430
int returnVal = jfc.showDialog(this, null);
431
if (returnVal == JFileChooser.APPROVE_OPTION) {
432
fileDest = jfc.getSelectedFile();
433
434
try {
435
asCurrent.add(new Destination(fileDest.toURI()));
436
} catch (Exception e) {
437
asCurrent.remove(dstCategory);
438
}
439
} else {
440
asCurrent.remove(dstCategory);
441
}
442
443
return (returnVal == JFileChooser.APPROVE_OPTION);
444
}
445
446
/**
447
* Updates each of the top level panels
448
*/
449
private void updatePanels() {
450
pnlGeneral.updateInfo();
451
pnlPageSetup.updateInfo();
452
pnlAppearance.updateInfo();
453
}
454
455
/**
456
* Initialize ResourceBundle
457
*/
458
@SuppressWarnings("removal")
459
public static void initResource() {
460
java.security.AccessController.doPrivileged(
461
new java.security.PrivilegedAction<Object>() {
462
public Object run() {
463
try {
464
messageRB = ResourceBundle.getBundle(strBundle);
465
return null;
466
} catch (java.util.MissingResourceException e) {
467
throw new Error("Fatal: Resource for ServiceUI " +
468
"is missing");
469
}
470
}
471
}
472
);
473
}
474
475
/**
476
* Returns message string from resource
477
*/
478
public static String getMsg(String key) {
479
try {
480
return removeMnemonics(messageRB.getString(key));
481
} catch (java.util.MissingResourceException e) {
482
throw new Error("Fatal: Resource for ServiceUI is broken; " +
483
"there is no " + key + " key in resource");
484
}
485
}
486
487
private static String removeMnemonics(String s) {
488
int i = s.indexOf('&');
489
int len = s.length();
490
if (i < 0 || i == (len - 1)) {
491
return s;
492
}
493
int j = s.indexOf('&', i+1);
494
if (j == i+1) {
495
if (j+1 == len) {
496
return s.substring(0, i+1); // string ends with &&
497
} else {
498
return s.substring(0, i+1) + removeMnemonics(s.substring(j+1));
499
}
500
}
501
// ok first & not double &&
502
if (i == 0) {
503
return removeMnemonics(s.substring(1));
504
} else {
505
return (s.substring(0, i) + removeMnemonics(s.substring(i+1)));
506
}
507
}
508
509
510
/**
511
* Returns mnemonic character from resource
512
*/
513
private static char getMnemonic(String key) {
514
String str = messageRB.getString(key).replace("&&", "");
515
int index = str.indexOf('&');
516
if (0 <= index && index < str.length() - 1) {
517
char c = str.charAt(index + 1);
518
return Character.toUpperCase(c);
519
} else {
520
return (char)0;
521
}
522
}
523
524
/**
525
* Returns the mnemonic as a KeyEvent.VK constant from the resource.
526
*/
527
static Class<?> _keyEventClazz = null;
528
private static int getVKMnemonic(String key) {
529
String s = String.valueOf(getMnemonic(key));
530
if ( s == null || s.length() != 1) {
531
return 0;
532
}
533
String vkString = "VK_" + s.toUpperCase();
534
535
try {
536
if (_keyEventClazz == null) {
537
_keyEventClazz= Class.forName("java.awt.event.KeyEvent",
538
true, (ServiceDialog.class).getClassLoader());
539
}
540
Field field = _keyEventClazz.getDeclaredField(vkString);
541
int value = field.getInt(null);
542
return value;
543
} catch (Exception e) {
544
}
545
return 0;
546
}
547
548
/**
549
* Returns URL for image resource
550
*/
551
private static URL getImageResource(final String key) {
552
@SuppressWarnings("removal")
553
URL url = java.security.AccessController.doPrivileged(
554
new java.security.PrivilegedAction<URL>() {
555
public URL run() {
556
URL url = ServiceDialog.class.getResource(
557
"resources/" + key);
558
return url;
559
}
560
});
561
562
if (url == null) {
563
throw new Error("Fatal: Resource for ServiceUI is broken; " +
564
"there is no " + key + " key in resource");
565
}
566
567
return url;
568
}
569
570
/**
571
* Creates a new JButton and sets its text, mnemonic, and ActionListener
572
*/
573
private static JButton createButton(String key, ActionListener al) {
574
JButton btn = new JButton(getMsg(key));
575
btn.setMnemonic(getMnemonic(key));
576
btn.addActionListener(al);
577
578
return btn;
579
}
580
581
/**
582
* Creates a new JButton and sets its text, and ActionListener
583
*/
584
private static JButton createExitButton(String key, ActionListener al) {
585
String str = getMsg(key);
586
JButton btn = new JButton(str);
587
btn.addActionListener(al);
588
btn.getAccessibleContext().setAccessibleDescription(str);
589
return btn;
590
}
591
592
/**
593
* Creates a new JCheckBox and sets its text, mnemonic, and ActionListener
594
*/
595
private static JCheckBox createCheckBox(String key, ActionListener al) {
596
JCheckBox cb = new JCheckBox(getMsg(key));
597
cb.setMnemonic(getMnemonic(key));
598
cb.addActionListener(al);
599
600
return cb;
601
}
602
603
/**
604
* Creates a new JRadioButton and sets its text, mnemonic,
605
* and ActionListener
606
*/
607
private static JRadioButton createRadioButton(String key,
608
ActionListener al)
609
{
610
JRadioButton rb = new JRadioButton(getMsg(key));
611
rb.setMnemonic(getMnemonic(key));
612
rb.addActionListener(al);
613
614
return rb;
615
}
616
617
/**
618
* Creates a pop-up dialog for "no print service"
619
*/
620
public static void showNoPrintService(GraphicsConfiguration gc)
621
{
622
Frame dlgFrame = new Frame(gc);
623
JOptionPane.showMessageDialog(dlgFrame,
624
getMsg("dialog.noprintermsg"));
625
dlgFrame.dispose();
626
}
627
628
/**
629
* Sets the constraints for the GridBagLayout and adds the Component
630
* to the given Container
631
*/
632
private static void addToGB(Component comp, Container cont,
633
GridBagLayout gridbag,
634
GridBagConstraints constraints)
635
{
636
gridbag.setConstraints(comp, constraints);
637
cont.add(comp);
638
}
639
640
/**
641
* Adds the AbstractButton to both the given ButtonGroup and Container
642
*/
643
private static void addToBG(AbstractButton button, Container cont,
644
ButtonGroup bg)
645
{
646
bg.add(button);
647
cont.add(button);
648
}
649
650
651
652
653
/**
654
* The "General" tab. Includes the controls for PrintService,
655
* PageRange, and Copies/Collate.
656
*/
657
@SuppressWarnings("serial") // Superclass is not serializable across versions
658
private class GeneralPanel extends JPanel {
659
660
private PrintServicePanel pnlPrintService;
661
private PrintRangePanel pnlPrintRange;
662
private CopiesPanel pnlCopies;
663
664
public GeneralPanel() {
665
super();
666
667
GridBagLayout gridbag = new GridBagLayout();
668
GridBagConstraints c = new GridBagConstraints();
669
670
setLayout(gridbag);
671
672
c.fill = GridBagConstraints.BOTH;
673
c.insets = panelInsets;
674
c.weightx = 1.0;
675
c.weighty = 1.0;
676
677
c.gridwidth = GridBagConstraints.REMAINDER;
678
pnlPrintService = new PrintServicePanel();
679
addToGB(pnlPrintService, this, gridbag, c);
680
681
c.gridwidth = GridBagConstraints.RELATIVE;
682
pnlPrintRange = new PrintRangePanel();
683
addToGB(pnlPrintRange, this, gridbag, c);
684
685
c.gridwidth = GridBagConstraints.REMAINDER;
686
pnlCopies = new CopiesPanel();
687
addToGB(pnlCopies, this, gridbag, c);
688
}
689
690
public boolean isPrintToFileRequested() {
691
return (pnlPrintService.isPrintToFileSelected());
692
}
693
694
public void updateInfo() {
695
pnlPrintService.updateInfo();
696
pnlPrintRange.updateInfo();
697
pnlCopies.updateInfo();
698
}
699
}
700
701
@SuppressWarnings("serial") // Superclass is not serializable across versions
702
private class PrintServicePanel extends JPanel
703
implements ActionListener, ItemListener, PopupMenuListener
704
{
705
private final String strTitle = getMsg("border.printservice");
706
private FilePermission printToFilePermission;
707
private JButton btnProperties;
708
private JCheckBox cbPrintToFile;
709
private JComboBox<String> cbName;
710
private JLabel lblType, lblStatus, lblInfo;
711
private ServiceUIFactory uiFactory;
712
private boolean changedService = false;
713
private boolean filePermission;
714
715
public PrintServicePanel() {
716
super();
717
718
uiFactory = psCurrent.getServiceUIFactory();
719
720
GridBagLayout gridbag = new GridBagLayout();
721
GridBagConstraints c = new GridBagConstraints();
722
723
setLayout(gridbag);
724
setBorder(BorderFactory.createTitledBorder(strTitle));
725
726
String[] psnames = new String[services.length];
727
for (int i = 0; i < psnames.length; i++) {
728
psnames[i] = services[i].getName();
729
}
730
cbName = new JComboBox<>(psnames);
731
cbName.setSelectedIndex(defaultServiceIndex);
732
cbName.addItemListener(this);
733
cbName.addPopupMenuListener(this);
734
735
c.fill = GridBagConstraints.BOTH;
736
c.insets = compInsets;
737
738
c.weightx = 0.0;
739
JLabel lblName = new JLabel(getMsg("label.psname"), JLabel.TRAILING);
740
lblName.setDisplayedMnemonic(getMnemonic("label.psname"));
741
lblName.setLabelFor(cbName);
742
addToGB(lblName, this, gridbag, c);
743
c.weightx = 1.0;
744
c.gridwidth = GridBagConstraints.RELATIVE;
745
addToGB(cbName, this, gridbag, c);
746
c.weightx = 0.0;
747
c.gridwidth = GridBagConstraints.REMAINDER;
748
btnProperties = createButton("button.properties", this);
749
addToGB(btnProperties, this, gridbag, c);
750
751
c.weighty = 1.0;
752
lblStatus = addLabel(getMsg("label.status"), gridbag, c);
753
lblStatus.setLabelFor(null);
754
755
lblType = addLabel(getMsg("label.pstype"), gridbag, c);
756
lblType.setLabelFor(null);
757
758
c.gridwidth = 1;
759
addToGB(new JLabel(getMsg("label.info"), JLabel.TRAILING),
760
this, gridbag, c);
761
c.gridwidth = GridBagConstraints.RELATIVE;
762
lblInfo = new JLabel();
763
lblInfo.setLabelFor(null);
764
765
addToGB(lblInfo, this, gridbag, c);
766
767
c.gridwidth = GridBagConstraints.REMAINDER;
768
cbPrintToFile = createCheckBox("checkbox.printtofile", this);
769
addToGB(cbPrintToFile, this, gridbag, c);
770
771
filePermission = allowedToPrintToFile();
772
}
773
774
public boolean isPrintToFileSelected() {
775
return cbPrintToFile.isSelected();
776
}
777
778
private JLabel addLabel(String text,
779
GridBagLayout gridbag, GridBagConstraints c)
780
{
781
c.gridwidth = 1;
782
addToGB(new JLabel(text, JLabel.TRAILING), this, gridbag, c);
783
784
c.gridwidth = GridBagConstraints.REMAINDER;
785
JLabel label = new JLabel();
786
addToGB(label, this, gridbag, c);
787
788
return label;
789
}
790
791
@SuppressWarnings("deprecation")
792
public void actionPerformed(ActionEvent e) {
793
Object source = e.getSource();
794
795
if (source == btnProperties) {
796
if (uiFactory != null) {
797
JDialog dialog = (JDialog)uiFactory.getUI(
798
ServiceUIFactory.MAIN_UIROLE,
799
ServiceUIFactory.JDIALOG_UI);
800
801
if (dialog != null) {
802
dialog.show();
803
} else {
804
DocumentPropertiesUI docPropertiesUI = null;
805
try {
806
docPropertiesUI =
807
(DocumentPropertiesUI)uiFactory.getUI
808
(DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE,
809
DocumentPropertiesUI.DOCPROPERTIESCLASSNAME);
810
} catch (Exception ex) {
811
}
812
if (docPropertiesUI != null) {
813
PrinterJobWrapper wrapper = (PrinterJobWrapper)
814
asCurrent.get(PrinterJobWrapper.class);
815
if (wrapper == null) {
816
return; // should not happen, defensive only.
817
}
818
PrinterJob job = wrapper.getPrinterJob();
819
if (job == null) {
820
return; // should not happen, defensive only.
821
}
822
PrintRequestAttributeSet newAttrs =
823
docPropertiesUI.showDocumentProperties
824
(job, ServiceDialog.this, psCurrent, asCurrent);
825
if (newAttrs != null) {
826
asCurrent.addAll(newAttrs);
827
updatePanels();
828
}
829
}
830
}
831
}
832
}
833
}
834
835
public void itemStateChanged(ItemEvent e) {
836
if (e.getStateChange() == ItemEvent.SELECTED) {
837
int index = cbName.getSelectedIndex();
838
839
if ((index >= 0) && (index < services.length)) {
840
if (!services[index].equals(psCurrent)) {
841
psCurrent = services[index];
842
uiFactory = psCurrent.getServiceUIFactory();
843
changedService = true;
844
845
Destination dest =
846
(Destination)asOriginal.get(Destination.class);
847
// to preserve the state of Print To File
848
if ((dest != null || isPrintToFileSelected())
849
&& psCurrent.isAttributeCategorySupported(
850
Destination.class)) {
851
852
if (dest != null) {
853
asCurrent.add(dest);
854
} else {
855
dest = (Destination)psCurrent.
856
getDefaultAttributeValue(Destination.class);
857
// "dest" should not be null. The following code
858
// is only added to safeguard against a possible
859
// buggy implementation of a PrintService having a
860
// null default Destination.
861
if (dest == null) {
862
try {
863
dest =
864
new Destination(new URI("file:out.prn"));
865
} catch (URISyntaxException ue) {
866
}
867
}
868
869
if (dest != null) {
870
asCurrent.add(dest);
871
}
872
}
873
} else {
874
asCurrent.remove(Destination.class);
875
}
876
}
877
}
878
}
879
}
880
881
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
882
changedService = false;
883
}
884
885
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
886
if (changedService) {
887
changedService = false;
888
updatePanels();
889
}
890
}
891
892
public void popupMenuCanceled(PopupMenuEvent e) {
893
}
894
895
/**
896
* We disable the "Print To File" checkbox if this returns false
897
*/
898
private boolean allowedToPrintToFile() {
899
try {
900
throwPrintToFile();
901
return true;
902
} catch (SecurityException e) {
903
return false;
904
}
905
}
906
907
/**
908
* Break this out as it may be useful when we allow API to
909
* specify printing to a file. In that case its probably right
910
* to throw a SecurityException if the permission is not granted.
911
*/
912
private void throwPrintToFile() {
913
@SuppressWarnings("removal")
914
SecurityManager security = System.getSecurityManager();
915
if (security != null) {
916
if (printToFilePermission == null) {
917
printToFilePermission =
918
new FilePermission("<<ALL FILES>>", "read,write");
919
}
920
security.checkPermission(printToFilePermission);
921
}
922
}
923
924
public void updateInfo() {
925
Class<Destination> dstCategory = Destination.class;
926
boolean dstSupported = false;
927
boolean dstSelected = false;
928
boolean dstAllowed = filePermission ?
929
allowedToPrintToFile() : false;
930
931
// setup Destination (print-to-file) widgets
932
Destination dst = (Destination)asCurrent.get(dstCategory);
933
if (dst != null) {
934
try {
935
dst.getURI().toURL();
936
if (psCurrent.isAttributeValueSupported(dst, docFlavor,
937
asCurrent)) {
938
dstSupported = true;
939
dstSelected = true;
940
}
941
} catch (MalformedURLException ex) {
942
dstSupported = true;
943
}
944
} else {
945
if (psCurrent.isAttributeCategorySupported(dstCategory)) {
946
dstSupported = true;
947
}
948
}
949
cbPrintToFile.setEnabled(dstSupported && dstAllowed);
950
cbPrintToFile.setSelected(dstSelected && dstAllowed
951
&& dstSupported);
952
953
// setup PrintService information widgets
954
Attribute type = psCurrent.getAttribute(PrinterMakeAndModel.class);
955
if (type != null) {
956
lblType.setText(type.toString());
957
}
958
Attribute status =
959
psCurrent.getAttribute(PrinterIsAcceptingJobs.class);
960
if (status != null) {
961
lblStatus.setText(getMsg(status.toString()));
962
}
963
Attribute info = psCurrent.getAttribute(PrinterInfo.class);
964
if (info != null) {
965
lblInfo.setText(info.toString());
966
}
967
PrinterJob job = null;
968
PrinterJobWrapper wrapper = (PrinterJobWrapper)
969
asCurrent.get(PrinterJobWrapper.class);
970
if (wrapper != null) {
971
job = wrapper.getPrinterJob();
972
}
973
btnProperties.setEnabled(uiFactory != null && job != null);
974
}
975
}
976
977
@SuppressWarnings("serial") // Superclass is not serializable across versions
978
private class PrintRangePanel extends JPanel
979
implements ActionListener, FocusListener
980
{
981
private final String strTitle = getMsg("border.printrange");
982
private final PageRanges prAll = new PageRanges(1, Integer.MAX_VALUE);
983
private JRadioButton rbAll, rbPages, rbSelect;
984
private JFormattedTextField tfRangeFrom, tfRangeTo;
985
private JLabel lblRangeTo;
986
private boolean prSupported;
987
private boolean prPgRngSupported;
988
989
public PrintRangePanel() {
990
super();
991
992
GridBagLayout gridbag = new GridBagLayout();
993
GridBagConstraints c = new GridBagConstraints();
994
995
setLayout(gridbag);
996
setBorder(BorderFactory.createTitledBorder(strTitle));
997
998
c.fill = GridBagConstraints.BOTH;
999
c.insets = compInsets;
1000
c.gridwidth = GridBagConstraints.REMAINDER;
1001
1002
ButtonGroup bg = new ButtonGroup();
1003
JPanel pnlTop = new JPanel(new FlowLayout(FlowLayout.LEADING));
1004
rbAll = createRadioButton("radiobutton.rangeall", this);
1005
rbAll.setSelected(true);
1006
bg.add(rbAll);
1007
pnlTop.add(rbAll);
1008
addToGB(pnlTop, this, gridbag, c);
1009
1010
// Selection never seemed to work so I'm commenting this part.
1011
/*
1012
if (isAWT) {
1013
JPanel pnlMiddle =
1014
new JPanel(new FlowLayout(FlowLayout.LEADING));
1015
rbSelect =
1016
createRadioButton("radiobutton.selection", this);
1017
bg.add(rbSelect);
1018
pnlMiddle.add(rbSelect);
1019
addToGB(pnlMiddle, this, gridbag, c);
1020
}
1021
*/
1022
1023
JPanel pnlBottom = new JPanel(new FlowLayout(FlowLayout.LEADING));
1024
rbPages = createRadioButton("radiobutton.rangepages", this);
1025
bg.add(rbPages);
1026
pnlBottom.add(rbPages);
1027
DecimalFormat format = new DecimalFormat("####0");
1028
format.setMinimumFractionDigits(0);
1029
format.setMaximumFractionDigits(0);
1030
format.setMinimumIntegerDigits(0);
1031
format.setMaximumIntegerDigits(5);
1032
format.setParseIntegerOnly(true);
1033
format.setDecimalSeparatorAlwaysShown(false);
1034
NumberFormatter nf = new NumberFormatter(format);
1035
nf.setMinimum(1);
1036
nf.setMaximum(Integer.MAX_VALUE);
1037
nf.setAllowsInvalid(true);
1038
nf.setCommitsOnValidEdit(true);
1039
tfRangeFrom = new JFormattedTextField(nf);
1040
tfRangeFrom.setColumns(4);
1041
tfRangeFrom.setEnabled(false);
1042
tfRangeFrom.addActionListener(this);
1043
tfRangeFrom.addFocusListener(this);
1044
tfRangeFrom.setFocusLostBehavior(
1045
JFormattedTextField.PERSIST);
1046
tfRangeFrom.getAccessibleContext().setAccessibleName(
1047
getMsg("radiobutton.rangepages"));
1048
pnlBottom.add(tfRangeFrom);
1049
lblRangeTo = new JLabel(getMsg("label.rangeto"));
1050
lblRangeTo.setEnabled(false);
1051
pnlBottom.add(lblRangeTo);
1052
NumberFormatter nfto;
1053
try {
1054
nfto = (NumberFormatter)nf.clone();
1055
} catch (CloneNotSupportedException e) {
1056
nfto = new NumberFormatter();
1057
}
1058
tfRangeTo = new JFormattedTextField(nfto);
1059
tfRangeTo.setColumns(4);
1060
tfRangeTo.setEnabled(false);
1061
tfRangeTo.addFocusListener(this);
1062
tfRangeTo.getAccessibleContext().setAccessibleName(
1063
getMsg("label.rangeto"));
1064
pnlBottom.add(tfRangeTo);
1065
addToGB(pnlBottom, this, gridbag, c);
1066
}
1067
1068
public void actionPerformed(ActionEvent e) {
1069
Object source = e.getSource();
1070
SunPageSelection select = SunPageSelection.ALL;
1071
1072
setupRangeWidgets();
1073
1074
if (source == rbAll) {
1075
asCurrent.add(prAll);
1076
} else if (source == rbSelect) {
1077
select = SunPageSelection.SELECTION;
1078
} else if (source == rbPages ||
1079
source == tfRangeFrom ||
1080
source == tfRangeTo) {
1081
updateRangeAttribute();
1082
select = SunPageSelection.RANGE;
1083
}
1084
1085
if (isAWT) {
1086
asCurrent.add(select);
1087
}
1088
}
1089
1090
public void focusLost(FocusEvent e) {
1091
Object source = e.getSource();
1092
1093
if ((source == tfRangeFrom) || (source == tfRangeTo)) {
1094
updateRangeAttribute();
1095
}
1096
}
1097
1098
public void focusGained(FocusEvent e) {}
1099
1100
private void setupRangeWidgets() {
1101
boolean rangeEnabled = (rbPages.isSelected() && prPgRngSupported);
1102
tfRangeFrom.setEnabled(rangeEnabled);
1103
tfRangeTo.setEnabled(rangeEnabled);
1104
lblRangeTo.setEnabled(rangeEnabled);
1105
}
1106
1107
private void updateRangeAttribute() {
1108
String strFrom = tfRangeFrom.getText();
1109
String strTo = tfRangeTo.getText();
1110
1111
int min;
1112
int max;
1113
1114
try {
1115
min = Integer.parseInt(strFrom);
1116
} catch (NumberFormatException e) {
1117
min = 1;
1118
}
1119
1120
try {
1121
max = Integer.parseInt(strTo);
1122
} catch (NumberFormatException e) {
1123
max = min;
1124
}
1125
1126
if (min < 1) {
1127
min = 1;
1128
tfRangeFrom.setValue(1);
1129
}
1130
1131
if (max < min) {
1132
max = min;
1133
tfRangeTo.setValue(min);
1134
}
1135
1136
PageRanges pr = new PageRanges(min, max);
1137
asCurrent.add(pr);
1138
}
1139
1140
public void updateInfo() {
1141
Class<PageRanges> prCategory = PageRanges.class;
1142
prSupported = false;
1143
1144
if (psCurrent.isAttributeCategorySupported(prCategory) ||
1145
isAWT) {
1146
prSupported = true;
1147
prPgRngSupported = psCurrent.isAttributeValueSupported(prAll,
1148
docFlavor,
1149
asCurrent);
1150
}
1151
1152
SunPageSelection select = SunPageSelection.ALL;
1153
int min = 1;
1154
int max = 1;
1155
1156
PageRanges pr = (PageRanges)asCurrent.get(prCategory);
1157
if (pr != null) {
1158
if (!pr.equals(prAll)) {
1159
select = SunPageSelection.RANGE;
1160
1161
int[][] members = pr.getMembers();
1162
if ((members.length > 0) &&
1163
(members[0].length > 1)) {
1164
min = members[0][0];
1165
max = members[0][1];
1166
}
1167
}
1168
}
1169
1170
if (isAWT) {
1171
select = (SunPageSelection)asCurrent.get(
1172
SunPageSelection.class);
1173
}
1174
1175
if (select == SunPageSelection.ALL) {
1176
rbAll.setSelected(true);
1177
} else if (select == SunPageSelection.SELECTION) {
1178
// Comment this for now - rbSelect is not initialized
1179
// because Selection button is not added.
1180
// See PrintRangePanel above.
1181
1182
//rbSelect.setSelected(true);
1183
} else { // RANGE
1184
rbPages.setSelected(true);
1185
}
1186
tfRangeFrom.setValue(min);
1187
tfRangeTo.setValue(max);
1188
rbAll.setEnabled(prSupported);
1189
rbPages.setEnabled(prPgRngSupported);
1190
setupRangeWidgets();
1191
}
1192
}
1193
1194
@SuppressWarnings("serial") // Superclass is not serializable across versions
1195
private class CopiesPanel extends JPanel
1196
implements ActionListener, ChangeListener
1197
{
1198
private final String strTitle = getMsg("border.copies");
1199
private SpinnerNumberModel snModel;
1200
private JSpinner spinCopies;
1201
private JLabel lblCopies;
1202
private JCheckBox cbCollate;
1203
private boolean scSupported;
1204
1205
public CopiesPanel() {
1206
super();
1207
1208
GridBagLayout gridbag = new GridBagLayout();
1209
GridBagConstraints c = new GridBagConstraints();
1210
1211
setLayout(gridbag);
1212
setBorder(BorderFactory.createTitledBorder(strTitle));
1213
1214
c.fill = GridBagConstraints.HORIZONTAL;
1215
c.insets = compInsets;
1216
1217
lblCopies = new JLabel(getMsg("label.numcopies"), JLabel.TRAILING);
1218
lblCopies.setDisplayedMnemonic(getMnemonic("label.numcopies"));
1219
lblCopies.getAccessibleContext().setAccessibleName(
1220
getMsg("label.numcopies"));
1221
addToGB(lblCopies, this, gridbag, c);
1222
1223
snModel = new SpinnerNumberModel(1, 1, 999, 1);
1224
spinCopies = new JSpinner(snModel);
1225
lblCopies.setLabelFor(spinCopies);
1226
// REMIND
1227
((JSpinner.NumberEditor)spinCopies.getEditor()).getTextField().setColumns(3);
1228
spinCopies.addChangeListener(this);
1229
c.gridwidth = GridBagConstraints.REMAINDER;
1230
addToGB(spinCopies, this, gridbag, c);
1231
1232
cbCollate = createCheckBox("checkbox.collate", this);
1233
cbCollate.setEnabled(false);
1234
addToGB(cbCollate, this, gridbag, c);
1235
}
1236
1237
public void actionPerformed(ActionEvent e) {
1238
if (cbCollate.isSelected()) {
1239
asCurrent.add(SheetCollate.COLLATED);
1240
} else {
1241
asCurrent.add(SheetCollate.UNCOLLATED);
1242
}
1243
}
1244
1245
public void stateChanged(ChangeEvent e) {
1246
updateCollateCB();
1247
1248
asCurrent.add(new Copies(snModel.getNumber().intValue()));
1249
}
1250
1251
private void updateCollateCB() {
1252
int num = snModel.getNumber().intValue();
1253
if (isAWT) {
1254
cbCollate.setEnabled(true);
1255
} else {
1256
cbCollate.setEnabled((num > 1) && scSupported);
1257
}
1258
}
1259
1260
public void updateInfo() {
1261
Class<Copies> cpCategory = Copies.class;
1262
Class<SheetCollate> scCategory = SheetCollate.class;
1263
boolean cpSupported = false;
1264
scSupported = false;
1265
1266
// setup Copies spinner
1267
if (psCurrent.isAttributeCategorySupported(cpCategory)) {
1268
cpSupported = true;
1269
}
1270
CopiesSupported cs =
1271
(CopiesSupported)psCurrent.getSupportedAttributeValues(
1272
cpCategory, null, null);
1273
if (cs == null) {
1274
cs = new CopiesSupported(1, 999);
1275
}
1276
Copies cp = (Copies)asCurrent.get(cpCategory);
1277
if (cp == null) {
1278
cp = (Copies)psCurrent.getDefaultAttributeValue(cpCategory);
1279
if (cp == null) {
1280
cp = new Copies(1);
1281
}
1282
}
1283
spinCopies.setEnabled(cpSupported);
1284
lblCopies.setEnabled(cpSupported);
1285
1286
int[][] members = cs.getMembers();
1287
int min, max;
1288
if ((members.length > 0) && (members[0].length > 0)) {
1289
min = members[0][0];
1290
max = members[0][1];
1291
} else {
1292
min = 1;
1293
max = Integer.MAX_VALUE;
1294
}
1295
snModel.setMinimum(min);
1296
snModel.setMaximum(max);
1297
1298
int value = cp.getValue();
1299
if ((value < min) || (value > max)) {
1300
value = min;
1301
}
1302
snModel.setValue(value);
1303
1304
// setup Collate checkbox
1305
if (psCurrent.isAttributeCategorySupported(scCategory)) {
1306
scSupported = true;
1307
}
1308
SheetCollate sc = (SheetCollate)asCurrent.get(scCategory);
1309
if (sc == null) {
1310
sc = (SheetCollate)psCurrent.getDefaultAttributeValue(scCategory);
1311
if (sc == null) {
1312
sc = SheetCollate.UNCOLLATED;
1313
}
1314
if (sc != null &&
1315
!psCurrent.isAttributeValueSupported(sc, docFlavor, asCurrent)) {
1316
scSupported = false;
1317
}
1318
} else {
1319
if (!psCurrent.isAttributeValueSupported(sc, docFlavor, asCurrent)) {
1320
scSupported = false;
1321
}
1322
}
1323
cbCollate.setSelected(sc == SheetCollate.COLLATED && scSupported);
1324
updateCollateCB();
1325
}
1326
}
1327
1328
1329
1330
1331
/**
1332
* The "Page Setup" tab. Includes the controls for MediaSource/MediaTray,
1333
* OrientationRequested, and Sides.
1334
*/
1335
@SuppressWarnings("serial") // Superclass is not serializable across versions
1336
private class PageSetupPanel extends JPanel {
1337
1338
private MediaPanel pnlMedia;
1339
private OrientationPanel pnlOrientation;
1340
private MarginsPanel pnlMargins;
1341
1342
public PageSetupPanel() {
1343
super();
1344
1345
GridBagLayout gridbag = new GridBagLayout();
1346
GridBagConstraints c = new GridBagConstraints();
1347
1348
setLayout(gridbag);
1349
1350
c.fill = GridBagConstraints.BOTH;
1351
c.insets = panelInsets;
1352
c.weightx = 1.0;
1353
c.weighty = 1.0;
1354
1355
c.gridwidth = GridBagConstraints.REMAINDER;
1356
pnlMedia = new MediaPanel();
1357
addToGB(pnlMedia, this, gridbag, c);
1358
1359
pnlOrientation = new OrientationPanel();
1360
c.gridwidth = GridBagConstraints.RELATIVE;
1361
addToGB(pnlOrientation, this, gridbag, c);
1362
1363
pnlMargins = new MarginsPanel();
1364
pnlOrientation.addOrientationListener(pnlMargins);
1365
pnlMedia.addMediaListener(pnlMargins);
1366
c.gridwidth = GridBagConstraints.REMAINDER;
1367
addToGB(pnlMargins, this, gridbag, c);
1368
}
1369
1370
public void updateInfo() {
1371
pnlMedia.updateInfo();
1372
pnlOrientation.updateInfo();
1373
pnlMargins.updateInfo();
1374
}
1375
}
1376
1377
@SuppressWarnings("serial") // Superclass is not serializable across versions
1378
private class MarginsPanel extends JPanel
1379
implements ActionListener, FocusListener {
1380
1381
private final String strTitle = getMsg("border.margins");
1382
private JFormattedTextField leftMargin, rightMargin,
1383
topMargin, bottomMargin;
1384
private JLabel lblLeft, lblRight, lblTop, lblBottom;
1385
private int units = MediaPrintableArea.MM;
1386
// storage for the last margin values calculated, -ve is uninitialised
1387
private float lmVal = -1f,rmVal = -1f, tmVal = -1f, bmVal = -1f;
1388
// storage for margins as objects mapped into orientation for display
1389
private Float lmObj,rmObj,tmObj,bmObj;
1390
1391
public MarginsPanel() {
1392
super();
1393
1394
GridBagLayout gridbag = new GridBagLayout();
1395
GridBagConstraints c = new GridBagConstraints();
1396
c.fill = GridBagConstraints.HORIZONTAL;
1397
c.weightx = 1.0;
1398
c.weighty = 0.0;
1399
c.insets = compInsets;
1400
1401
setLayout(gridbag);
1402
setBorder(BorderFactory.createTitledBorder(strTitle));
1403
1404
String unitsKey = "label.millimetres";
1405
String defaultCountry = Locale.getDefault().getCountry();
1406
if (defaultCountry != null &&
1407
(defaultCountry.isEmpty() ||
1408
defaultCountry.equals(Locale.US.getCountry()) ||
1409
defaultCountry.equals(Locale.CANADA.getCountry()))) {
1410
unitsKey = "label.inches";
1411
units = MediaPrintableArea.INCH;
1412
}
1413
String unitsMsg = getMsg(unitsKey);
1414
1415
DecimalFormat format;
1416
if (units == MediaPrintableArea.MM) {
1417
format = new DecimalFormat("###.##");
1418
format.setMaximumIntegerDigits(3);
1419
} else {
1420
format = new DecimalFormat("##.##");
1421
format.setMaximumIntegerDigits(2);
1422
}
1423
1424
format.setMinimumFractionDigits(1);
1425
format.setMaximumFractionDigits(2);
1426
format.setMinimumIntegerDigits(1);
1427
format.setParseIntegerOnly(false);
1428
format.setDecimalSeparatorAlwaysShown(true);
1429
NumberFormatter nf = new NumberFormatter(format);
1430
nf.setMinimum(Float.valueOf(0.0f));
1431
nf.setMaximum(Float.valueOf(999.0f));
1432
nf.setAllowsInvalid(true);
1433
nf.setCommitsOnValidEdit(true);
1434
1435
leftMargin = new JFormattedTextField(nf);
1436
leftMargin.addFocusListener(this);
1437
leftMargin.addActionListener(this);
1438
leftMargin.getAccessibleContext().setAccessibleName(
1439
getMsg("label.leftmargin"));
1440
rightMargin = new JFormattedTextField(nf);
1441
rightMargin.addFocusListener(this);
1442
rightMargin.addActionListener(this);
1443
rightMargin.getAccessibleContext().setAccessibleName(
1444
getMsg("label.rightmargin"));
1445
topMargin = new JFormattedTextField(nf);
1446
topMargin.addFocusListener(this);
1447
topMargin.addActionListener(this);
1448
topMargin.getAccessibleContext().setAccessibleName(
1449
getMsg("label.topmargin"));
1450
1451
bottomMargin = new JFormattedTextField(nf);
1452
bottomMargin.addFocusListener(this);
1453
bottomMargin.addActionListener(this);
1454
bottomMargin.getAccessibleContext().setAccessibleName(
1455
getMsg("label.bottommargin"));
1456
1457
c.gridwidth = GridBagConstraints.RELATIVE;
1458
lblLeft = new JLabel(getMsg("label.leftmargin") + " " + unitsMsg,
1459
JLabel.LEADING);
1460
lblLeft.setDisplayedMnemonic(getMnemonic("label.leftmargin"));
1461
lblLeft.setLabelFor(leftMargin);
1462
addToGB(lblLeft, this, gridbag, c);
1463
1464
c.gridwidth = GridBagConstraints.REMAINDER;
1465
lblRight = new JLabel(getMsg("label.rightmargin") + " " + unitsMsg,
1466
JLabel.LEADING);
1467
lblRight.setDisplayedMnemonic(getMnemonic("label.rightmargin"));
1468
lblRight.setLabelFor(rightMargin);
1469
addToGB(lblRight, this, gridbag, c);
1470
1471
c.gridwidth = GridBagConstraints.RELATIVE;
1472
addToGB(leftMargin, this, gridbag, c);
1473
1474
c.gridwidth = GridBagConstraints.REMAINDER;
1475
addToGB(rightMargin, this, gridbag, c);
1476
1477
// add an invisible spacing component.
1478
addToGB(new JPanel(), this, gridbag, c);
1479
1480
c.gridwidth = GridBagConstraints.RELATIVE;
1481
lblTop = new JLabel(getMsg("label.topmargin") + " " + unitsMsg,
1482
JLabel.LEADING);
1483
lblTop.setDisplayedMnemonic(getMnemonic("label.topmargin"));
1484
lblTop.setLabelFor(topMargin);
1485
addToGB(lblTop, this, gridbag, c);
1486
1487
c.gridwidth = GridBagConstraints.REMAINDER;
1488
lblBottom = new JLabel(getMsg("label.bottommargin") +
1489
" " + unitsMsg, JLabel.LEADING);
1490
lblBottom.setDisplayedMnemonic(getMnemonic("label.bottommargin"));
1491
lblBottom.setLabelFor(bottomMargin);
1492
addToGB(lblBottom, this, gridbag, c);
1493
1494
c.gridwidth = GridBagConstraints.RELATIVE;
1495
addToGB(topMargin, this, gridbag, c);
1496
1497
c.gridwidth = GridBagConstraints.REMAINDER;
1498
addToGB(bottomMargin, this, gridbag, c);
1499
1500
}
1501
1502
public void actionPerformed(ActionEvent e) {
1503
Object source = e.getSource();
1504
updateMargins(source);
1505
}
1506
1507
public void focusLost(FocusEvent e) {
1508
Object source = e.getSource();
1509
updateMargins(source);
1510
}
1511
1512
public void focusGained(FocusEvent e) {}
1513
1514
/* Get the numbers, use to create a MPA.
1515
* If its valid, accept it and update the attribute set.
1516
* If its not valid, then reject it and call updateInfo()
1517
* to re-establish the previous entries.
1518
*/
1519
public void updateMargins(Object source) {
1520
if (!(source instanceof JFormattedTextField)) {
1521
return;
1522
} else {
1523
JFormattedTextField tf = (JFormattedTextField)source;
1524
Float val = (Float)tf.getValue();
1525
if (val == null) {
1526
return;
1527
}
1528
if (tf == leftMargin && val.equals(lmObj)) {
1529
return;
1530
}
1531
if (tf == rightMargin && val.equals(rmObj)) {
1532
return;
1533
}
1534
if (tf == topMargin && val.equals(tmObj)) {
1535
return;
1536
}
1537
if (tf == bottomMargin && val.equals(bmObj)) {
1538
return;
1539
}
1540
}
1541
1542
Float lmTmpObj = (Float)leftMargin.getValue();
1543
Float rmTmpObj = (Float)rightMargin.getValue();
1544
Float tmTmpObj = (Float)topMargin.getValue();
1545
Float bmTmpObj = (Float)bottomMargin.getValue();
1546
1547
float lm = lmTmpObj.floatValue();
1548
float rm = rmTmpObj.floatValue();
1549
float tm = tmTmpObj.floatValue();
1550
float bm = bmTmpObj.floatValue();
1551
1552
/* adjust for orientation */
1553
Class<OrientationRequested> orCategory = OrientationRequested.class;
1554
OrientationRequested or =
1555
(OrientationRequested)asCurrent.get(orCategory);
1556
1557
if (or == null) {
1558
or = (OrientationRequested)
1559
psCurrent.getDefaultAttributeValue(orCategory);
1560
}
1561
1562
float tmp;
1563
if (or == OrientationRequested.REVERSE_PORTRAIT) {
1564
tmp = lm; lm = rm; rm = tmp;
1565
tmp = tm; tm = bm; bm = tmp;
1566
} else if (or == OrientationRequested.LANDSCAPE) {
1567
tmp = lm;
1568
lm = tm;
1569
tm = rm;
1570
rm = bm;
1571
bm = tmp;
1572
} else if (or == OrientationRequested.REVERSE_LANDSCAPE) {
1573
tmp = lm;
1574
lm = bm;
1575
bm = rm;
1576
rm = tm;
1577
tm = tmp;
1578
}
1579
MediaPrintableArea mpa;
1580
if ((mpa = validateMargins(lm, rm, tm, bm)) != null) {
1581
asCurrent.add(mpa);
1582
lmVal = lm;
1583
rmVal = rm;
1584
tmVal = tm;
1585
bmVal = bm;
1586
lmObj = lmTmpObj;
1587
rmObj = rmTmpObj;
1588
tmObj = tmTmpObj;
1589
bmObj = bmTmpObj;
1590
} else {
1591
if (lmObj == null || rmObj == null ||
1592
tmObj == null || bmObj == null) {
1593
return;
1594
} else {
1595
leftMargin.setValue(lmObj);
1596
rightMargin.setValue(rmObj);
1597
topMargin.setValue(tmObj);
1598
bottomMargin.setValue(bmObj);
1599
1600
}
1601
}
1602
}
1603
1604
/*
1605
* This method either accepts the values and creates a new
1606
* MediaPrintableArea, or does nothing.
1607
* It should not attempt to create a printable area from anything
1608
* other than the exact values passed in.
1609
* But REMIND/TBD: it would be user friendly to replace margins the
1610
* user entered but are out of bounds with the minimum.
1611
* At that point this method will need to take responsibility for
1612
* updating the "stored" values and the UI.
1613
*/
1614
private MediaPrintableArea validateMargins(float lm, float rm,
1615
float tm, float bm) {
1616
1617
Class<MediaPrintableArea> mpaCategory = MediaPrintableArea.class;
1618
MediaPrintableArea mpa;
1619
MediaPrintableArea mpaMax = null;
1620
MediaSize mediaSize = null;
1621
1622
Media media = (Media)asCurrent.get(Media.class);
1623
if (media == null || !(media instanceof MediaSizeName)) {
1624
media = (Media)psCurrent.getDefaultAttributeValue(Media.class);
1625
}
1626
if (media != null && (media instanceof MediaSizeName)) {
1627
MediaSizeName msn = (MediaSizeName)media;
1628
mediaSize = MediaSize.getMediaSizeForName(msn);
1629
}
1630
if (mediaSize == null) {
1631
mediaSize = new MediaSize(8.5f, 11f, Size2DSyntax.INCH);
1632
}
1633
1634
if (media != null) {
1635
PrintRequestAttributeSet tmpASet =
1636
new HashPrintRequestAttributeSet(asCurrent);
1637
tmpASet.add(media);
1638
1639
Object values =
1640
psCurrent.getSupportedAttributeValues(mpaCategory,
1641
docFlavor,
1642
tmpASet);
1643
if (values instanceof MediaPrintableArea[] &&
1644
((MediaPrintableArea[])values).length > 0) {
1645
mpaMax = ((MediaPrintableArea[])values)[0];
1646
1647
}
1648
}
1649
if (mpaMax == null) {
1650
mpaMax = new MediaPrintableArea(0f, 0f,
1651
mediaSize.getX(units),
1652
mediaSize.getY(units),
1653
units);
1654
}
1655
1656
float wid = mediaSize.getX(units);
1657
float hgt = mediaSize.getY(units);
1658
float pax = lm;
1659
float pay = tm;
1660
float par = rm;
1661
float pab = bm;
1662
float paw = wid - lm - rm;
1663
float pah = hgt - tm - bm;
1664
1665
if (paw <= 0f || pah <= 0f || pax < 0f || pay < 0f ||
1666
par <= 0f || pab <= 0f ||
1667
pax < mpaMax.getX(units) || paw > mpaMax.getWidth(units) ||
1668
pay < mpaMax.getY(units) || pah > mpaMax.getHeight(units)) {
1669
return null;
1670
} else {
1671
return new MediaPrintableArea(lm, tm, paw, pah, units);
1672
}
1673
}
1674
1675
/* This is complex as a MediaPrintableArea is valid only within
1676
* a particular context of media size.
1677
* So we need a MediaSize as well as a MediaPrintableArea.
1678
* MediaSize can be obtained from MediaSizeName.
1679
* If the application specifies a MediaPrintableArea, we accept it
1680
* to the extent its valid for the Media they specify. If they
1681
* don't specify a Media, then the default is assumed.
1682
*
1683
* If an application doesn't define a MediaPrintableArea, we need to
1684
* create a suitable one, this is created using the specified (or
1685
* default) Media and default 1 inch margins. This is validated
1686
* against the paper in case this is too large for tiny media.
1687
*/
1688
public void updateInfo() {
1689
1690
if (isAWT) {
1691
leftMargin.setEnabled(false);
1692
rightMargin.setEnabled(false);
1693
topMargin.setEnabled(false);
1694
bottomMargin.setEnabled(false);
1695
lblLeft.setEnabled(false);
1696
lblRight.setEnabled(false);
1697
lblTop.setEnabled(false);
1698
lblBottom.setEnabled(false);
1699
return;
1700
}
1701
1702
Class<MediaPrintableArea> mpaCategory = MediaPrintableArea.class;
1703
MediaPrintableArea mpa =
1704
(MediaPrintableArea)asCurrent.get(mpaCategory);
1705
MediaPrintableArea mpaMax = null;
1706
MediaSize mediaSize = null;
1707
1708
Media media = (Media)asCurrent.get(Media.class);
1709
if (media == null || !(media instanceof MediaSizeName)) {
1710
media = (Media)psCurrent.getDefaultAttributeValue(Media.class);
1711
}
1712
if (media != null && (media instanceof MediaSizeName)) {
1713
MediaSizeName msn = (MediaSizeName)media;
1714
mediaSize = MediaSize.getMediaSizeForName(msn);
1715
}
1716
if (mediaSize == null) {
1717
mediaSize = new MediaSize(8.5f, 11f, Size2DSyntax.INCH);
1718
}
1719
1720
if (media != null) {
1721
PrintRequestAttributeSet tmpASet =
1722
new HashPrintRequestAttributeSet(asCurrent);
1723
tmpASet.add(media);
1724
1725
Object values =
1726
psCurrent.getSupportedAttributeValues(mpaCategory,
1727
docFlavor,
1728
tmpASet);
1729
if (values instanceof MediaPrintableArea[] &&
1730
((MediaPrintableArea[])values).length > 0) {
1731
mpaMax = ((MediaPrintableArea[])values)[0];
1732
1733
} else if (values instanceof MediaPrintableArea) {
1734
mpaMax = (MediaPrintableArea)values;
1735
}
1736
}
1737
if (mpaMax == null) {
1738
mpaMax = new MediaPrintableArea(0f, 0f,
1739
mediaSize.getX(units),
1740
mediaSize.getY(units),
1741
units);
1742
}
1743
1744
/*
1745
* At this point we now know as best we can :-
1746
* - the media size
1747
* - the maximum corresponding printable area
1748
* - the media printable area specified by the client, if any.
1749
* The next step is to create a default MPA if none was specified.
1750
* 1" margins are used unless they are disproportionately
1751
* large compared to the size of the media.
1752
*/
1753
1754
float wid = mediaSize.getX(MediaPrintableArea.INCH);
1755
float hgt = mediaSize.getY(MediaPrintableArea.INCH);
1756
float maxMarginRatio = 5f;
1757
float xMgn, yMgn;
1758
if (wid > maxMarginRatio) {
1759
xMgn = 1f;
1760
} else {
1761
xMgn = wid / maxMarginRatio;
1762
}
1763
if (hgt > maxMarginRatio) {
1764
yMgn = 1f;
1765
} else {
1766
yMgn = hgt / maxMarginRatio;
1767
}
1768
1769
if (mpa == null) {
1770
mpa = new MediaPrintableArea(xMgn, yMgn,
1771
wid-(2*xMgn), hgt-(2*yMgn),
1772
MediaPrintableArea.INCH);
1773
asCurrent.add(mpa);
1774
}
1775
float pax = mpa.getX(units);
1776
float pay = mpa.getY(units);
1777
float paw = mpa.getWidth(units);
1778
float pah = mpa.getHeight(units);
1779
float paxMax = mpaMax.getX(units);
1780
float payMax = mpaMax.getY(units);
1781
float pawMax = mpaMax.getWidth(units);
1782
float pahMax = mpaMax.getHeight(units);
1783
1784
1785
boolean invalid = false;
1786
1787
// If the paper is set to something which is too small to
1788
// accommodate a specified printable area, perhaps carried
1789
// over from a larger paper, the adjustment that needs to be
1790
// performed should seem the most natural from a user's viewpoint.
1791
// Since the user is specifying margins, then we are biased
1792
// towards keeping the margins as close to what is specified as
1793
// possible, shrinking or growing the printable area.
1794
// But the API uses printable area, so you need to know the
1795
// media size in which the margins were previously interpreted,
1796
// or at least have a record of the margins.
1797
// In the case that this is the creation of this UI we do not
1798
// have this record, so we are somewhat reliant on the client
1799
// to supply a reasonable default
1800
wid = mediaSize.getX(units);
1801
hgt = mediaSize.getY(units);
1802
if (lmVal >= 0f) {
1803
invalid = true;
1804
1805
if (lmVal + rmVal > wid) {
1806
// margins impossible, but maintain P.A if can
1807
if (paw > pawMax) {
1808
paw = pawMax;
1809
}
1810
// try to centre the printable area.
1811
pax = (wid - paw)/2f;
1812
} else {
1813
pax = (lmVal >= paxMax) ? lmVal : paxMax;
1814
paw = wid - pax - rmVal;
1815
}
1816
if (tmVal + bmVal > hgt) {
1817
if (pah > pahMax) {
1818
pah = pahMax;
1819
}
1820
pay = (hgt - pah)/2f;
1821
} else {
1822
pay = (tmVal >= payMax) ? tmVal : payMax;
1823
pah = hgt - pay - bmVal;
1824
}
1825
}
1826
if (pax < paxMax) {
1827
invalid = true;
1828
pax = paxMax;
1829
}
1830
if (pay < payMax) {
1831
invalid = true;
1832
pay = payMax;
1833
}
1834
if (paw > pawMax) {
1835
invalid = true;
1836
paw = pawMax;
1837
}
1838
if (pah > pahMax) {
1839
invalid = true;
1840
pah = pahMax;
1841
}
1842
1843
if ((pax + paw > paxMax + pawMax) || (paw <= 0f)) {
1844
invalid = true;
1845
pax = paxMax;
1846
paw = pawMax;
1847
}
1848
if ((pay + pah > payMax + pahMax) || (pah <= 0f)) {
1849
invalid = true;
1850
pay = payMax;
1851
pah = pahMax;
1852
}
1853
1854
if (invalid) {
1855
mpa = new MediaPrintableArea(pax, pay, paw, pah, units);
1856
asCurrent.add(mpa);
1857
}
1858
1859
/* We now have a valid printable area.
1860
* Turn it into margins, using the mediaSize
1861
*/
1862
lmVal = pax;
1863
tmVal = pay;
1864
rmVal = mediaSize.getX(units) - pax - paw;
1865
bmVal = mediaSize.getY(units) - pay - pah;
1866
1867
lmObj = lmVal;
1868
rmObj = rmVal;
1869
tmObj = tmVal;
1870
bmObj = bmVal;
1871
1872
/* Now we know the values to use, we need to assign them
1873
* to the fields appropriate for the orientation.
1874
* Note: if orientation changes this method must be called.
1875
*/
1876
Class<OrientationRequested> orCategory = OrientationRequested.class;
1877
OrientationRequested or =
1878
(OrientationRequested)asCurrent.get(orCategory);
1879
1880
if (or == null) {
1881
or = (OrientationRequested)
1882
psCurrent.getDefaultAttributeValue(orCategory);
1883
}
1884
1885
Float tmp;
1886
1887
if (or == OrientationRequested.REVERSE_PORTRAIT) {
1888
tmp = lmObj; lmObj = rmObj; rmObj = tmp;
1889
tmp = tmObj; tmObj = bmObj; bmObj = tmp;
1890
} else if (or == OrientationRequested.LANDSCAPE) {
1891
tmp = lmObj;
1892
lmObj = bmObj;
1893
bmObj = rmObj;
1894
rmObj = tmObj;
1895
tmObj = tmp;
1896
} else if (or == OrientationRequested.REVERSE_LANDSCAPE) {
1897
tmp = lmObj;
1898
lmObj = tmObj;
1899
tmObj = rmObj;
1900
rmObj = bmObj;
1901
bmObj = tmp;
1902
}
1903
1904
leftMargin.setValue(lmObj);
1905
rightMargin.setValue(rmObj);
1906
topMargin.setValue(tmObj);
1907
bottomMargin.setValue(bmObj);
1908
}
1909
}
1910
1911
@SuppressWarnings("serial") // Superclass is not serializable across versions
1912
private class MediaPanel extends JPanel implements ItemListener {
1913
1914
private final String strTitle = getMsg("border.media");
1915
private JLabel lblSize, lblSource;
1916
private JComboBox<Object> cbSize, cbSource;
1917
private Vector<MediaSizeName> sizes = new Vector<>();
1918
private Vector<MediaTray> sources = new Vector<>();
1919
private MarginsPanel pnlMargins = null;
1920
1921
public MediaPanel() {
1922
super();
1923
1924
GridBagLayout gridbag = new GridBagLayout();
1925
GridBagConstraints c = new GridBagConstraints();
1926
1927
setLayout(gridbag);
1928
setBorder(BorderFactory.createTitledBorder(strTitle));
1929
1930
cbSize = new JComboBox<>();
1931
cbSource = new JComboBox<>();
1932
1933
c.fill = GridBagConstraints.BOTH;
1934
c.insets = compInsets;
1935
c.weighty = 1.0;
1936
1937
c.weightx = 0.0;
1938
lblSize = new JLabel(getMsg("label.size"), JLabel.TRAILING);
1939
lblSize.setDisplayedMnemonic(getMnemonic("label.size"));
1940
lblSize.setLabelFor(cbSize);
1941
addToGB(lblSize, this, gridbag, c);
1942
c.weightx = 1.0;
1943
c.gridwidth = GridBagConstraints.REMAINDER;
1944
addToGB(cbSize, this, gridbag, c);
1945
1946
c.weightx = 0.0;
1947
c.gridwidth = 1;
1948
lblSource = new JLabel(getMsg("label.source"), JLabel.TRAILING);
1949
lblSource.setDisplayedMnemonic(getMnemonic("label.source"));
1950
lblSource.setLabelFor(cbSource);
1951
addToGB(lblSource, this, gridbag, c);
1952
c.gridwidth = GridBagConstraints.REMAINDER;
1953
addToGB(cbSource, this, gridbag, c);
1954
}
1955
1956
private String getMediaName(String key) {
1957
try {
1958
// replace characters that would be invalid in
1959
// a resource key with valid characters
1960
String newkey = key.replace(' ', '-');
1961
newkey = newkey.replace('#', 'n');
1962
1963
return messageRB.getString(newkey);
1964
} catch (java.util.MissingResourceException e) {
1965
return key;
1966
}
1967
}
1968
1969
public void itemStateChanged(ItemEvent e) {
1970
Object source = e.getSource();
1971
1972
if (e.getStateChange() == ItemEvent.SELECTED) {
1973
if (source == cbSize) {
1974
int index = cbSize.getSelectedIndex();
1975
1976
if ((index >= 0) && (index < sizes.size())) {
1977
if ((cbSource.getItemCount() > 1) &&
1978
(cbSource.getSelectedIndex() >= 1))
1979
{
1980
int src = cbSource.getSelectedIndex() - 1;
1981
MediaTray mt = sources.get(src);
1982
asCurrent.add(new SunAlternateMedia(mt));
1983
}
1984
asCurrent.add(sizes.get(index));
1985
}
1986
} else if (source == cbSource) {
1987
int index = cbSource.getSelectedIndex();
1988
1989
if ((index >= 1) && (index < (sources.size() + 1))) {
1990
asCurrent.remove(SunAlternateMedia.class);
1991
MediaTray newTray = sources.get(index - 1);
1992
Media m = (Media)asCurrent.get(Media.class);
1993
if (m == null || m instanceof MediaTray) {
1994
asCurrent.add(newTray);
1995
} else if (m instanceof MediaSizeName) {
1996
MediaSizeName msn = (MediaSizeName)m;
1997
Media def = (Media)psCurrent.getDefaultAttributeValue(Media.class);
1998
if (def instanceof MediaSizeName && def.equals(msn)) {
1999
asCurrent.add(newTray);
2000
} else {
2001
/* Non-default paper size, so need to store tray
2002
* as SunAlternateMedia
2003
*/
2004
asCurrent.add(new SunAlternateMedia(newTray));
2005
}
2006
}
2007
} else if (index == 0) {
2008
asCurrent.remove(SunAlternateMedia.class);
2009
if (cbSize.getItemCount() > 0) {
2010
int size = cbSize.getSelectedIndex();
2011
asCurrent.add(sizes.get(size));
2012
}
2013
}
2014
}
2015
// orientation affects display of margins.
2016
if (pnlMargins != null) {
2017
pnlMargins.updateInfo();
2018
}
2019
}
2020
}
2021
2022
2023
/* this is ad hoc to keep things simple */
2024
public void addMediaListener(MarginsPanel pnl) {
2025
pnlMargins = pnl;
2026
}
2027
public void updateInfo() {
2028
Class<Media> mdCategory = Media.class;
2029
Class<SunAlternateMedia> amCategory = SunAlternateMedia.class;
2030
boolean mediaSupported = false;
2031
2032
cbSize.removeItemListener(this);
2033
cbSize.removeAllItems();
2034
cbSource.removeItemListener(this);
2035
cbSource.removeAllItems();
2036
cbSource.addItem(getMediaName("auto-select"));
2037
2038
sizes.clear();
2039
sources.clear();
2040
2041
if (psCurrent.isAttributeCategorySupported(mdCategory)) {
2042
mediaSupported = true;
2043
2044
Object values =
2045
psCurrent.getSupportedAttributeValues(mdCategory,
2046
docFlavor,
2047
asCurrent);
2048
2049
if (values instanceof Media[]) {
2050
Media[] media = (Media[])values;
2051
2052
for (int i = 0; i < media.length; i++) {
2053
Media medium = media[i];
2054
2055
if (medium instanceof MediaSizeName) {
2056
sizes.add((MediaSizeName)medium);
2057
cbSize.addItem(getMediaName(medium.toString()));
2058
} else if (medium instanceof MediaTray) {
2059
sources.add((MediaTray)medium);
2060
cbSource.addItem(getMediaName(medium.toString()));
2061
}
2062
}
2063
}
2064
}
2065
2066
boolean msSupported = (mediaSupported && (sizes.size() > 0));
2067
lblSize.setEnabled(msSupported);
2068
cbSize.setEnabled(msSupported);
2069
2070
if (isAWT) {
2071
cbSource.setEnabled(false);
2072
lblSource.setEnabled(false);
2073
} else {
2074
cbSource.setEnabled(mediaSupported);
2075
}
2076
2077
if (mediaSupported) {
2078
2079
Media medium = (Media)asCurrent.get(mdCategory);
2080
2081
// initialize size selection to default
2082
Media defMedia = (Media)psCurrent.getDefaultAttributeValue(mdCategory);
2083
if (defMedia instanceof MediaSizeName) {
2084
cbSize.setSelectedIndex(sizes.size() > 0 ? sizes.indexOf(defMedia) : -1);
2085
}
2086
2087
if (medium == null ||
2088
!psCurrent.isAttributeValueSupported(medium,
2089
docFlavor, asCurrent)) {
2090
2091
medium = defMedia;
2092
2093
if (medium == null) {
2094
if (sizes.size() > 0) {
2095
medium = (Media)sizes.get(0);
2096
}
2097
}
2098
if (medium != null) {
2099
asCurrent.add(medium);
2100
}
2101
}
2102
if (medium != null) {
2103
if (medium instanceof MediaSizeName) {
2104
MediaSizeName ms = (MediaSizeName)medium;
2105
cbSize.setSelectedIndex(sizes.indexOf(ms));
2106
} else if (medium instanceof MediaTray) {
2107
MediaTray mt = (MediaTray)medium;
2108
cbSource.setSelectedIndex(sources.indexOf(mt) + 1);
2109
}
2110
} else {
2111
cbSize.setSelectedIndex(sizes.size() > 0 ? 0 : -1);
2112
cbSource.setSelectedIndex(0);
2113
}
2114
2115
SunAlternateMedia alt = (SunAlternateMedia)asCurrent.get(amCategory);
2116
if (alt != null) {
2117
Media md = alt.getMedia();
2118
if (md instanceof MediaTray) {
2119
MediaTray mt = (MediaTray)md;
2120
cbSource.setSelectedIndex(sources.indexOf(mt) + 1);
2121
}
2122
}
2123
2124
int selIndex = cbSize.getSelectedIndex();
2125
if ((selIndex >= 0) && (selIndex < sizes.size())) {
2126
asCurrent.add(sizes.get(selIndex));
2127
}
2128
2129
selIndex = cbSource.getSelectedIndex();
2130
if ((selIndex >= 1) && (selIndex < (sources.size()+1))) {
2131
MediaTray mt = sources.get(selIndex-1);
2132
if (medium instanceof MediaTray) {
2133
asCurrent.add(mt);
2134
} else {
2135
asCurrent.add(new SunAlternateMedia(mt));
2136
}
2137
}
2138
2139
2140
}
2141
cbSize.addItemListener(this);
2142
cbSource.addItemListener(this);
2143
}
2144
}
2145
2146
@SuppressWarnings("serial") // Superclass is not serializable across versions
2147
private class OrientationPanel extends JPanel
2148
implements ActionListener
2149
{
2150
private final String strTitle = getMsg("border.orientation");
2151
private IconRadioButton rbPortrait, rbLandscape,
2152
rbRevPortrait, rbRevLandscape;
2153
private MarginsPanel pnlMargins = null;
2154
2155
public OrientationPanel() {
2156
super();
2157
2158
GridBagLayout gridbag = new GridBagLayout();
2159
GridBagConstraints c = new GridBagConstraints();
2160
2161
setLayout(gridbag);
2162
setBorder(BorderFactory.createTitledBorder(strTitle));
2163
2164
c.fill = GridBagConstraints.BOTH;
2165
c.insets = compInsets;
2166
c.weighty = 1.0;
2167
c.gridwidth = GridBagConstraints.REMAINDER;
2168
2169
ButtonGroup bg = new ButtonGroup();
2170
rbPortrait = new IconRadioButton("radiobutton.portrait",
2171
"orientPortrait.png", true,
2172
bg, this);
2173
rbPortrait.addActionListener(this);
2174
addToGB(rbPortrait, this, gridbag, c);
2175
rbLandscape = new IconRadioButton("radiobutton.landscape",
2176
"orientLandscape.png", false,
2177
bg, this);
2178
rbLandscape.addActionListener(this);
2179
addToGB(rbLandscape, this, gridbag, c);
2180
rbRevPortrait = new IconRadioButton("radiobutton.revportrait",
2181
"orientRevPortrait.png", false,
2182
bg, this);
2183
rbRevPortrait.addActionListener(this);
2184
addToGB(rbRevPortrait, this, gridbag, c);
2185
rbRevLandscape = new IconRadioButton("radiobutton.revlandscape",
2186
"orientRevLandscape.png", false,
2187
bg, this);
2188
rbRevLandscape.addActionListener(this);
2189
addToGB(rbRevLandscape, this, gridbag, c);
2190
}
2191
2192
public void actionPerformed(ActionEvent e) {
2193
Object source = e.getSource();
2194
2195
if (rbPortrait.isSameAs(source)) {
2196
asCurrent.add(OrientationRequested.PORTRAIT);
2197
} else if (rbLandscape.isSameAs(source)) {
2198
asCurrent.add(OrientationRequested.LANDSCAPE);
2199
} else if (rbRevPortrait.isSameAs(source)) {
2200
asCurrent.add(OrientationRequested.REVERSE_PORTRAIT);
2201
} else if (rbRevLandscape.isSameAs(source)) {
2202
asCurrent.add(OrientationRequested.REVERSE_LANDSCAPE);
2203
}
2204
// orientation affects display of margins.
2205
if (pnlMargins != null) {
2206
pnlMargins.updateInfo();
2207
}
2208
}
2209
2210
/* This is ad hoc to keep things simple */
2211
void addOrientationListener(MarginsPanel pnl) {
2212
pnlMargins = pnl;
2213
}
2214
2215
public void updateInfo() {
2216
Class<OrientationRequested> orCategory = OrientationRequested.class;
2217
boolean pSupported = false;
2218
boolean lSupported = false;
2219
boolean rpSupported = false;
2220
boolean rlSupported = false;
2221
2222
if (isAWT) {
2223
pSupported = true;
2224
lSupported = true;
2225
} else
2226
if (psCurrent.isAttributeCategorySupported(orCategory)) {
2227
Object values =
2228
psCurrent.getSupportedAttributeValues(orCategory,
2229
docFlavor,
2230
asCurrent);
2231
2232
if (values instanceof OrientationRequested[]) {
2233
OrientationRequested[] ovalues =
2234
(OrientationRequested[])values;
2235
2236
for (int i = 0; i < ovalues.length; i++) {
2237
OrientationRequested value = ovalues[i];
2238
2239
if (value == OrientationRequested.PORTRAIT) {
2240
pSupported = true;
2241
} else if (value == OrientationRequested.LANDSCAPE) {
2242
lSupported = true;
2243
} else if (value == OrientationRequested.REVERSE_PORTRAIT) {
2244
rpSupported = true;
2245
} else if (value == OrientationRequested.REVERSE_LANDSCAPE) {
2246
rlSupported = true;
2247
}
2248
}
2249
}
2250
}
2251
2252
2253
rbPortrait.setEnabled(pSupported);
2254
rbLandscape.setEnabled(lSupported);
2255
rbRevPortrait.setEnabled(rpSupported);
2256
rbRevLandscape.setEnabled(rlSupported);
2257
2258
OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
2259
if (or == null ||
2260
!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
2261
2262
or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
2263
// need to validate if default is not supported
2264
if ((or != null) &&
2265
!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
2266
or = null;
2267
Object values =
2268
psCurrent.getSupportedAttributeValues(orCategory,
2269
docFlavor,
2270
asCurrent);
2271
if (values instanceof OrientationRequested[]) {
2272
OrientationRequested[] orValues =
2273
(OrientationRequested[])values;
2274
if (orValues.length > 1) {
2275
// get the first in the list
2276
or = orValues[0];
2277
}
2278
}
2279
}
2280
2281
if (or == null) {
2282
or = OrientationRequested.PORTRAIT;
2283
}
2284
asCurrent.add(or);
2285
}
2286
2287
if (or == OrientationRequested.PORTRAIT) {
2288
rbPortrait.setSelected(true);
2289
} else if (or == OrientationRequested.LANDSCAPE) {
2290
rbLandscape.setSelected(true);
2291
} else if (or == OrientationRequested.REVERSE_PORTRAIT) {
2292
rbRevPortrait.setSelected(true);
2293
} else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
2294
rbRevLandscape.setSelected(true);
2295
}
2296
}
2297
}
2298
2299
2300
2301
/**
2302
* The "Appearance" tab. Includes the controls for Chromaticity,
2303
* PrintQuality, JobPriority, JobName, and other related job attributes.
2304
*/
2305
@SuppressWarnings("serial") // Superclass is not serializable across versions
2306
private class AppearancePanel extends JPanel {
2307
2308
private ChromaticityPanel pnlChromaticity;
2309
private QualityPanel pnlQuality;
2310
private JobAttributesPanel pnlJobAttributes;
2311
private SidesPanel pnlSides;
2312
2313
public AppearancePanel() {
2314
super();
2315
2316
GridBagLayout gridbag = new GridBagLayout();
2317
GridBagConstraints c = new GridBagConstraints();
2318
2319
setLayout(gridbag);
2320
2321
c.fill = GridBagConstraints.BOTH;
2322
c.insets = panelInsets;
2323
c.weightx = 1.0;
2324
c.weighty = 1.0;
2325
2326
c.gridwidth = GridBagConstraints.RELATIVE;
2327
pnlChromaticity = new ChromaticityPanel();
2328
addToGB(pnlChromaticity, this, gridbag, c);
2329
2330
c.gridwidth = GridBagConstraints.REMAINDER;
2331
pnlQuality = new QualityPanel();
2332
addToGB(pnlQuality, this, gridbag, c);
2333
2334
c.gridwidth = 1;
2335
pnlSides = new SidesPanel();
2336
addToGB(pnlSides, this, gridbag, c);
2337
2338
c.gridwidth = GridBagConstraints.REMAINDER;
2339
pnlJobAttributes = new JobAttributesPanel();
2340
addToGB(pnlJobAttributes, this, gridbag, c);
2341
2342
}
2343
2344
public void updateInfo() {
2345
pnlChromaticity.updateInfo();
2346
pnlQuality.updateInfo();
2347
pnlSides.updateInfo();
2348
pnlJobAttributes.updateInfo();
2349
}
2350
}
2351
2352
@SuppressWarnings("serial") // Superclass is not serializable across versions
2353
private class ChromaticityPanel extends JPanel
2354
implements ActionListener
2355
{
2356
private final String strTitle = getMsg("border.chromaticity");
2357
private JRadioButton rbMonochrome, rbColor;
2358
2359
public ChromaticityPanel() {
2360
super();
2361
2362
GridBagLayout gridbag = new GridBagLayout();
2363
GridBagConstraints c = new GridBagConstraints();
2364
2365
setLayout(gridbag);
2366
setBorder(BorderFactory.createTitledBorder(strTitle));
2367
2368
c.fill = GridBagConstraints.BOTH;
2369
c.gridwidth = GridBagConstraints.REMAINDER;
2370
c.weighty = 1.0;
2371
2372
ButtonGroup bg = new ButtonGroup();
2373
rbMonochrome = createRadioButton("radiobutton.monochrome", this);
2374
rbMonochrome.setSelected(true);
2375
bg.add(rbMonochrome);
2376
addToGB(rbMonochrome, this, gridbag, c);
2377
rbColor = createRadioButton("radiobutton.color", this);
2378
bg.add(rbColor);
2379
addToGB(rbColor, this, gridbag, c);
2380
}
2381
2382
public void actionPerformed(ActionEvent e) {
2383
Object source = e.getSource();
2384
2385
// REMIND: use isSameAs if we move to a IconRB in the future
2386
if (source == rbMonochrome) {
2387
asCurrent.add(Chromaticity.MONOCHROME);
2388
} else if (source == rbColor) {
2389
asCurrent.add(Chromaticity.COLOR);
2390
}
2391
}
2392
2393
public void updateInfo() {
2394
Class<Chromaticity> chCategory = Chromaticity.class;
2395
boolean monoSupported = false;
2396
boolean colorSupported = false;
2397
2398
if (isAWT) {
2399
monoSupported = true;
2400
colorSupported = true;
2401
} else
2402
if (psCurrent.isAttributeCategorySupported(chCategory)) {
2403
Object values =
2404
psCurrent.getSupportedAttributeValues(chCategory,
2405
docFlavor,
2406
asCurrent);
2407
2408
if (values instanceof Chromaticity[]) {
2409
Chromaticity[] cvalues = (Chromaticity[])values;
2410
2411
for (int i = 0; i < cvalues.length; i++) {
2412
Chromaticity value = cvalues[i];
2413
2414
if (value == Chromaticity.MONOCHROME) {
2415
monoSupported = true;
2416
} else if (value == Chromaticity.COLOR) {
2417
colorSupported = true;
2418
}
2419
}
2420
}
2421
}
2422
2423
2424
rbMonochrome.setEnabled(monoSupported);
2425
rbColor.setEnabled(colorSupported);
2426
2427
Chromaticity ch = (Chromaticity)asCurrent.get(chCategory);
2428
if (ch == null) {
2429
ch = (Chromaticity)psCurrent.getDefaultAttributeValue(chCategory);
2430
if (ch == null) {
2431
ch = Chromaticity.MONOCHROME;
2432
}
2433
}
2434
2435
if (ch == Chromaticity.MONOCHROME) {
2436
rbMonochrome.setSelected(true);
2437
} else { // if (ch == Chromaticity.COLOR)
2438
rbColor.setSelected(true);
2439
}
2440
}
2441
}
2442
2443
@SuppressWarnings("serial") // Superclass is not serializable across versions
2444
private class QualityPanel extends JPanel
2445
implements ActionListener
2446
{
2447
private final String strTitle = getMsg("border.quality");
2448
private JRadioButton rbDraft, rbNormal, rbHigh;
2449
2450
public QualityPanel() {
2451
super();
2452
2453
GridBagLayout gridbag = new GridBagLayout();
2454
GridBagConstraints c = new GridBagConstraints();
2455
2456
setLayout(gridbag);
2457
setBorder(BorderFactory.createTitledBorder(strTitle));
2458
2459
c.fill = GridBagConstraints.BOTH;
2460
c.gridwidth = GridBagConstraints.REMAINDER;
2461
c.weighty = 1.0;
2462
2463
ButtonGroup bg = new ButtonGroup();
2464
rbDraft = createRadioButton("radiobutton.draftq", this);
2465
bg.add(rbDraft);
2466
addToGB(rbDraft, this, gridbag, c);
2467
rbNormal = createRadioButton("radiobutton.normalq", this);
2468
rbNormal.setSelected(true);
2469
bg.add(rbNormal);
2470
addToGB(rbNormal, this, gridbag, c);
2471
rbHigh = createRadioButton("radiobutton.highq", this);
2472
bg.add(rbHigh);
2473
addToGB(rbHigh, this, gridbag, c);
2474
}
2475
2476
public void actionPerformed(ActionEvent e) {
2477
Object source = e.getSource();
2478
2479
if (source == rbDraft) {
2480
asCurrent.add(PrintQuality.DRAFT);
2481
} else if (source == rbNormal) {
2482
asCurrent.add(PrintQuality.NORMAL);
2483
} else if (source == rbHigh) {
2484
asCurrent.add(PrintQuality.HIGH);
2485
}
2486
}
2487
2488
public void updateInfo() {
2489
Class<PrintQuality> pqCategory = PrintQuality.class;
2490
boolean draftSupported = false;
2491
boolean normalSupported = false;
2492
boolean highSupported = false;
2493
2494
if (isAWT) {
2495
draftSupported = true;
2496
normalSupported = true;
2497
highSupported = true;
2498
} else
2499
if (psCurrent.isAttributeCategorySupported(pqCategory)) {
2500
Object values =
2501
psCurrent.getSupportedAttributeValues(pqCategory,
2502
docFlavor,
2503
asCurrent);
2504
2505
if (values instanceof PrintQuality[]) {
2506
PrintQuality[] qvalues = (PrintQuality[])values;
2507
2508
for (int i = 0; i < qvalues.length; i++) {
2509
PrintQuality value = qvalues[i];
2510
2511
if (value == PrintQuality.DRAFT) {
2512
draftSupported = true;
2513
} else if (value == PrintQuality.NORMAL) {
2514
normalSupported = true;
2515
} else if (value == PrintQuality.HIGH) {
2516
highSupported = true;
2517
}
2518
}
2519
}
2520
}
2521
2522
rbDraft.setEnabled(draftSupported);
2523
rbNormal.setEnabled(normalSupported);
2524
rbHigh.setEnabled(highSupported);
2525
2526
PrintQuality pq = (PrintQuality)asCurrent.get(pqCategory);
2527
if (pq == null) {
2528
pq = (PrintQuality)psCurrent.getDefaultAttributeValue(pqCategory);
2529
if (pq == null) {
2530
pq = PrintQuality.NORMAL;
2531
}
2532
}
2533
2534
if (pq == PrintQuality.DRAFT) {
2535
rbDraft.setSelected(true);
2536
} else if (pq == PrintQuality.NORMAL) {
2537
rbNormal.setSelected(true);
2538
} else { // if (pq == PrintQuality.HIGH)
2539
rbHigh.setSelected(true);
2540
}
2541
}
2542
2543
2544
}
2545
2546
@SuppressWarnings("serial") // Superclass is not serializable across versions
2547
private class SidesPanel extends JPanel
2548
implements ActionListener
2549
{
2550
private final String strTitle = getMsg("border.sides");
2551
private IconRadioButton rbOneSide, rbTumble, rbDuplex;
2552
2553
public SidesPanel() {
2554
super();
2555
2556
GridBagLayout gridbag = new GridBagLayout();
2557
GridBagConstraints c = new GridBagConstraints();
2558
2559
setLayout(gridbag);
2560
setBorder(BorderFactory.createTitledBorder(strTitle));
2561
2562
c.fill = GridBagConstraints.BOTH;
2563
c.insets = compInsets;
2564
c.weighty = 1.0;
2565
c.gridwidth = GridBagConstraints.REMAINDER;
2566
2567
ButtonGroup bg = new ButtonGroup();
2568
rbOneSide = new IconRadioButton("radiobutton.oneside",
2569
"oneside.png", true,
2570
bg, this);
2571
rbOneSide.addActionListener(this);
2572
addToGB(rbOneSide, this, gridbag, c);
2573
rbTumble = new IconRadioButton("radiobutton.tumble",
2574
"tumble.png", false,
2575
bg, this);
2576
rbTumble.addActionListener(this);
2577
addToGB(rbTumble, this, gridbag, c);
2578
rbDuplex = new IconRadioButton("radiobutton.duplex",
2579
"duplex.png", false,
2580
bg, this);
2581
rbDuplex.addActionListener(this);
2582
c.gridwidth = GridBagConstraints.REMAINDER;
2583
addToGB(rbDuplex, this, gridbag, c);
2584
}
2585
2586
public void actionPerformed(ActionEvent e) {
2587
Object source = e.getSource();
2588
2589
if (rbOneSide.isSameAs(source)) {
2590
asCurrent.add(Sides.ONE_SIDED);
2591
} else if (rbTumble.isSameAs(source)) {
2592
asCurrent.add(Sides.TUMBLE);
2593
} else if (rbDuplex.isSameAs(source)) {
2594
asCurrent.add(Sides.DUPLEX);
2595
}
2596
}
2597
2598
public void updateInfo() {
2599
Class<Sides> sdCategory = Sides.class;
2600
boolean osSupported = false;
2601
boolean tSupported = false;
2602
boolean dSupported = false;
2603
2604
if (psCurrent.isAttributeCategorySupported(sdCategory)) {
2605
Object values =
2606
psCurrent.getSupportedAttributeValues(sdCategory,
2607
docFlavor,
2608
asCurrent);
2609
2610
if (values instanceof Sides[]) {
2611
Sides[] svalues = (Sides[])values;
2612
2613
for (int i = 0; i < svalues.length; i++) {
2614
Sides value = svalues[i];
2615
2616
if (value == Sides.ONE_SIDED) {
2617
osSupported = true;
2618
} else if (value == Sides.TUMBLE) {
2619
tSupported = true;
2620
} else if (value == Sides.DUPLEX) {
2621
dSupported = true;
2622
}
2623
}
2624
}
2625
}
2626
rbOneSide.setEnabled(osSupported);
2627
rbTumble.setEnabled(tSupported);
2628
rbDuplex.setEnabled(dSupported);
2629
2630
Sides sd = (Sides)asCurrent.get(sdCategory);
2631
if (sd == null) {
2632
sd = (Sides)psCurrent.getDefaultAttributeValue(sdCategory);
2633
if (sd == null) {
2634
sd = Sides.ONE_SIDED;
2635
}
2636
}
2637
2638
if (sd == Sides.ONE_SIDED) {
2639
rbOneSide.setSelected(true);
2640
} else if (sd == Sides.TUMBLE) {
2641
rbTumble.setSelected(true);
2642
} else { // if (sd == Sides.DUPLEX)
2643
rbDuplex.setSelected(true);
2644
}
2645
}
2646
}
2647
2648
2649
@SuppressWarnings("serial") // Superclass is not serializable across versions
2650
private class JobAttributesPanel extends JPanel
2651
implements ActionListener, ChangeListener, FocusListener
2652
{
2653
private final String strTitle = getMsg("border.jobattributes");
2654
private JLabel lblPriority, lblJobName, lblUserName;
2655
private JSpinner spinPriority;
2656
private SpinnerNumberModel snModel;
2657
private JCheckBox cbJobSheets;
2658
private JTextField tfJobName, tfUserName;
2659
2660
public JobAttributesPanel() {
2661
super();
2662
2663
GridBagLayout gridbag = new GridBagLayout();
2664
GridBagConstraints c = new GridBagConstraints();
2665
2666
setLayout(gridbag);
2667
setBorder(BorderFactory.createTitledBorder(strTitle));
2668
2669
c.fill = GridBagConstraints.NONE;
2670
c.insets = compInsets;
2671
c.weighty = 1.0;
2672
2673
cbJobSheets = createCheckBox("checkbox.jobsheets", this);
2674
c.anchor = GridBagConstraints.LINE_START;
2675
addToGB(cbJobSheets, this, gridbag, c);
2676
2677
JPanel pnlTop = new JPanel();
2678
lblPriority = new JLabel(getMsg("label.priority"), JLabel.TRAILING);
2679
lblPriority.setDisplayedMnemonic(getMnemonic("label.priority"));
2680
2681
pnlTop.add(lblPriority);
2682
snModel = new SpinnerNumberModel(1, 1, 100, 1);
2683
spinPriority = new JSpinner(snModel);
2684
lblPriority.setLabelFor(spinPriority);
2685
// REMIND
2686
((JSpinner.NumberEditor)spinPriority.getEditor()).getTextField().setColumns(3);
2687
spinPriority.addChangeListener(this);
2688
pnlTop.add(spinPriority);
2689
c.anchor = GridBagConstraints.LINE_END;
2690
c.gridwidth = GridBagConstraints.REMAINDER;
2691
pnlTop.getAccessibleContext().setAccessibleName(
2692
getMsg("label.priority"));
2693
addToGB(pnlTop, this, gridbag, c);
2694
2695
c.fill = GridBagConstraints.HORIZONTAL;
2696
c.anchor = GridBagConstraints.CENTER;
2697
c.weightx = 0.0;
2698
c.gridwidth = 1;
2699
char jmnemonic = getMnemonic("label.jobname");
2700
lblJobName = new JLabel(getMsg("label.jobname"), JLabel.TRAILING);
2701
lblJobName.setDisplayedMnemonic(jmnemonic);
2702
addToGB(lblJobName, this, gridbag, c);
2703
c.weightx = 1.0;
2704
c.gridwidth = GridBagConstraints.REMAINDER;
2705
tfJobName = new JTextField();
2706
lblJobName.setLabelFor(tfJobName);
2707
tfJobName.addFocusListener(this);
2708
tfJobName.setFocusAccelerator(jmnemonic);
2709
tfJobName.getAccessibleContext().setAccessibleName(
2710
getMsg("label.jobname"));
2711
addToGB(tfJobName, this, gridbag, c);
2712
2713
c.weightx = 0.0;
2714
c.gridwidth = 1;
2715
char umnemonic = getMnemonic("label.username");
2716
lblUserName = new JLabel(getMsg("label.username"), JLabel.TRAILING);
2717
lblUserName.setDisplayedMnemonic(umnemonic);
2718
addToGB(lblUserName, this, gridbag, c);
2719
c.gridwidth = GridBagConstraints.REMAINDER;
2720
tfUserName = new JTextField();
2721
lblUserName.setLabelFor(tfUserName);
2722
tfUserName.addFocusListener(this);
2723
tfUserName.setFocusAccelerator(umnemonic);
2724
tfUserName.getAccessibleContext().setAccessibleName(
2725
getMsg("label.username"));
2726
addToGB(tfUserName, this, gridbag, c);
2727
}
2728
2729
public void actionPerformed(ActionEvent e) {
2730
if (cbJobSheets.isSelected()) {
2731
asCurrent.add(JobSheets.STANDARD);
2732
} else {
2733
asCurrent.add(JobSheets.NONE);
2734
}
2735
}
2736
2737
public void stateChanged(ChangeEvent e) {
2738
asCurrent.add(new JobPriority(snModel.getNumber().intValue()));
2739
}
2740
2741
public void focusLost(FocusEvent e) {
2742
Object source = e.getSource();
2743
2744
if (source == tfJobName) {
2745
asCurrent.add(new JobName(tfJobName.getText(),
2746
Locale.getDefault()));
2747
} else if (source == tfUserName) {
2748
asCurrent.add(new RequestingUserName(tfUserName.getText(),
2749
Locale.getDefault()));
2750
}
2751
}
2752
2753
public void focusGained(FocusEvent e) {}
2754
2755
public void updateInfo() {
2756
Class<JobSheets> jsCategory = JobSheets.class;
2757
Class<JobPriority> jpCategory = JobPriority.class;
2758
Class<JobName> jnCategory = JobName.class;
2759
Class<RequestingUserName> unCategory = RequestingUserName.class;
2760
boolean jsSupported = false;
2761
boolean jpSupported = false;
2762
boolean jnSupported = false;
2763
boolean unSupported = false;
2764
2765
// setup JobSheets checkbox
2766
if (psCurrent.isAttributeCategorySupported(jsCategory)) {
2767
jsSupported = true;
2768
}
2769
JobSheets js = (JobSheets)asCurrent.get(jsCategory);
2770
if (js == null) {
2771
js = (JobSheets)psCurrent.getDefaultAttributeValue(jsCategory);
2772
if (js == null) {
2773
js = JobSheets.STANDARD;
2774
}
2775
}
2776
cbJobSheets.setSelected(js != JobSheets.NONE && jsSupported);
2777
cbJobSheets.setEnabled(jsSupported);
2778
2779
// setup JobPriority spinner
2780
if (!isAWT && psCurrent.isAttributeCategorySupported(jpCategory)) {
2781
jpSupported = true;
2782
}
2783
JobPriority jp = (JobPriority)asCurrent.get(jpCategory);
2784
if (jp == null) {
2785
jp = (JobPriority)psCurrent.getDefaultAttributeValue(jpCategory);
2786
if (jp == null) {
2787
jp = new JobPriority(1);
2788
}
2789
}
2790
int value = jp.getValue();
2791
if ((value < 1) || (value > 100)) {
2792
value = 1;
2793
}
2794
snModel.setValue(value);
2795
lblPriority.setEnabled(jpSupported);
2796
spinPriority.setEnabled(jpSupported);
2797
2798
// setup JobName text field
2799
if (psCurrent.isAttributeCategorySupported(jnCategory)) {
2800
jnSupported = true;
2801
}
2802
JobName jn = (JobName)asCurrent.get(jnCategory);
2803
if (jn == null) {
2804
jn = (JobName)psCurrent.getDefaultAttributeValue(jnCategory);
2805
if (jn == null) {
2806
jn = new JobName("", Locale.getDefault());
2807
}
2808
}
2809
tfJobName.setText(jn.getValue());
2810
tfJobName.setEnabled(jnSupported);
2811
lblJobName.setEnabled(jnSupported);
2812
2813
// setup RequestingUserName text field
2814
if (!isAWT && psCurrent.isAttributeCategorySupported(unCategory)) {
2815
unSupported = true;
2816
}
2817
RequestingUserName un = (RequestingUserName)asCurrent.get(unCategory);
2818
if (un == null) {
2819
un = (RequestingUserName)psCurrent.getDefaultAttributeValue(unCategory);
2820
if (un == null) {
2821
un = new RequestingUserName("", Locale.getDefault());
2822
}
2823
}
2824
tfUserName.setText(un.getValue());
2825
tfUserName.setEnabled(unSupported);
2826
lblUserName.setEnabled(unSupported);
2827
}
2828
}
2829
2830
2831
2832
2833
/**
2834
* A special widget that groups a JRadioButton with an associated icon,
2835
* placed to the left of the radio button.
2836
*/
2837
@SuppressWarnings("serial") // Superclass is not serializable across versions
2838
private class IconRadioButton extends JPanel {
2839
2840
private JRadioButton rb;
2841
private JLabel lbl;
2842
2843
public IconRadioButton(String key, String img, boolean selected,
2844
ButtonGroup bg, ActionListener al)
2845
{
2846
super(new FlowLayout(FlowLayout.LEADING));
2847
final URL imgURL = getImageResource(img);
2848
@SuppressWarnings("removal")
2849
Icon icon = java.security.AccessController.doPrivileged(
2850
new java.security.PrivilegedAction<Icon>() {
2851
public Icon run() {
2852
Icon icon = new ImageIcon(imgURL);
2853
return icon;
2854
}
2855
});
2856
lbl = new JLabel(icon);
2857
add(lbl);
2858
2859
rb = createRadioButton(key, al);
2860
rb.setSelected(selected);
2861
addToBG(rb, this, bg);
2862
}
2863
2864
public void addActionListener(ActionListener al) {
2865
rb.addActionListener(al);
2866
}
2867
2868
public boolean isSameAs(Object source) {
2869
return (rb == source);
2870
}
2871
2872
public void setEnabled(boolean enabled) {
2873
rb.setEnabled(enabled);
2874
lbl.setEnabled(enabled);
2875
}
2876
2877
public boolean isSelected() {
2878
return rb.isSelected();
2879
}
2880
2881
public void setSelected(boolean selected) {
2882
rb.setSelected(selected);
2883
}
2884
}
2885
2886
/**
2887
* Similar in functionality to the default JFileChooser, except this
2888
* chooser will pop up a "Do you want to overwrite..." dialog if the
2889
* user selects a file that already exists.
2890
*/
2891
@SuppressWarnings("serial") // JDK implementation class
2892
private class ValidatingFileChooser extends JFileChooser {
2893
public void approveSelection() {
2894
File selected = getSelectedFile();
2895
boolean exists;
2896
2897
try {
2898
exists = selected.exists();
2899
} catch (SecurityException e) {
2900
exists = false;
2901
}
2902
2903
if (exists) {
2904
int val;
2905
val = JOptionPane.showConfirmDialog(this,
2906
getMsg("dialog.overwrite"),
2907
getMsg("dialog.owtitle"),
2908
JOptionPane.YES_NO_OPTION);
2909
if (val != JOptionPane.YES_OPTION) {
2910
return;
2911
}
2912
}
2913
2914
try {
2915
if (selected.createNewFile()) {
2916
selected.delete();
2917
}
2918
} catch (IOException ioe) {
2919
JOptionPane.showMessageDialog(this,
2920
getMsg("dialog.writeerror")+" "+selected,
2921
getMsg("dialog.owtitle"),
2922
JOptionPane.WARNING_MESSAGE);
2923
return;
2924
} catch (SecurityException se) {
2925
//There is already file read/write access so at this point
2926
// only delete access is denied. Just ignore it because in
2927
// most cases the file created in createNewFile gets
2928
// overwritten anyway.
2929
}
2930
File pFile = selected.getParentFile();
2931
if ((selected.exists() &&
2932
(!selected.isFile() || !selected.canWrite())) ||
2933
((pFile != null) &&
2934
(!pFile.exists() || (pFile.exists() && !pFile.canWrite())))) {
2935
JOptionPane.showMessageDialog(this,
2936
getMsg("dialog.writeerror")+" "+selected,
2937
getMsg("dialog.owtitle"),
2938
JOptionPane.WARNING_MESSAGE);
2939
return;
2940
}
2941
2942
super.approveSelection();
2943
}
2944
}
2945
}
2946
2947