mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
2503 lines
89 KiB
Java
2503 lines
89 KiB
Java
/*
|
|
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
|
|
*/
|
|
|
|
/*
|
|
* @(#)ServiceDialog.java 1.16 03/01/23
|
|
*
|
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
|
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
|
|
package sun.print;
|
|
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Container;
|
|
import java.awt.Dialog;
|
|
import java.awt.FlowLayout;
|
|
import java.awt.Frame;
|
|
import java.awt.GraphicsConfiguration;
|
|
import java.awt.GridBagLayout;
|
|
import java.awt.GridBagConstraints;
|
|
import java.awt.GridLayout;
|
|
import java.awt.Insets;
|
|
import java.awt.Toolkit;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.FocusEvent;
|
|
import java.awt.event.FocusListener;
|
|
import java.awt.event.ItemEvent;
|
|
import java.awt.event.ItemListener;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.event.WindowAdapter;
|
|
import java.io.File;
|
|
import java.io.FilePermission;
|
|
import java.net.URI;
|
|
import java.net.URL;
|
|
import java.text.DecimalFormat;
|
|
import java.util.Locale;
|
|
import java.util.ResourceBundle;
|
|
import java.util.Vector;
|
|
import javax.print.*;
|
|
import javax.print.attribute.*;
|
|
import javax.print.attribute.standard.*;
|
|
import javax.swing.*;
|
|
import javax.swing.border.Border;
|
|
import javax.swing.border.EmptyBorder;
|
|
import javax.swing.border.TitledBorder;
|
|
import javax.swing.event.ChangeEvent;
|
|
import javax.swing.event.ChangeListener;
|
|
import javax.swing.event.DocumentEvent;
|
|
import javax.swing.event.DocumentListener;
|
|
import javax.swing.event.PopupMenuEvent;
|
|
import javax.swing.event.PopupMenuListener;
|
|
import javax.swing.text.NumberFormatter;
|
|
|
|
|
|
/**
|
|
* A class which implements a cross-platform print dialog.
|
|
*
|
|
* @version 1.4 02/03/01
|
|
* @author Chris Campbell
|
|
*/
|
|
public class ServiceDialog extends JDialog implements ActionListener {
|
|
|
|
/**
|
|
* Waiting print status (user response pending).
|
|
*/
|
|
public final static int WAITING = 0;
|
|
|
|
/**
|
|
* Approve print status (user activated "Print" or "OK").
|
|
*/
|
|
public final static int APPROVE = 1;
|
|
|
|
/**
|
|
* Cancel print status (user activated "Cancel");
|
|
*/
|
|
public final static int CANCEL = 2;
|
|
|
|
private static final String strBundle = "sun.print.resources.serviceui";
|
|
private static final Insets panelInsets = new Insets(6, 6, 6, 6);
|
|
private static final Insets compInsets = new Insets(3, 6, 3, 6);
|
|
|
|
private static ResourceBundle messageRB;
|
|
private JTabbedPane tpTabs;
|
|
private JButton btnCancel, btnApprove;
|
|
private PrintService[] services;
|
|
private int defaultServiceIndex;
|
|
private PrintRequestAttributeSet asOriginal;
|
|
private HashPrintRequestAttributeSet asCurrent;
|
|
private PrintService psCurrent;
|
|
private DocFlavor docFlavor;
|
|
private int status;
|
|
|
|
private ValidatingFileChooser jfc;
|
|
|
|
private GeneralPanel pnlGeneral;
|
|
private PageSetupPanel pnlPageSetup;
|
|
private AppearancePanel pnlAppearance;
|
|
|
|
static {
|
|
initResource();
|
|
}
|
|
|
|
/**
|
|
* Constructor for the "standard" print dialog (containing all relevant
|
|
* tabs)
|
|
*/
|
|
public ServiceDialog(GraphicsConfiguration gc,
|
|
int x, int y,
|
|
PrintService[] services,
|
|
int defaultServiceIndex,
|
|
DocFlavor flavor,
|
|
PrintRequestAttributeSet attributes, Dialog dialog)
|
|
{
|
|
super(dialog, getMsg("dialog.printtitle"), true, gc);
|
|
initPrintDialog(x, y, services, defaultServiceIndex, flavor, attributes);
|
|
}
|
|
|
|
public ServiceDialog(GraphicsConfiguration gc,
|
|
int x, int y,
|
|
PrintService[] services,
|
|
int defaultServiceIndex,
|
|
DocFlavor flavor,
|
|
PrintRequestAttributeSet attributes, Frame frame)
|
|
{
|
|
super(frame, getMsg("dialog.printtitle"), true, gc);
|
|
initPrintDialog(x, y, services, defaultServiceIndex, flavor, attributes);
|
|
}
|
|
|
|
void initPrintDialog(int x, int y, PrintService[] services,
|
|
int defaultServiceIndex, DocFlavor flavor,
|
|
PrintRequestAttributeSet attributes) {
|
|
this.services = services;
|
|
this.defaultServiceIndex = defaultServiceIndex;
|
|
this.asOriginal = attributes;
|
|
this.asCurrent = new HashPrintRequestAttributeSet(attributes);
|
|
this.psCurrent = services[defaultServiceIndex];
|
|
this.docFlavor = flavor;
|
|
|
|
Container c = getContentPane();
|
|
c.setLayout(new BorderLayout());
|
|
|
|
tpTabs = new JTabbedPane();
|
|
tpTabs.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
|
|
String gkey = getMsg("tab.general");
|
|
int gmnemonic = getVKMnemonic("tab.general");
|
|
pnlGeneral = new GeneralPanel();
|
|
tpTabs.add(gkey, pnlGeneral);
|
|
tpTabs.setMnemonicAt(0, gmnemonic);
|
|
|
|
String pkey = getMsg("tab.pagesetup");
|
|
int pmnemonic = getVKMnemonic("tab.pagesetup");
|
|
pnlPageSetup = new PageSetupPanel();
|
|
tpTabs.add(pkey, pnlPageSetup);
|
|
tpTabs.setMnemonicAt(1, pmnemonic);
|
|
|
|
String akey = getMsg("tab.appearance");
|
|
int amnemonic = getVKMnemonic("tab.appearance");
|
|
pnlAppearance = new AppearancePanel();
|
|
tpTabs.add(akey, pnlAppearance);
|
|
tpTabs.setMnemonicAt(2, amnemonic);
|
|
|
|
c.add(tpTabs, BorderLayout.CENTER);
|
|
|
|
updatePanels();
|
|
|
|
JPanel pnlSouth = new JPanel(new FlowLayout(FlowLayout.TRAILING));
|
|
btnApprove = createButton("button.print", this);
|
|
pnlSouth.add(btnApprove);
|
|
btnCancel = createButton("button.cancel", this);
|
|
pnlSouth.add(btnCancel);
|
|
c.add(pnlSouth, BorderLayout.SOUTH);
|
|
|
|
addWindowListener(new WindowAdapter() {
|
|
public void windowClosing(WindowEvent event) {
|
|
dispose(CANCEL);
|
|
}
|
|
});
|
|
|
|
setResizable(false);
|
|
setLocation(x, y);
|
|
pack();
|
|
}
|
|
|
|
/**
|
|
* Constructor for the solitary "page setup" dialog
|
|
*/
|
|
public ServiceDialog(GraphicsConfiguration gc,
|
|
int x, int y,
|
|
PrintService ps,
|
|
DocFlavor flavor,
|
|
PrintRequestAttributeSet attributes, Dialog dialog)
|
|
{
|
|
super(dialog, getMsg("dialog.pstitle"), true, gc);
|
|
initPageDialog(x, y, ps, flavor, attributes);
|
|
}
|
|
|
|
public ServiceDialog(GraphicsConfiguration gc,
|
|
int x, int y,
|
|
PrintService ps,
|
|
DocFlavor flavor,
|
|
PrintRequestAttributeSet attributes, Frame frame)
|
|
{
|
|
super(frame, getMsg("dialog.pstitle"), true, gc);
|
|
initPageDialog(x, y, ps, flavor, attributes);
|
|
}
|
|
|
|
void initPageDialog(int x, int y, PrintService ps,
|
|
DocFlavor flavor, PrintRequestAttributeSet attributes) {
|
|
this.psCurrent = ps;
|
|
this.docFlavor = flavor;
|
|
this.asOriginal = attributes;
|
|
this.asCurrent = new HashPrintRequestAttributeSet(attributes);
|
|
|
|
Container c = getContentPane();
|
|
c.setLayout(new BorderLayout());
|
|
|
|
pnlPageSetup = new PageSetupPanel();
|
|
c.add(pnlPageSetup, BorderLayout.CENTER);
|
|
|
|
pnlPageSetup.updateInfo();
|
|
|
|
JPanel pnlSouth = new JPanel(new FlowLayout(FlowLayout.TRAILING));
|
|
btnApprove = createButton("button.ok", this);
|
|
pnlSouth.add(btnApprove);
|
|
btnCancel = createButton("button.cancel", this);
|
|
pnlSouth.add(btnCancel);
|
|
c.add(pnlSouth, BorderLayout.SOUTH);
|
|
|
|
addWindowListener(new WindowAdapter() {
|
|
public void windowClosing(WindowEvent event) {
|
|
dispose(CANCEL);
|
|
}
|
|
});
|
|
|
|
setResizable(false);
|
|
setLocation(x, y);
|
|
pack();
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the current status of the dialog (whether the user has selected
|
|
* the "Print" or "Cancel" button)
|
|
*/
|
|
public int getStatus() {
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Returns an AttributeSet based on whether or not the user cancelled the
|
|
* dialog. If the user selected "Print" we return their new selections,
|
|
* otherwise we return the attributes that were passed in initially.
|
|
*/
|
|
public PrintRequestAttributeSet getAttributes() {
|
|
if (status == APPROVE) {
|
|
return asCurrent;
|
|
} else {
|
|
return asOriginal;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a PrintService based on whether or not the user cancelled the
|
|
* dialog. If the user selected "Print" we return the user's selection
|
|
* for the PrintService, otherwise we return null.
|
|
*/
|
|
public PrintService getPrintService() {
|
|
if (status == APPROVE) {
|
|
return psCurrent;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the current status flag for the dialog and disposes it (thus
|
|
* returning control of the parent frame back to the user)
|
|
*/
|
|
public void dispose(int status) {
|
|
this.status = status;
|
|
|
|
super.dispose();
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
boolean approved = false;
|
|
|
|
if (source == btnApprove) {
|
|
approved = true;
|
|
|
|
if (pnlGeneral != null) {
|
|
if (pnlGeneral.isPrintToFileSelected()) {
|
|
approved = showFileChooser();
|
|
} else {
|
|
asCurrent.remove(Destination.class);
|
|
}
|
|
}
|
|
}
|
|
|
|
dispose(approved ? APPROVE : CANCEL);
|
|
}
|
|
|
|
/**
|
|
* Displays a JFileChooser that allows the user to select the destination
|
|
* for "Print To File"
|
|
*/
|
|
private boolean showFileChooser() {
|
|
Class dstCategory = Destination.class;
|
|
|
|
Destination dst = (Destination)asCurrent.get(dstCategory);
|
|
if (dst == null) {
|
|
dst = (Destination)psCurrent.getDefaultAttributeValue(dstCategory);
|
|
if (dst == null) {
|
|
dst = new Destination((new File("out.prn")).toURI());
|
|
}
|
|
}
|
|
|
|
File fileDest;
|
|
if (dst != null) {
|
|
try {
|
|
fileDest = new File(dst.getURI());
|
|
} catch (Exception e) {
|
|
// all manner of runtime exceptions possible
|
|
fileDest = new File("out.prn");
|
|
}
|
|
} else {
|
|
fileDest = new File("out.prn");
|
|
}
|
|
|
|
ValidatingFileChooser jfc = new ValidatingFileChooser();
|
|
jfc.setApproveButtonText(getMsg("button.ok"));
|
|
jfc.setApproveButtonMnemonic(getMnemonic("button.ok"));
|
|
jfc.setDialogTitle(getMsg("dialog.printtofile"));
|
|
jfc.setSelectedFile(fileDest);
|
|
|
|
int returnVal = jfc.showDialog(this, null);
|
|
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
|
fileDest = jfc.getSelectedFile();
|
|
|
|
try {
|
|
asCurrent.add(new Destination(fileDest.toURI()));
|
|
} catch (Exception e) {
|
|
asCurrent.remove(dstCategory);
|
|
}
|
|
} else {
|
|
asCurrent.remove(dstCategory);
|
|
}
|
|
|
|
return (returnVal == JFileChooser.APPROVE_OPTION);
|
|
}
|
|
|
|
/**
|
|
* Updates each of the top level panels
|
|
*/
|
|
private void updatePanels() {
|
|
pnlGeneral.updateInfo();
|
|
pnlPageSetup.updateInfo();
|
|
pnlAppearance.updateInfo();
|
|
}
|
|
|
|
/**
|
|
* Initialize ResourceBundle
|
|
*/
|
|
private static void initResource() {
|
|
java.security.AccessController.doPrivileged(
|
|
new java.security.PrivilegedAction() {
|
|
public Object run() {
|
|
try {
|
|
messageRB = ResourceBundle.getBundle(strBundle);
|
|
return null;
|
|
} catch (java.util.MissingResourceException e) {
|
|
throw new Error("Fatal: Resource for ServiceUI " +
|
|
"is missing");
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns message string from resource
|
|
*/
|
|
private static String getMsg(String key) {
|
|
try {
|
|
return messageRB.getString(key);
|
|
} catch (java.util.MissingResourceException e) {
|
|
throw new Error("Fatal: Resource for ServiceUI is broken; " +
|
|
"there is no " + key + " key in resource");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns mnemonic character from resource
|
|
*/
|
|
private static char getMnemonic(String key) {
|
|
String str = getMsg(key + ".mnemonic");
|
|
if ((str != null) && (str.length() > 0)) {
|
|
return str.charAt(0);
|
|
} else {
|
|
return (char)0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the mnemonic as a KeyEvent.VK constant from the resource.
|
|
*/
|
|
private static int getVKMnemonic(String key) {
|
|
String str = getMsg(key + ".vkMnemonic");
|
|
if ((str != null) && (str.length() > 0)) {
|
|
try {
|
|
return Integer.parseInt(str);
|
|
} catch (NumberFormatException nfe) {}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Returns URL for image resource
|
|
*/
|
|
private static URL getImageResource(String key) {
|
|
URL url = ServiceDialog.class.getResource("resources/" + key);
|
|
|
|
if (url == null) {
|
|
throw new Error("Fatal: Resource for ServiceUI is broken; " +
|
|
"there is no " + key + " key in resource");
|
|
}
|
|
|
|
return url;
|
|
}
|
|
|
|
/**
|
|
* Creates a new JButton and sets its text, mnemonic, and ActionListener
|
|
*/
|
|
private static JButton createButton(String key, ActionListener al) {
|
|
JButton btn = new JButton(getMsg(key));
|
|
btn.setMnemonic(getMnemonic(key));
|
|
btn.addActionListener(al);
|
|
|
|
return btn;
|
|
}
|
|
|
|
/**
|
|
* Creates a new JCheckBox and sets its text, mnemonic, and ActionListener
|
|
*/
|
|
private static JCheckBox createCheckBox(String key, ActionListener al) {
|
|
JCheckBox cb = new JCheckBox(getMsg(key));
|
|
cb.setMnemonic(getMnemonic(key));
|
|
cb.addActionListener(al);
|
|
|
|
return cb;
|
|
}
|
|
|
|
/**
|
|
* Creates a new JRadioButton and sets its text, mnemonic,
|
|
* and ActionListener
|
|
*/
|
|
private static JRadioButton createRadioButton(String key,
|
|
ActionListener al)
|
|
{
|
|
JRadioButton rb = new JRadioButton(getMsg(key));
|
|
rb.setMnemonic(getMnemonic(key));
|
|
rb.addActionListener(al);
|
|
|
|
return rb;
|
|
}
|
|
|
|
/**
|
|
* Creates a pop-up dialog for "no print service"
|
|
*/
|
|
public static void showNoPrintService(GraphicsConfiguration gc)
|
|
{
|
|
JOptionPane.showMessageDialog(new Frame(gc),
|
|
getMsg("dialog.noprintermsg"));
|
|
}
|
|
|
|
/**
|
|
* Sets the constraints for the GridBagLayout and adds the Component
|
|
* to the given Container
|
|
*/
|
|
private static void addToGB(Component comp, Container cont,
|
|
GridBagLayout gridbag,
|
|
GridBagConstraints constraints)
|
|
{
|
|
gridbag.setConstraints(comp, constraints);
|
|
cont.add(comp);
|
|
}
|
|
|
|
/**
|
|
* Adds the AbstractButton to both the given ButtonGroup and Container
|
|
*/
|
|
private static void addToBG(AbstractButton button, Container cont,
|
|
ButtonGroup bg)
|
|
{
|
|
bg.add(button);
|
|
cont.add(button);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* The "General" tab. Includes the controls for PrintService,
|
|
* PageRange, and Copies/Collate.
|
|
*/
|
|
private class GeneralPanel extends JPanel {
|
|
|
|
private PrintServicePanel pnlPrintService;
|
|
private PrintRangePanel pnlPrintRange;
|
|
private CopiesPanel pnlCopies;
|
|
|
|
public GeneralPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = panelInsets;
|
|
c.weightx = 1.0;
|
|
c.weighty = 1.0;
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
pnlPrintService = new PrintServicePanel();
|
|
addToGB(pnlPrintService, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
pnlPrintRange = new PrintRangePanel();
|
|
addToGB(pnlPrintRange, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
pnlCopies = new CopiesPanel();
|
|
addToGB(pnlCopies, this, gridbag, c);
|
|
}
|
|
|
|
public boolean isPrintToFileSelected() {
|
|
return pnlPrintService.isPrintToFileSelected();
|
|
}
|
|
|
|
public void updateInfo() {
|
|
pnlPrintService.updateInfo();
|
|
pnlPrintRange.updateInfo();
|
|
pnlCopies.updateInfo();
|
|
}
|
|
}
|
|
|
|
private class PrintServicePanel extends JPanel
|
|
implements ActionListener, ItemListener, PopupMenuListener
|
|
{
|
|
private final String strTitle = getMsg("border.printservice");
|
|
private FilePermission printToFilePermission;
|
|
private JButton btnProperties;
|
|
private JCheckBox cbPrintToFile;
|
|
private JComboBox cbName;
|
|
private JLabel lblType, lblStatus, lblInfo;
|
|
private ServiceUIFactory uiFactory;
|
|
private boolean changedService = false;
|
|
|
|
public PrintServicePanel() {
|
|
super();
|
|
|
|
uiFactory = psCurrent.getServiceUIFactory();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
String[] psnames = new String[services.length];
|
|
for (int i = 0; i < psnames.length; i++) {
|
|
psnames[i] = services[i].getName();
|
|
}
|
|
cbName = new JComboBox(psnames);
|
|
cbName.setSelectedIndex(defaultServiceIndex);
|
|
cbName.addItemListener(this);
|
|
cbName.addPopupMenuListener(this);
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = compInsets;
|
|
|
|
c.weightx = 0.0;
|
|
JLabel lblName = new JLabel(getMsg("label.psname"), JLabel.TRAILING);
|
|
lblName.setDisplayedMnemonic(getMnemonic("label.psname"));
|
|
lblName.setLabelFor(cbName);
|
|
addToGB(lblName, this, gridbag, c);
|
|
c.weightx = 1.0;
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
addToGB(cbName, this, gridbag, c);
|
|
c.weightx = 0.0;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
btnProperties = createButton("button.properties", this);
|
|
addToGB(btnProperties, this, gridbag, c);
|
|
|
|
c.weighty = 1.0;
|
|
lblStatus = addLabel(getMsg("label.status"), gridbag, c);
|
|
lblType = addLabel(getMsg("label.pstype"), gridbag, c);
|
|
|
|
c.gridwidth = 1;
|
|
addToGB(new JLabel(getMsg("label.info"), JLabel.TRAILING),
|
|
this, gridbag, c);
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
lblInfo = new JLabel();
|
|
lblInfo.setForeground(Color.black);
|
|
addToGB(lblInfo, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
cbPrintToFile = createCheckBox("checkbox.printtofile", this);
|
|
addToGB(cbPrintToFile, this, gridbag, c);
|
|
}
|
|
|
|
public boolean isPrintToFileSelected() {
|
|
return cbPrintToFile.isSelected();
|
|
}
|
|
|
|
private JLabel addLabel(String text,
|
|
GridBagLayout gridbag, GridBagConstraints c)
|
|
{
|
|
c.gridwidth = 1;
|
|
addToGB(new JLabel(text, JLabel.TRAILING), this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
JLabel label = new JLabel();
|
|
label.setForeground(Color.black);
|
|
addToGB(label, this, gridbag, c);
|
|
|
|
return label;
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (source == btnProperties) {
|
|
if (uiFactory != null) {
|
|
JDialog dialog = (JDialog)uiFactory.getUI(
|
|
ServiceUIFactory.MAIN_UIROLE,
|
|
ServiceUIFactory.JDIALOG_UI);
|
|
|
|
if (dialog != null) {
|
|
dialog.show();
|
|
} else {
|
|
// REMIND: may want to notify the user why we're
|
|
// disabling the button
|
|
btnProperties.setEnabled(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void itemStateChanged(ItemEvent e) {
|
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
|
int index = cbName.getSelectedIndex();
|
|
|
|
if ((index >= 0) && (index < services.length)) {
|
|
if (!services[index].equals(psCurrent)) {
|
|
psCurrent = services[index];
|
|
uiFactory = psCurrent.getServiceUIFactory();
|
|
changedService = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
|
changedService = false;
|
|
}
|
|
|
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
|
if (changedService) {
|
|
changedService = false;
|
|
updatePanels();
|
|
}
|
|
}
|
|
|
|
public void popupMenuCanceled(PopupMenuEvent e) {
|
|
}
|
|
|
|
/**
|
|
* We disable the "Print To File" checkbox if this returns false
|
|
*/
|
|
private boolean allowedToPrintToFile() {
|
|
try {
|
|
throwPrintToFile();
|
|
return true;
|
|
} catch (SecurityException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Break this out as it may be useful when we allow API to
|
|
* specify printing to a file. In that case its probably right
|
|
* to throw a SecurityException if the permission is not granted.
|
|
*/
|
|
private void throwPrintToFile() {
|
|
SecurityManager security = System.getSecurityManager();
|
|
if (security != null) {
|
|
if (printToFilePermission == null) {
|
|
printToFilePermission =
|
|
new FilePermission("<<ALL FILES>>", "read,write");
|
|
}
|
|
security.checkPermission(printToFilePermission);
|
|
}
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class dstCategory = Destination.class;
|
|
boolean dstSupported = false;
|
|
boolean dstSelected = false;
|
|
boolean dstAllowed = allowedToPrintToFile();
|
|
|
|
// setup Destination (print-to-file) widgets
|
|
if (psCurrent.isAttributeCategorySupported(dstCategory)) {
|
|
dstSupported = true;
|
|
}
|
|
Destination dst = (Destination)asCurrent.get(dstCategory);
|
|
if (dst != null) {
|
|
dstSelected = true;
|
|
}
|
|
cbPrintToFile.setEnabled(dstSupported && dstAllowed);
|
|
cbPrintToFile.setSelected(dstSelected && dstAllowed);
|
|
|
|
// setup PrintService information widgets
|
|
Attribute type = psCurrent.getAttribute(PrinterMakeAndModel.class);
|
|
if (type != null) {
|
|
lblType.setText(type.toString());
|
|
}
|
|
Attribute status =
|
|
psCurrent.getAttribute(PrinterIsAcceptingJobs.class);
|
|
if (status != null) {
|
|
lblStatus.setText(getMsg(status.toString()));
|
|
}
|
|
Attribute info = psCurrent.getAttribute(PrinterInfo.class);
|
|
if (info != null) {
|
|
lblInfo.setText(info.toString());
|
|
}
|
|
btnProperties.setEnabled(uiFactory != null);
|
|
}
|
|
}
|
|
|
|
private class PrintRangePanel extends JPanel
|
|
implements ActionListener, FocusListener
|
|
{
|
|
private final String strTitle = getMsg("border.printrange");
|
|
private final PageRanges prAll = new PageRanges(1, Integer.MAX_VALUE);
|
|
private JRadioButton rbAll, rbPages;
|
|
private JFormattedTextField tfRangeFrom, tfRangeTo;
|
|
private JLabel lblRangeTo;
|
|
private boolean prSupported;
|
|
|
|
public PrintRangePanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = compInsets;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
ButtonGroup bg = new ButtonGroup();
|
|
JPanel pnlTop = new JPanel(new FlowLayout(FlowLayout.LEADING));
|
|
rbAll = createRadioButton("radiobutton.rangeall", this);
|
|
rbAll.setSelected(true);
|
|
bg.add(rbAll);
|
|
pnlTop.add(rbAll);
|
|
addToGB(pnlTop, this, gridbag, c);
|
|
|
|
JPanel pnlBottom = new JPanel(new FlowLayout(FlowLayout.LEADING));
|
|
rbPages = createRadioButton("radiobutton.rangepages", this);
|
|
bg.add(rbPages);
|
|
pnlBottom.add(rbPages);
|
|
DecimalFormat format = new DecimalFormat("####0");
|
|
format.setMinimumFractionDigits(0);
|
|
format.setMaximumFractionDigits(0);
|
|
format.setMinimumIntegerDigits(0);
|
|
format.setMaximumIntegerDigits(5);
|
|
format.setParseIntegerOnly(true);
|
|
format.setDecimalSeparatorAlwaysShown(false);
|
|
NumberFormatter nf = new NumberFormatter(format);
|
|
nf.setMinimum(new Integer(1));
|
|
nf.setMaximum(new Integer(Integer.MAX_VALUE));
|
|
nf.setAllowsInvalid(true);
|
|
nf.setCommitsOnValidEdit(true);
|
|
tfRangeFrom = new JFormattedTextField(nf);
|
|
tfRangeFrom.setColumns(4);
|
|
tfRangeFrom.setEnabled(false);
|
|
tfRangeFrom.addActionListener(this);
|
|
tfRangeFrom.addFocusListener(this);
|
|
tfRangeFrom.setFocusLostBehavior(
|
|
JFormattedTextField.PERSIST);
|
|
pnlBottom.add(tfRangeFrom);
|
|
lblRangeTo = new JLabel(getMsg("label.rangeto"));
|
|
lblRangeTo.setEnabled(false);
|
|
pnlBottom.add(lblRangeTo);
|
|
NumberFormatter nfto;
|
|
try {
|
|
nfto = (NumberFormatter)nf.clone();
|
|
} catch (CloneNotSupportedException e) {
|
|
nfto = new NumberFormatter();
|
|
}
|
|
tfRangeTo = new JFormattedTextField(nfto);
|
|
tfRangeTo.setColumns(4);
|
|
tfRangeTo.setEnabled(false);
|
|
tfRangeTo.addFocusListener(this);
|
|
pnlBottom.add(tfRangeTo);
|
|
addToGB(pnlBottom, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
setupRangeWidgets();
|
|
|
|
if (source == rbAll) {
|
|
asCurrent.add(prAll);
|
|
} else if (source == rbPages ||
|
|
source == tfRangeFrom ||
|
|
source == tfRangeTo) {
|
|
updateRangeAttribute();
|
|
}
|
|
}
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if ((source == tfRangeFrom) || (source == tfRangeTo)) {
|
|
updateRangeAttribute();
|
|
}
|
|
}
|
|
|
|
public void focusGained(FocusEvent e) {}
|
|
|
|
private void setupRangeWidgets() {
|
|
boolean rangeEnabled = (rbPages.isSelected() && prSupported);
|
|
tfRangeFrom.setEnabled(rangeEnabled);
|
|
tfRangeTo.setEnabled(rangeEnabled);
|
|
lblRangeTo.setEnabled(rangeEnabled);
|
|
}
|
|
|
|
private void updateRangeAttribute() {
|
|
String strFrom = tfRangeFrom.getText();
|
|
String strTo = tfRangeTo.getText();
|
|
|
|
int min;
|
|
int max;
|
|
|
|
try {
|
|
min = Integer.parseInt(strFrom);
|
|
} catch (NumberFormatException e) {
|
|
min = 1;
|
|
}
|
|
|
|
try {
|
|
max = Integer.parseInt(strTo);
|
|
} catch (NumberFormatException e) {
|
|
max = min;
|
|
}
|
|
|
|
if (min < 1) {
|
|
min = 1;
|
|
tfRangeFrom.setValue(new Integer(1));
|
|
}
|
|
|
|
if (max < min) {
|
|
max = min;
|
|
tfRangeTo.setValue(new Integer(min));
|
|
}
|
|
|
|
PageRanges pr = new PageRanges(min, max);
|
|
asCurrent.add(pr);
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class prCategory = PageRanges.class;
|
|
prSupported = false;
|
|
|
|
if (psCurrent.isAttributeCategorySupported(prCategory)) {
|
|
prSupported = true;
|
|
}
|
|
|
|
PageRanges pr = (PageRanges)asCurrent.get(prCategory);
|
|
if (pr != null) {
|
|
if (pr.equals(prAll)) {
|
|
rbAll.setSelected(true);
|
|
} else {
|
|
rbPages.setSelected(true);
|
|
|
|
int[][] members = pr.getMembers();
|
|
int min = 1;
|
|
int max = 1;
|
|
if ((members.length > 0) && (members[0].length > 1)) {
|
|
min = members[0][0];
|
|
max = members[0][1];
|
|
}
|
|
tfRangeFrom.setValue(new Integer(min));
|
|
tfRangeTo.setValue(new Integer(max));
|
|
}
|
|
} else {
|
|
rbAll.setSelected(true);
|
|
tfRangeFrom.setValue(new Integer(1));
|
|
tfRangeTo.setValue(new Integer(1));
|
|
}
|
|
|
|
rbAll.setEnabled(prSupported);
|
|
rbPages.setEnabled(prSupported);
|
|
setupRangeWidgets();
|
|
}
|
|
}
|
|
|
|
private class CopiesPanel extends JPanel
|
|
implements ActionListener, ChangeListener
|
|
{
|
|
private final String strTitle = getMsg("border.copies");
|
|
private SpinnerNumberModel snModel;
|
|
private JSpinner spinCopies;
|
|
private JLabel lblCopies;
|
|
private JCheckBox cbCollate;
|
|
private boolean scSupported;
|
|
|
|
public CopiesPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.insets = compInsets;
|
|
|
|
lblCopies = new JLabel(getMsg("label.numcopies"), JLabel.TRAILING);
|
|
lblCopies.setDisplayedMnemonic(getMnemonic("label.numcopies"));
|
|
lblCopies.setLabelFor(spinCopies);
|
|
addToGB(lblCopies, this, gridbag, c);
|
|
|
|
snModel = new SpinnerNumberModel(1, 1, 999, 1);
|
|
spinCopies = new JSpinner(snModel);
|
|
// REMIND
|
|
((JSpinner.NumberEditor)spinCopies.getEditor()).getTextField().setColumns(3);
|
|
spinCopies.addChangeListener(this);
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(spinCopies, this, gridbag, c);
|
|
|
|
cbCollate = createCheckBox("checkbox.collate", this);
|
|
cbCollate.setEnabled(false);
|
|
addToGB(cbCollate, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
if (cbCollate.isSelected()) {
|
|
asCurrent.add(SheetCollate.COLLATED);
|
|
} else {
|
|
asCurrent.add(SheetCollate.UNCOLLATED);
|
|
}
|
|
}
|
|
|
|
public void stateChanged(ChangeEvent e) {
|
|
updateCollateCB();
|
|
|
|
asCurrent.add(new Copies(snModel.getNumber().intValue()));
|
|
}
|
|
|
|
private void updateCollateCB() {
|
|
int num = snModel.getNumber().intValue();
|
|
|
|
cbCollate.setEnabled((num > 1) && scSupported);
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class cpCategory = Copies.class;
|
|
Class csCategory = CopiesSupported.class;
|
|
Class scCategory = SheetCollate.class;
|
|
boolean cpSupported = false;
|
|
scSupported = false;
|
|
|
|
// setup Copies spinner
|
|
if (psCurrent.isAttributeCategorySupported(cpCategory)) {
|
|
cpSupported = true;
|
|
}
|
|
CopiesSupported cs = (CopiesSupported)psCurrent.getDefaultAttributeValue(csCategory);
|
|
if (cs == null) {
|
|
cs = new CopiesSupported(1, 999);
|
|
}
|
|
Copies cp = (Copies)asCurrent.get(cpCategory);
|
|
if (cp == null) {
|
|
cp = (Copies)psCurrent.getDefaultAttributeValue(cpCategory);
|
|
if (cp == null) {
|
|
cp = new Copies(1);
|
|
}
|
|
}
|
|
spinCopies.setEnabled(cpSupported);
|
|
lblCopies.setEnabled(cpSupported);
|
|
|
|
int[][] members = cs.getMembers();
|
|
int min, max;
|
|
if ((members.length > 0) && (members[0].length > 0)) {
|
|
min = members[0][0];
|
|
max = members[0][1];
|
|
} else {
|
|
min = 1;
|
|
max = Integer.MAX_VALUE;
|
|
}
|
|
snModel.setMinimum(new Integer(min));
|
|
snModel.setMaximum(new Integer(max));
|
|
|
|
int value = cp.getValue();
|
|
if ((value < min) || (value > max)) {
|
|
value = min;
|
|
}
|
|
snModel.setValue(new Integer(value));
|
|
|
|
// setup Collate checkbox
|
|
if (psCurrent.isAttributeCategorySupported(scCategory)) {
|
|
scSupported = true;
|
|
}
|
|
SheetCollate sc = (SheetCollate)asCurrent.get(scCategory);
|
|
if (sc == null) {
|
|
sc = (SheetCollate)psCurrent.getDefaultAttributeValue(scCategory);
|
|
if (sc == null) {
|
|
sc = SheetCollate.UNCOLLATED;
|
|
}
|
|
}
|
|
cbCollate.setSelected(sc == SheetCollate.COLLATED);
|
|
updateCollateCB();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* The "Page Setup" tab. Includes the controls for MediaSource/MediaTray,
|
|
* OrientationRequested, and Sides.
|
|
*/
|
|
private class PageSetupPanel extends JPanel {
|
|
|
|
private MediaPanel pnlMedia;
|
|
private OrientationPanel pnlOrientation;
|
|
private MarginsPanel pnlMargins;
|
|
|
|
public PageSetupPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = panelInsets;
|
|
c.weightx = 1.0;
|
|
c.weighty = 1.0;
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
pnlMedia = new MediaPanel();
|
|
addToGB(pnlMedia, this, gridbag, c);
|
|
|
|
pnlOrientation = new OrientationPanel();
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
addToGB(pnlOrientation, this, gridbag, c);
|
|
|
|
pnlMargins = new MarginsPanel();
|
|
pnlOrientation.addOrientationListener(pnlMargins);
|
|
pnlMedia.addMediaListener(pnlMargins);
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(pnlMargins, this, gridbag, c);
|
|
}
|
|
|
|
public void updateInfo() {
|
|
pnlMedia.updateInfo();
|
|
pnlOrientation.updateInfo();
|
|
pnlMargins.updateInfo();
|
|
}
|
|
}
|
|
|
|
private class MarginsPanel extends JPanel
|
|
implements ActionListener, FocusListener {
|
|
|
|
private final String strTitle = getMsg("border.margins");
|
|
private JFormattedTextField leftMargin, rightMargin,
|
|
topMargin, bottomMargin;
|
|
private JLabel lblLeft, lblRight, lblTop, lblBottom;
|
|
private int units = MediaPrintableArea.MM;
|
|
// storage for the last margin values calculated, -ve is uninitialised
|
|
private float lmVal = -1f,rmVal = -1f, tmVal = -1f, bmVal = -1f;
|
|
// storage for margins as objects mapped into orientation for display
|
|
private Float lmObj,rmObj,tmObj,bmObj;
|
|
|
|
public MarginsPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.weightx = 1.0;
|
|
c.weighty = 0.0;
|
|
c.insets = compInsets;
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
String unitsKey = "label.millimetres";
|
|
String defaultCountry = Locale.getDefault().getCountry();
|
|
if (defaultCountry != null &&
|
|
(defaultCountry.equals("") ||
|
|
defaultCountry.equals(Locale.US.getCountry()) ||
|
|
defaultCountry.equals(Locale.CANADA.getCountry()))) {
|
|
unitsKey = "label.inches";
|
|
units = MediaPrintableArea.INCH;
|
|
}
|
|
String unitsMsg = getMsg(unitsKey);
|
|
|
|
DecimalFormat format;
|
|
if (units == MediaPrintableArea.MM) {
|
|
format = new DecimalFormat("###.##");
|
|
format.setMaximumIntegerDigits(3);
|
|
} else {
|
|
format = new DecimalFormat("##.##");
|
|
format.setMaximumIntegerDigits(2);
|
|
}
|
|
|
|
format.setMinimumFractionDigits(1);
|
|
format.setMaximumFractionDigits(2);
|
|
format.setMinimumIntegerDigits(1);
|
|
format.setParseIntegerOnly(false);
|
|
format.setDecimalSeparatorAlwaysShown(true);
|
|
NumberFormatter nf = new NumberFormatter(format);
|
|
nf.setMinimum(new Float(0.0f));
|
|
nf.setMaximum(new Float(999.0f));
|
|
nf.setAllowsInvalid(true);
|
|
nf.setCommitsOnValidEdit(true);
|
|
|
|
leftMargin = new JFormattedTextField(nf);
|
|
leftMargin.addFocusListener(this);
|
|
leftMargin.addActionListener(this);
|
|
rightMargin = new JFormattedTextField(nf);
|
|
rightMargin.addFocusListener(this);
|
|
rightMargin.addActionListener(this);
|
|
topMargin = new JFormattedTextField(nf);
|
|
topMargin.addFocusListener(this);
|
|
topMargin.addActionListener(this);
|
|
bottomMargin = new JFormattedTextField(nf);
|
|
bottomMargin.addFocusListener(this);
|
|
bottomMargin.addActionListener(this);
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
lblLeft = new JLabel(getMsg("label.leftmargin") + " " + unitsMsg,
|
|
JLabel.LEADING);
|
|
lblLeft.setDisplayedMnemonic(getMnemonic("label.leftmargin"));
|
|
lblLeft.setLabelFor(leftMargin);
|
|
addToGB(lblLeft, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
lblRight = new JLabel(getMsg("label.rightmargin") + " " + unitsMsg,
|
|
JLabel.LEADING);
|
|
lblRight.setDisplayedMnemonic(getMnemonic("label.rightmargin"));
|
|
lblRight.setLabelFor(rightMargin);
|
|
addToGB(lblRight, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
addToGB(leftMargin, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(rightMargin, this, gridbag, c);
|
|
|
|
// add an invisible spacing component.
|
|
addToGB(new JPanel(), this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
lblTop = new JLabel(getMsg("label.topmargin") + " " + unitsMsg,
|
|
JLabel.LEADING);
|
|
lblTop.setDisplayedMnemonic(getMnemonic("label.topmargin"));
|
|
lblTop.setLabelFor(topMargin);
|
|
addToGB(lblTop, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
lblBottom = new JLabel(getMsg("label.bottommargin") +
|
|
" " + unitsMsg, JLabel.LEADING);
|
|
lblBottom.setDisplayedMnemonic(getMnemonic("label.bottommargin"));
|
|
lblBottom.setLabelFor(bottomMargin);
|
|
addToGB(lblBottom, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
addToGB(topMargin, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(bottomMargin, this, gridbag, c);
|
|
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
updateMargins(source);
|
|
}
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
Object source = e.getSource();
|
|
updateMargins(source);
|
|
}
|
|
|
|
public void focusGained(FocusEvent e) {}
|
|
|
|
/* Get the numbers, use to create a MPA.
|
|
* If its valid, accept it and update the attribute set.
|
|
* If its not valid, then reject it and call updateInfo()
|
|
* to re-establish the previous entries.
|
|
*/
|
|
public void updateMargins(Object source) {
|
|
if (!(source instanceof JFormattedTextField)) {
|
|
return;
|
|
} else {
|
|
JFormattedTextField tf = (JFormattedTextField)source;
|
|
Float val = (Float)tf.getValue();
|
|
if (val == null) {
|
|
return;
|
|
}
|
|
if (tf == leftMargin && val.equals(lmObj)) {
|
|
return;
|
|
}
|
|
if (tf == rightMargin && val.equals(rmObj)) {
|
|
return;
|
|
}
|
|
if (tf == topMargin && val.equals(tmObj)) {
|
|
return;
|
|
}
|
|
if (tf == bottomMargin && val.equals(bmObj)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
Float lmTmpObj = (Float)leftMargin.getValue();
|
|
Float rmTmpObj = (Float)rightMargin.getValue();
|
|
Float tmTmpObj = (Float)topMargin.getValue();
|
|
Float bmTmpObj = (Float)bottomMargin.getValue();
|
|
|
|
float lm = lmTmpObj.floatValue();
|
|
float rm = rmTmpObj.floatValue();
|
|
float tm = tmTmpObj.floatValue();
|
|
float bm = bmTmpObj.floatValue();
|
|
|
|
/* adjust for orientation */
|
|
Class orCategory = OrientationRequested.class;
|
|
OrientationRequested or =
|
|
(OrientationRequested)asCurrent.get(orCategory);
|
|
|
|
if (or == null) {
|
|
or = (OrientationRequested)
|
|
psCurrent.getDefaultAttributeValue(orCategory);
|
|
}
|
|
|
|
float tmp;
|
|
if (or == OrientationRequested.REVERSE_PORTRAIT) {
|
|
tmp = lm; lm = rm; rm = tmp;
|
|
tmp = tm; tm = bm; bm = tmp;
|
|
} else if (or == OrientationRequested.LANDSCAPE) {
|
|
tmp = lm;
|
|
lm = tm;
|
|
tm = rm;
|
|
rm = bm;
|
|
bm = tmp;
|
|
} else if (or == OrientationRequested.REVERSE_LANDSCAPE) {
|
|
tmp = lm;
|
|
lm = bm;
|
|
bm = rm;
|
|
rm = tm;
|
|
tm = tmp;
|
|
}
|
|
MediaPrintableArea mpa;
|
|
if ((mpa = validateMargins(lm, rm, tm, bm)) != null) {
|
|
asCurrent.add(mpa);
|
|
lmVal = lm;
|
|
rmVal = rm;
|
|
tmVal = tm;
|
|
bmVal = bm;
|
|
lmObj = lmTmpObj;
|
|
rmObj = rmTmpObj;
|
|
tmObj = tmTmpObj;
|
|
bmObj = bmTmpObj;
|
|
} else {
|
|
if (lmObj == null || rmObj == null ||
|
|
tmObj == null || rmObj == null) {
|
|
return;
|
|
} else {
|
|
leftMargin.setValue(lmObj);
|
|
rightMargin.setValue(rmObj);
|
|
topMargin.setValue(tmObj);
|
|
bottomMargin.setValue(bmObj);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This method either accepts the values and creates a new
|
|
* MediaPrintableArea, or does nothing.
|
|
* It should not attempt to create a printable area from anything
|
|
* other than the exact values passed in.
|
|
* But REMIND/TBD: it would be user friendly to replace margins the
|
|
* user entered but are out of bounds with the minimum.
|
|
* At that point this method will need to take responsibility for
|
|
* updating the "stored" values and the UI.
|
|
*/
|
|
private MediaPrintableArea validateMargins(float lm, float rm,
|
|
float tm, float bm) {
|
|
|
|
Class mpaCategory = MediaPrintableArea.class;
|
|
MediaPrintableArea mpa;
|
|
MediaPrintableArea mpaMax = null;
|
|
MediaSize mediaSize = null;
|
|
|
|
Media media = (Media)asCurrent.get(Media.class);
|
|
if (media == null || !(media instanceof MediaSizeName)) {
|
|
media = (Media)psCurrent.getDefaultAttributeValue(Media.class);
|
|
}
|
|
if (media != null && (media instanceof MediaSizeName)) {
|
|
MediaSizeName msn = (MediaSizeName)media;
|
|
mediaSize = MediaSize.getMediaSizeForName(msn);
|
|
}
|
|
if (mediaSize == null) {
|
|
mediaSize = new MediaSize(8.5f, 11f, Size2DSyntax.INCH);
|
|
}
|
|
|
|
if (media != null) {
|
|
PrintRequestAttributeSet tmpASet =
|
|
new HashPrintRequestAttributeSet(asCurrent);
|
|
tmpASet.add(media);
|
|
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(mpaCategory,
|
|
docFlavor,
|
|
tmpASet);
|
|
if (values instanceof MediaPrintableArea[] &&
|
|
((MediaPrintableArea[])values).length > 0) {
|
|
mpaMax = ((MediaPrintableArea[])values)[0];
|
|
|
|
}
|
|
}
|
|
if (mpaMax == null) {
|
|
mpaMax = new MediaPrintableArea(0f, 0f,
|
|
mediaSize.getX(units),
|
|
mediaSize.getY(units),
|
|
units);
|
|
}
|
|
|
|
float wid = mediaSize.getX(units);
|
|
float hgt = mediaSize.getY(units);
|
|
float pax = lm;
|
|
float pay = tm;
|
|
float paw = wid - lm - rm;
|
|
float pah = hgt - tm - bm;
|
|
|
|
if (paw <= 0f || pah <= 0f || pax < 0f || pay < 0f ||
|
|
pax < mpaMax.getX(units) || paw > mpaMax.getWidth(units) ||
|
|
pay < mpaMax.getY(units) || pah > mpaMax.getHeight(units)) {
|
|
return null;
|
|
} else {
|
|
return new MediaPrintableArea(lm, tm, paw, pah, units);
|
|
}
|
|
}
|
|
|
|
/* This is complex as a MediaPrintableArea is valid only within
|
|
* a particular context of media size.
|
|
* So we need a MediaSize as well as a MediaPrintableArea.
|
|
* MediaSize can be obtained from MediaSizeName.
|
|
* If the application specifies a MediaPrintableArea, we accept it
|
|
* to the extent its valid for the Media they specify. If they
|
|
* don't specify a Media, then the default is assumed.
|
|
*
|
|
* If an application doesn't define a MediaPrintableArea, we need to
|
|
* create a suitable one, this is created using the specified (or
|
|
* default) Media and default 1 inch margins. This is validated
|
|
* against the paper in case this is too large for tiny media.
|
|
*/
|
|
public void updateInfo() {
|
|
|
|
Class mpaCategory = MediaPrintableArea.class;
|
|
MediaPrintableArea mpa =
|
|
(MediaPrintableArea)asCurrent.get(mpaCategory);
|
|
MediaPrintableArea mpaMax = null;
|
|
MediaSize mediaSize = null;
|
|
|
|
Media media = (Media)asCurrent.get(Media.class);
|
|
if (media == null || !(media instanceof MediaSizeName)) {
|
|
media = (Media)psCurrent.getDefaultAttributeValue(Media.class);
|
|
}
|
|
if (media != null && (media instanceof MediaSizeName)) {
|
|
MediaSizeName msn = (MediaSizeName)media;
|
|
mediaSize = MediaSize.getMediaSizeForName(msn);
|
|
}
|
|
if (mediaSize == null) {
|
|
mediaSize = new MediaSize(8.5f, 11f, Size2DSyntax.INCH);
|
|
}
|
|
|
|
if (media != null) {
|
|
PrintRequestAttributeSet tmpASet =
|
|
new HashPrintRequestAttributeSet(asCurrent);
|
|
tmpASet.add(media);
|
|
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(mpaCategory,
|
|
docFlavor,
|
|
tmpASet);
|
|
if (values instanceof MediaPrintableArea[] &&
|
|
((MediaPrintableArea[])values).length > 0) {
|
|
mpaMax = ((MediaPrintableArea[])values)[0];
|
|
|
|
} else if (values instanceof MediaPrintableArea) {
|
|
mpaMax = (MediaPrintableArea)values;
|
|
}
|
|
}
|
|
if (mpaMax == null) {
|
|
mpaMax = new MediaPrintableArea(0f, 0f,
|
|
mediaSize.getX(units),
|
|
mediaSize.getY(units),
|
|
units);
|
|
}
|
|
|
|
/*
|
|
* At this point we now know as best we can :-
|
|
* - the media size
|
|
* - the maximum corresponding printable area
|
|
* - the media printable area specified by the client, if any.
|
|
* The next step is to create a default MPA if none was specified.
|
|
* 1" margins are used unless they are disproportionately
|
|
* large compared to the size of the media.
|
|
*/
|
|
|
|
float wid = mediaSize.getX(MediaPrintableArea.INCH);
|
|
float hgt = mediaSize.getY(MediaPrintableArea.INCH);
|
|
float maxMarginRatio = 5f;
|
|
float xMgn, yMgn;
|
|
if (wid > maxMarginRatio) {
|
|
xMgn = 1f;
|
|
} else {
|
|
xMgn = wid / maxMarginRatio;
|
|
}
|
|
if (hgt > maxMarginRatio) {
|
|
yMgn = 1f;
|
|
} else {
|
|
yMgn = hgt / maxMarginRatio;
|
|
}
|
|
|
|
if (mpa == null) {
|
|
mpa = new MediaPrintableArea(xMgn, yMgn,
|
|
wid-(2*xMgn), hgt-(2*yMgn),
|
|
MediaPrintableArea.INCH);
|
|
asCurrent.add(mpa);
|
|
}
|
|
float pax = mpa.getX(units);
|
|
float pay = mpa.getY(units);
|
|
float paw = mpa.getWidth(units);
|
|
float pah = mpa.getHeight(units);
|
|
float paxMax = mpaMax.getX(units);
|
|
float payMax = mpaMax.getY(units);
|
|
float pawMax = mpaMax.getWidth(units);
|
|
float pahMax = mpaMax.getHeight(units);
|
|
|
|
|
|
boolean invalid = false;
|
|
|
|
// If the paper is set to something which is too small to
|
|
// accommodate a specified printable area, perhaps carried
|
|
// over from a larger paper, the adjustment that needs to be
|
|
// performed should seem the most natural from a user's viewpoint.
|
|
// Since the user is specifying margins, then we are biased
|
|
// towards keeping the margins as close to what is specified as
|
|
// possible, shrinking or growing the printable area.
|
|
// But the API uses printable area, so you need to know the
|
|
// media size in which the margins were previously interpreted,
|
|
// or at least have a record of the margins.
|
|
// In the case that this is the creation of this UI we do not
|
|
// have this record, so we are somewhat reliant on the client
|
|
// to supply a reasonable default
|
|
wid = mediaSize.getX(units);
|
|
hgt = mediaSize.getY(units);
|
|
if (lmVal >= 0f) {
|
|
invalid = true;
|
|
|
|
if (lmVal + rmVal > wid) {
|
|
// margins impossible, but maintain P.A if can
|
|
if (paw > pawMax) {
|
|
paw = pawMax;
|
|
}
|
|
// try to centre the printable area.
|
|
pax = (wid - paw)/2f;
|
|
} else {
|
|
pax = (lmVal >= paxMax) ? lmVal : paxMax;
|
|
paw = wid - pax - rmVal;
|
|
}
|
|
if (tmVal + bmVal > hgt) {
|
|
if (pah > pahMax) {
|
|
pah = pahMax;
|
|
}
|
|
pay = (hgt - pah)/2f;
|
|
} else {
|
|
pay = (tmVal >= payMax) ? tmVal : payMax;
|
|
pah = hgt - pay - bmVal;
|
|
}
|
|
}
|
|
if (pax < paxMax) {
|
|
invalid = true;
|
|
pax = paxMax;
|
|
}
|
|
if (pay < payMax) {
|
|
invalid = true;
|
|
pay = payMax;
|
|
}
|
|
if (paw > pawMax) {
|
|
invalid = true;
|
|
paw = pawMax;
|
|
}
|
|
if (pah > pahMax) {
|
|
invalid = true;
|
|
pah = pahMax;
|
|
}
|
|
|
|
if ((pax + paw > paxMax + pawMax) || (paw <= 0f)) {
|
|
invalid = true;
|
|
pax = paxMax;
|
|
paw = pawMax;
|
|
}
|
|
if ((pay + pah > payMax + pahMax) || (pah <= 0f)) {
|
|
invalid = true;
|
|
pay = payMax;
|
|
pah = pahMax;
|
|
}
|
|
|
|
if (invalid) {
|
|
mpa = new MediaPrintableArea(pax, pay, paw, pah, units);
|
|
asCurrent.add(mpa);
|
|
}
|
|
|
|
/* We now have a valid printable area.
|
|
* Turn it into margins, using the mediaSize
|
|
*/
|
|
lmVal = pax;
|
|
tmVal = pay;
|
|
rmVal = mediaSize.getX(units) - pax - paw;
|
|
bmVal = mediaSize.getY(units) - pay - pah;
|
|
|
|
lmObj = new Float(lmVal);
|
|
rmObj = new Float(rmVal);
|
|
tmObj = new Float(tmVal);
|
|
bmObj = new Float(bmVal);
|
|
|
|
/* Now we know the values to use, we need to assign them
|
|
* to the fields appropriate for the orientation.
|
|
* Note: if orientation changes this method must be called.
|
|
*/
|
|
Class orCategory = OrientationRequested.class;
|
|
OrientationRequested or =
|
|
(OrientationRequested)asCurrent.get(orCategory);
|
|
|
|
if (or == null) {
|
|
or = (OrientationRequested)
|
|
psCurrent.getDefaultAttributeValue(orCategory);
|
|
}
|
|
|
|
Float tmp;
|
|
|
|
if (or == OrientationRequested.REVERSE_PORTRAIT) {
|
|
tmp = lmObj; lmObj = rmObj; rmObj = tmp;
|
|
tmp = tmObj; tmObj = bmObj; bmObj = tmp;
|
|
} else if (or == OrientationRequested.LANDSCAPE) {
|
|
tmp = lmObj;
|
|
lmObj = bmObj;
|
|
bmObj = rmObj;
|
|
rmObj = tmObj;
|
|
tmObj = tmp;
|
|
} else if (or == OrientationRequested.REVERSE_LANDSCAPE) {
|
|
tmp = lmObj;
|
|
lmObj = tmObj;
|
|
tmObj = rmObj;
|
|
rmObj = bmObj;
|
|
bmObj = tmp;
|
|
}
|
|
|
|
leftMargin.setValue(lmObj);
|
|
rightMargin.setValue(rmObj);
|
|
topMargin.setValue(tmObj);
|
|
bottomMargin.setValue(bmObj);
|
|
}
|
|
}
|
|
|
|
private class MediaPanel extends JPanel implements ItemListener {
|
|
|
|
private final String strTitle = getMsg("border.media");
|
|
private JLabel lblSize, lblSource;
|
|
private JComboBox cbSize, cbSource;
|
|
private Vector sizes = new Vector();
|
|
private Vector sources = new Vector();
|
|
private MarginsPanel pnlMargins = null;
|
|
|
|
public MediaPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
cbSize = new JComboBox();
|
|
cbSource = new JComboBox();
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = compInsets;
|
|
c.weighty = 1.0;
|
|
|
|
c.weightx = 0.0;
|
|
lblSize = new JLabel(getMsg("label.size"), JLabel.TRAILING);
|
|
lblSize.setDisplayedMnemonic(getMnemonic("label.size"));
|
|
lblSize.setLabelFor(cbSize);
|
|
addToGB(lblSize, this, gridbag, c);
|
|
c.weightx = 1.0;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(cbSize, this, gridbag, c);
|
|
|
|
c.weightx = 0.0;
|
|
c.gridwidth = 1;
|
|
lblSource = new JLabel(getMsg("label.source"), JLabel.TRAILING);
|
|
lblSource.setDisplayedMnemonic(getMnemonic("label.source"));
|
|
lblSource.setLabelFor(cbSource);
|
|
addToGB(lblSource, this, gridbag, c);
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(cbSource, this, gridbag, c);
|
|
}
|
|
|
|
private String getMediaName(String key) {
|
|
try {
|
|
// replace characters that would be invalid in
|
|
// a resource key with valid characters
|
|
String newkey = key.replace(' ', '-');
|
|
newkey = newkey.replace('#', 'n');
|
|
|
|
return messageRB.getString(newkey);
|
|
} catch (java.util.MissingResourceException e) {
|
|
return key;
|
|
}
|
|
}
|
|
|
|
public void itemStateChanged(ItemEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
|
if (source == cbSize) {
|
|
int index = cbSize.getSelectedIndex();
|
|
|
|
if ((index >= 0) && (index < sizes.size())) {
|
|
if ((cbSource.getItemCount() > 1) &&
|
|
(cbSource.getSelectedIndex() >= 1))
|
|
{
|
|
int src = cbSource.getSelectedIndex() - 1;
|
|
MediaTray mt = (MediaTray)sources.get(src);
|
|
asCurrent.add(new SunAlternateMedia(mt));
|
|
}
|
|
asCurrent.add((MediaSizeName)sizes.get(index));
|
|
}
|
|
} else if (source == cbSource) {
|
|
int index = cbSource.getSelectedIndex();
|
|
|
|
if ((index >= 1) && (index < (sources.size() + 1))) {
|
|
asCurrent.remove(SunAlternateMedia.class);
|
|
asCurrent.add((MediaTray)sources.get(index - 1));
|
|
} else if (index == 0) {
|
|
asCurrent.remove(SunAlternateMedia.class);
|
|
if (cbSize.getItemCount() > 0) {
|
|
int size = cbSize.getSelectedIndex();
|
|
asCurrent.add((MediaSizeName)sizes.get(size));
|
|
}
|
|
}
|
|
}
|
|
// orientation affects display of margins.
|
|
if (pnlMargins != null) {
|
|
pnlMargins.updateInfo();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* this is ad hoc to keep things simple */
|
|
public void addMediaListener(MarginsPanel pnl) {
|
|
pnlMargins = pnl;
|
|
}
|
|
public void updateInfo() {
|
|
Class mdCategory = Media.class;
|
|
Class amCategory = SunAlternateMedia.class;
|
|
boolean mediaSupported = false;
|
|
|
|
cbSize.removeItemListener(this);
|
|
cbSize.removeAllItems();
|
|
cbSource.removeItemListener(this);
|
|
cbSource.removeAllItems();
|
|
cbSource.addItem(getMediaName("auto-select"));
|
|
|
|
sizes.clear();
|
|
sources.clear();
|
|
|
|
if (psCurrent.isAttributeCategorySupported(mdCategory)) {
|
|
mediaSupported = true;
|
|
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(mdCategory,
|
|
docFlavor,
|
|
asCurrent);
|
|
|
|
if (values instanceof Media[]) {
|
|
Media[] media = (Media[])values;
|
|
|
|
for (int i = 0; i < media.length; i++) {
|
|
Media medium = media[i];
|
|
|
|
if (medium instanceof MediaSizeName) {
|
|
sizes.add(medium);
|
|
cbSize.addItem(getMediaName(medium.toString()));
|
|
} else if (medium instanceof MediaTray) {
|
|
sources.add(medium);
|
|
cbSource.addItem(getMediaName(medium.toString()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean msSupported = (mediaSupported && (sizes.size() > 0));
|
|
lblSize.setEnabled(msSupported);
|
|
cbSize.setEnabled(msSupported);
|
|
cbSource.setEnabled(mediaSupported);
|
|
|
|
if (mediaSupported) {
|
|
|
|
Media medium = (Media)asCurrent.get(mdCategory);
|
|
|
|
if (medium == null) {
|
|
medium = (Media)psCurrent.getDefaultAttributeValue(mdCategory);
|
|
|
|
if (medium == null) {
|
|
if (sizes.size() > 0) {
|
|
medium = (Media)sizes.get(0);
|
|
}
|
|
}
|
|
}
|
|
if (medium != null) {
|
|
if (medium instanceof MediaSizeName) {
|
|
MediaSizeName ms = (MediaSizeName)medium;
|
|
cbSize.setSelectedIndex(sizes.indexOf(ms));
|
|
} else if (medium instanceof MediaTray) {
|
|
MediaTray mt = (MediaTray)medium;
|
|
cbSource.setSelectedIndex(sources.indexOf(mt) + 1);
|
|
}
|
|
} else {
|
|
cbSize.setSelectedIndex(sizes.size() > 0 ? 0 : -1);
|
|
cbSource.setSelectedIndex(0);
|
|
}
|
|
|
|
SunAlternateMedia alt = (SunAlternateMedia)asCurrent.get(amCategory);
|
|
if (alt != null) {
|
|
Media md = alt.getMedia();
|
|
if (md instanceof MediaTray) {
|
|
MediaTray mt = (MediaTray)md;
|
|
cbSource.setSelectedIndex(sources.indexOf(mt) + 1);
|
|
}
|
|
}
|
|
|
|
int selIndex = cbSize.getSelectedIndex();
|
|
if ((selIndex >= 0) && (selIndex < sizes.size())) {
|
|
asCurrent.add((MediaSizeName)sizes.get(selIndex));
|
|
}
|
|
|
|
selIndex = cbSource.getSelectedIndex();
|
|
if ((selIndex >= 1) && (selIndex < (sources.size()+1))) {
|
|
asCurrent.add((MediaTray)sources.get(selIndex-1));
|
|
}
|
|
|
|
|
|
}
|
|
cbSize.addItemListener(this);
|
|
cbSource.addItemListener(this);
|
|
}
|
|
}
|
|
|
|
private class OrientationPanel extends JPanel
|
|
implements ActionListener
|
|
{
|
|
private final String strTitle = getMsg("border.orientation");
|
|
private IconRadioButton rbPortrait, rbLandscape,
|
|
rbRevPortrait, rbRevLandscape;
|
|
private MarginsPanel pnlMargins = null;
|
|
|
|
public OrientationPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = compInsets;
|
|
c.weighty = 1.0;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
ButtonGroup bg = new ButtonGroup();
|
|
rbPortrait = new IconRadioButton("radiobutton.portrait",
|
|
"orientPortrait.gif", true,
|
|
bg, this);
|
|
rbPortrait.addActionListener(this);
|
|
addToGB(rbPortrait, this, gridbag, c);
|
|
rbLandscape = new IconRadioButton("radiobutton.landscape",
|
|
"orientLandscape.gif", false,
|
|
bg, this);
|
|
rbLandscape.addActionListener(this);
|
|
addToGB(rbLandscape, this, gridbag, c);
|
|
rbRevPortrait = new IconRadioButton("radiobutton.revportrait",
|
|
"orientRevPortrait.gif", false,
|
|
bg, this);
|
|
rbRevPortrait.addActionListener(this);
|
|
addToGB(rbRevPortrait, this, gridbag, c);
|
|
rbRevLandscape = new IconRadioButton("radiobutton.revlandscape",
|
|
"orientRevLandscape.gif", false,
|
|
bg, this);
|
|
rbRevLandscape.addActionListener(this);
|
|
addToGB(rbRevLandscape, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (rbPortrait.isSameAs(source)) {
|
|
asCurrent.add(OrientationRequested.PORTRAIT);
|
|
} else if (rbLandscape.isSameAs(source)) {
|
|
asCurrent.add(OrientationRequested.LANDSCAPE);
|
|
} else if (rbRevPortrait.isSameAs(source)) {
|
|
asCurrent.add(OrientationRequested.REVERSE_PORTRAIT);
|
|
} else if (rbRevLandscape.isSameAs(source)) {
|
|
asCurrent.add(OrientationRequested.REVERSE_LANDSCAPE);
|
|
}
|
|
// orientation affects display of margins.
|
|
if (pnlMargins != null) {
|
|
pnlMargins.updateInfo();
|
|
}
|
|
}
|
|
|
|
/* This is ad hoc to keep things simple */
|
|
void addOrientationListener(MarginsPanel pnl) {
|
|
pnlMargins = pnl;
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class orCategory = OrientationRequested.class;
|
|
boolean pSupported = false;
|
|
boolean lSupported = false;
|
|
boolean rpSupported = false;
|
|
boolean rlSupported = false;
|
|
|
|
if (psCurrent.isAttributeCategorySupported(orCategory)) {
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(orCategory,
|
|
docFlavor,
|
|
asCurrent);
|
|
|
|
if (values instanceof OrientationRequested[]) {
|
|
OrientationRequested[] ovalues =
|
|
(OrientationRequested[])values;
|
|
|
|
for (int i = 0; i < ovalues.length; i++) {
|
|
OrientationRequested value = ovalues[i];
|
|
|
|
if (value == OrientationRequested.PORTRAIT) {
|
|
pSupported = true;
|
|
} else if (value == OrientationRequested.LANDSCAPE) {
|
|
lSupported = true;
|
|
} else if (value == OrientationRequested.REVERSE_PORTRAIT) {
|
|
rpSupported = true;
|
|
} else if (value == OrientationRequested.REVERSE_LANDSCAPE) {
|
|
rlSupported = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rbPortrait.setEnabled(pSupported);
|
|
rbLandscape.setEnabled(lSupported);
|
|
rbRevPortrait.setEnabled(rpSupported);
|
|
rbRevLandscape.setEnabled(rlSupported);
|
|
|
|
OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
|
|
if (or == null) {
|
|
or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
|
|
if (or == null) {
|
|
or = OrientationRequested.PORTRAIT;
|
|
}
|
|
}
|
|
|
|
if (or == OrientationRequested.PORTRAIT) {
|
|
rbPortrait.setSelected(true);
|
|
} else if (or == OrientationRequested.LANDSCAPE) {
|
|
rbLandscape.setSelected(true);
|
|
} else if (or == OrientationRequested.REVERSE_PORTRAIT) {
|
|
rbRevPortrait.setSelected(true);
|
|
} else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
|
|
rbRevLandscape.setSelected(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* The "Appearance" tab. Includes the controls for Chromaticity,
|
|
* PrintQuality, JobPriority, JobName, and other related job attributes.
|
|
*/
|
|
private class AppearancePanel extends JPanel {
|
|
|
|
private ChromaticityPanel pnlChromaticity;
|
|
private QualityPanel pnlQuality;
|
|
private JobAttributesPanel pnlJobAttributes;
|
|
private SidesPanel pnlSides;
|
|
|
|
public AppearancePanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = panelInsets;
|
|
c.weightx = 1.0;
|
|
c.weighty = 1.0;
|
|
|
|
c.gridwidth = GridBagConstraints.RELATIVE;
|
|
pnlChromaticity = new ChromaticityPanel();
|
|
addToGB(pnlChromaticity, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
pnlQuality = new QualityPanel();
|
|
addToGB(pnlQuality, this, gridbag, c);
|
|
|
|
c.gridwidth = 1;
|
|
pnlSides = new SidesPanel();
|
|
addToGB(pnlSides, this, gridbag, c);
|
|
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
pnlJobAttributes = new JobAttributesPanel();
|
|
addToGB(pnlJobAttributes, this, gridbag, c);
|
|
|
|
}
|
|
|
|
public void updateInfo() {
|
|
pnlChromaticity.updateInfo();
|
|
pnlQuality.updateInfo();
|
|
pnlSides.updateInfo();
|
|
pnlJobAttributes.updateInfo();
|
|
}
|
|
}
|
|
|
|
private class ChromaticityPanel extends JPanel
|
|
implements ActionListener
|
|
{
|
|
private final String strTitle = getMsg("border.chromaticity");
|
|
private JRadioButton rbMonochrome, rbColor;
|
|
|
|
public ChromaticityPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
c.weighty = 1.0;
|
|
|
|
ButtonGroup bg = new ButtonGroup();
|
|
rbMonochrome = createRadioButton("radiobutton.monochrome", this);
|
|
rbMonochrome.setSelected(true);
|
|
bg.add(rbMonochrome);
|
|
addToGB(rbMonochrome, this, gridbag, c);
|
|
rbColor = createRadioButton("radiobutton.color", this);
|
|
bg.add(rbColor);
|
|
addToGB(rbColor, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
// REMIND: use isSameAs if we move to a IconRB in the future
|
|
if (source == rbMonochrome) {
|
|
asCurrent.add(Chromaticity.MONOCHROME);
|
|
} else if (source == rbColor) {
|
|
asCurrent.add(Chromaticity.COLOR);
|
|
}
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class chCategory = Chromaticity.class;
|
|
boolean monoSupported = false;
|
|
boolean colorSupported = false;
|
|
|
|
if (psCurrent.isAttributeCategorySupported(chCategory)) {
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(chCategory,
|
|
docFlavor,
|
|
asCurrent);
|
|
|
|
if (values instanceof Chromaticity[]) {
|
|
Chromaticity[] cvalues = (Chromaticity[])values;
|
|
|
|
for (int i = 0; i < cvalues.length; i++) {
|
|
Chromaticity value = cvalues[i];
|
|
|
|
if (value == Chromaticity.MONOCHROME) {
|
|
monoSupported = true;
|
|
} else if (value == Chromaticity.COLOR) {
|
|
colorSupported = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rbMonochrome.setEnabled(monoSupported);
|
|
rbColor.setEnabled(colorSupported);
|
|
|
|
Chromaticity ch = (Chromaticity)asCurrent.get(chCategory);
|
|
if (ch == null) {
|
|
ch = (Chromaticity)psCurrent.getDefaultAttributeValue(chCategory);
|
|
if (ch == null) {
|
|
ch = Chromaticity.MONOCHROME;
|
|
}
|
|
}
|
|
|
|
if (ch == Chromaticity.MONOCHROME) {
|
|
rbMonochrome.setSelected(true);
|
|
} else { // if (ch == Chromaticity.COLOR)
|
|
rbColor.setSelected(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private class QualityPanel extends JPanel
|
|
implements ActionListener
|
|
{
|
|
private final String strTitle = getMsg("border.quality");
|
|
private JRadioButton rbDraft, rbNormal, rbHigh;
|
|
|
|
public QualityPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
c.weighty = 1.0;
|
|
|
|
ButtonGroup bg = new ButtonGroup();
|
|
rbDraft = createRadioButton("radiobutton.draftq", this);
|
|
bg.add(rbDraft);
|
|
addToGB(rbDraft, this, gridbag, c);
|
|
rbNormal = createRadioButton("radiobutton.normalq", this);
|
|
rbNormal.setSelected(true);
|
|
bg.add(rbNormal);
|
|
addToGB(rbNormal, this, gridbag, c);
|
|
rbHigh = createRadioButton("radiobutton.highq", this);
|
|
bg.add(rbHigh);
|
|
addToGB(rbHigh, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (source == rbDraft) {
|
|
asCurrent.add(PrintQuality.DRAFT);
|
|
} else if (source == rbNormal) {
|
|
asCurrent.add(PrintQuality.NORMAL);
|
|
} else if (source == rbHigh) {
|
|
asCurrent.add(PrintQuality.HIGH);
|
|
}
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class pqCategory = PrintQuality.class;
|
|
boolean draftSupported = false;
|
|
boolean normalSupported = false;
|
|
boolean highSupported = false;
|
|
|
|
if (psCurrent.isAttributeCategorySupported(pqCategory)) {
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(pqCategory,
|
|
docFlavor,
|
|
asCurrent);
|
|
|
|
if (values instanceof PrintQuality[]) {
|
|
PrintQuality[] qvalues = (PrintQuality[])values;
|
|
|
|
for (int i = 0; i < qvalues.length; i++) {
|
|
PrintQuality value = qvalues[i];
|
|
|
|
if (value == PrintQuality.DRAFT) {
|
|
draftSupported = true;
|
|
} else if (value == PrintQuality.NORMAL) {
|
|
normalSupported = true;
|
|
} else if (value == PrintQuality.HIGH) {
|
|
highSupported = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rbDraft.setEnabled(draftSupported);
|
|
rbNormal.setEnabled(normalSupported);
|
|
rbHigh.setEnabled(highSupported);
|
|
|
|
PrintQuality pq = (PrintQuality)asCurrent.get(pqCategory);
|
|
if (pq == null) {
|
|
pq = (PrintQuality)psCurrent.getDefaultAttributeValue(pqCategory);
|
|
if (pq == null) {
|
|
pq = PrintQuality.NORMAL;
|
|
}
|
|
}
|
|
|
|
if (pq == PrintQuality.DRAFT) {
|
|
rbDraft.setSelected(true);
|
|
} else if (pq == PrintQuality.NORMAL) {
|
|
rbNormal.setSelected(true);
|
|
} else { // if (pq == PrintQuality.HIGH)
|
|
rbHigh.setSelected(true);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
private class SidesPanel extends JPanel
|
|
implements ActionListener
|
|
{
|
|
private final String strTitle = getMsg("border.sides");
|
|
private IconRadioButton rbOneSide, rbTumble, rbDuplex;
|
|
|
|
public SidesPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.BOTH;
|
|
c.insets = compInsets;
|
|
c.weighty = 1.0;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
ButtonGroup bg = new ButtonGroup();
|
|
rbOneSide = new IconRadioButton("radiobutton.oneside",
|
|
"oneside.gif", true,
|
|
bg, this);
|
|
rbOneSide.addActionListener(this);
|
|
addToGB(rbOneSide, this, gridbag, c);
|
|
rbTumble = new IconRadioButton("radiobutton.tumble",
|
|
"tumble.gif", false,
|
|
bg, this);
|
|
rbTumble.addActionListener(this);
|
|
addToGB(rbTumble, this, gridbag, c);
|
|
rbDuplex = new IconRadioButton("radiobutton.duplex",
|
|
"duplex.gif", false,
|
|
bg, this);
|
|
rbDuplex.addActionListener(this);
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(rbDuplex, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (rbOneSide.isSameAs(source)) {
|
|
asCurrent.add(Sides.ONE_SIDED);
|
|
} else if (rbTumble.isSameAs(source)) {
|
|
asCurrent.add(Sides.TUMBLE);
|
|
} else if (rbDuplex.isSameAs(source)) {
|
|
asCurrent.add(Sides.DUPLEX);
|
|
}
|
|
}
|
|
|
|
public void updateInfo() {
|
|
Class sdCategory = Sides.class;
|
|
boolean osSupported = false;
|
|
boolean tSupported = false;
|
|
boolean dSupported = false;
|
|
|
|
if (psCurrent.isAttributeCategorySupported(sdCategory)) {
|
|
Object values =
|
|
psCurrent.getSupportedAttributeValues(sdCategory,
|
|
docFlavor,
|
|
asCurrent);
|
|
|
|
if (values instanceof Sides[]) {
|
|
Sides[] svalues = (Sides[])values;
|
|
|
|
for (int i = 0; i < svalues.length; i++) {
|
|
Sides value = svalues[i];
|
|
|
|
if (value == Sides.ONE_SIDED) {
|
|
osSupported = true;
|
|
} else if (value == Sides.TUMBLE) {
|
|
tSupported = true;
|
|
} else if (value == Sides.DUPLEX) {
|
|
dSupported = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rbOneSide.setEnabled(osSupported);
|
|
rbTumble.setEnabled(tSupported);
|
|
rbDuplex.setEnabled(dSupported);
|
|
|
|
Sides sd = (Sides)asCurrent.get(sdCategory);
|
|
if (sd == null) {
|
|
sd = (Sides)psCurrent.getDefaultAttributeValue(sdCategory);
|
|
if (sd == null) {
|
|
sd = Sides.ONE_SIDED;
|
|
}
|
|
}
|
|
|
|
if (sd == Sides.ONE_SIDED) {
|
|
rbOneSide.setSelected(true);
|
|
} else if (sd == Sides.TUMBLE) {
|
|
rbTumble.setSelected(true);
|
|
} else { // if (sd == Sides.DUPLEX)
|
|
rbDuplex.setSelected(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private class JobAttributesPanel extends JPanel
|
|
implements ActionListener, ChangeListener, FocusListener
|
|
{
|
|
private final String strTitle = getMsg("border.jobattributes");
|
|
private JLabel lblPriority, lblJobName, lblUserName;
|
|
private JSpinner spinPriority;
|
|
private SpinnerNumberModel snModel;
|
|
private JCheckBox cbJobSheets;
|
|
private JTextField tfJobName, tfUserName;
|
|
|
|
public JobAttributesPanel() {
|
|
super();
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
|
|
setLayout(gridbag);
|
|
setBorder(BorderFactory.createTitledBorder(strTitle));
|
|
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.insets = compInsets;
|
|
c.weighty = 1.0;
|
|
|
|
cbJobSheets = createCheckBox("checkbox.jobsheets", this);
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
addToGB(cbJobSheets, this, gridbag, c);
|
|
|
|
JPanel pnlTop = new JPanel();
|
|
lblPriority = new JLabel(getMsg("label.priority"), JLabel.TRAILING);
|
|
lblPriority.setDisplayedMnemonic(getMnemonic("label.priority"));
|
|
lblPriority.setLabelFor(spinPriority);
|
|
pnlTop.add(lblPriority);
|
|
snModel = new SpinnerNumberModel(1, 1, 100, 1);
|
|
spinPriority = new JSpinner(snModel);
|
|
// REMIND
|
|
((JSpinner.NumberEditor)spinPriority.getEditor()).getTextField().setColumns(3);
|
|
spinPriority.addChangeListener(this);
|
|
pnlTop.add(spinPriority);
|
|
c.anchor = GridBagConstraints.LINE_END;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
addToGB(pnlTop, this, gridbag, c);
|
|
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.anchor = GridBagConstraints.CENTER;
|
|
c.weightx = 0.0;
|
|
c.gridwidth = 1;
|
|
char jmnemonic = getMnemonic("label.jobname");
|
|
lblJobName = new JLabel(getMsg("label.jobname"), JLabel.TRAILING);
|
|
lblJobName.setDisplayedMnemonic(jmnemonic);
|
|
addToGB(lblJobName, this, gridbag, c);
|
|
c.weightx = 1.0;
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
tfJobName = new JTextField();
|
|
tfJobName.addFocusListener(this);
|
|
tfJobName.setFocusAccelerator(jmnemonic);
|
|
addToGB(tfJobName, this, gridbag, c);
|
|
|
|
c.weightx = 0.0;
|
|
c.gridwidth = 1;
|
|
char umnemonic = getMnemonic("label.username");
|
|
lblUserName = new JLabel(getMsg("label.username"), JLabel.TRAILING);
|
|
lblUserName.setDisplayedMnemonic(umnemonic);
|
|
addToGB(lblUserName, this, gridbag, c);
|
|
c.gridwidth = GridBagConstraints.REMAINDER;
|
|
tfUserName = new JTextField();
|
|
tfUserName.addFocusListener(this);
|
|
tfUserName.setFocusAccelerator(umnemonic);
|
|
addToGB(tfUserName, this, gridbag, c);
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
if (cbJobSheets.isSelected()) {
|
|
asCurrent.add(JobSheets.STANDARD);
|
|
} else {
|
|
asCurrent.add(JobSheets.NONE);
|
|
}
|
|
}
|
|
|
|
public void stateChanged(ChangeEvent e) {
|
|
asCurrent.add(new JobPriority(snModel.getNumber().intValue()));
|
|
}
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
Object source = e.getSource();
|
|
|
|
if (source == tfJobName) {
|
|
asCurrent.add(new JobName(tfJobName.getText(),
|
|
Locale.getDefault()));
|
|
} else if (source == tfUserName) {
|
|
asCurrent.add(new RequestingUserName(tfUserName.getText(),
|
|
Locale.getDefault()));
|
|
}
|
|
}
|
|
|
|
public void focusGained(FocusEvent e) {}
|
|
|
|
public void updateInfo() {
|
|
Class jsCategory = JobSheets.class;
|
|
Class jpCategory = JobPriority.class;
|
|
Class jnCategory = JobName.class;
|
|
Class unCategory = RequestingUserName.class;
|
|
boolean jsSupported = false;
|
|
boolean jpSupported = false;
|
|
boolean jnSupported = false;
|
|
boolean unSupported = false;
|
|
|
|
// setup JobSheets checkbox
|
|
if (psCurrent.isAttributeCategorySupported(jsCategory)) {
|
|
jsSupported = true;
|
|
}
|
|
JobSheets js = (JobSheets)asCurrent.get(jsCategory);
|
|
if (js == null) {
|
|
js = (JobSheets)psCurrent.getDefaultAttributeValue(jsCategory);
|
|
if (js == null) {
|
|
js = JobSheets.NONE;
|
|
}
|
|
}
|
|
cbJobSheets.setSelected(js != JobSheets.NONE);
|
|
cbJobSheets.setEnabled(jsSupported);
|
|
|
|
// setup JobPriority spinner
|
|
if (psCurrent.isAttributeCategorySupported(jpCategory)) {
|
|
jpSupported = true;
|
|
}
|
|
JobPriority jp = (JobPriority)asCurrent.get(jpCategory);
|
|
if (jp == null) {
|
|
jp = (JobPriority)psCurrent.getDefaultAttributeValue(jpCategory);
|
|
if (jp == null) {
|
|
jp = new JobPriority(1);
|
|
}
|
|
}
|
|
int value = jp.getValue();
|
|
if ((value < 1) || (value > 100)) {
|
|
value = 1;
|
|
}
|
|
snModel.setValue(new Integer(value));
|
|
lblPriority.setEnabled(jpSupported);
|
|
spinPriority.setEnabled(jpSupported);
|
|
|
|
// setup JobName text field
|
|
if (psCurrent.isAttributeCategorySupported(jnCategory)) {
|
|
jnSupported = true;
|
|
}
|
|
JobName jn = (JobName)asCurrent.get(jnCategory);
|
|
if (jn == null) {
|
|
jn = (JobName)psCurrent.getDefaultAttributeValue(jnCategory);
|
|
if (jn == null) {
|
|
jn = new JobName("", Locale.getDefault());
|
|
}
|
|
}
|
|
tfJobName.setText(jn.getValue());
|
|
tfJobName.setEnabled(jnSupported);
|
|
lblJobName.setEnabled(jnSupported);
|
|
|
|
// setup RequestingUserName text field
|
|
if (psCurrent.isAttributeCategorySupported(unCategory)) {
|
|
unSupported = true;
|
|
}
|
|
RequestingUserName un = (RequestingUserName)asCurrent.get(unCategory);
|
|
if (un == null) {
|
|
un = (RequestingUserName)psCurrent.getDefaultAttributeValue(unCategory);
|
|
if (un == null) {
|
|
un = new RequestingUserName("", Locale.getDefault());
|
|
}
|
|
}
|
|
tfUserName.setText(un.getValue());
|
|
tfUserName.setEnabled(unSupported);
|
|
lblUserName.setEnabled(unSupported);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* A special widget that groups a JRadioButton with an associated icon,
|
|
* placed to the left of the radio button.
|
|
*/
|
|
private class IconRadioButton extends JPanel {
|
|
|
|
private JRadioButton rb;
|
|
private JLabel lbl;
|
|
|
|
public IconRadioButton(String key, String img, boolean selected,
|
|
ButtonGroup bg, ActionListener al)
|
|
{
|
|
super(new FlowLayout(FlowLayout.LEADING));
|
|
|
|
Icon icon = new ImageIcon(getImageResource(img));
|
|
lbl = new JLabel(icon);
|
|
add(lbl);
|
|
|
|
rb = createRadioButton(key, al);
|
|
rb.setSelected(selected);
|
|
addToBG(rb, this, bg);
|
|
}
|
|
|
|
public void addActionListener(ActionListener al) {
|
|
rb.addActionListener(al);
|
|
}
|
|
|
|
public boolean isSameAs(Object source) {
|
|
return (rb == source);
|
|
}
|
|
|
|
public void setEnabled(boolean enabled) {
|
|
rb.setEnabled(enabled);
|
|
lbl.setEnabled(enabled);
|
|
}
|
|
|
|
public boolean isSelected() {
|
|
return rb.isSelected();
|
|
}
|
|
|
|
public void setSelected(boolean selected) {
|
|
rb.setSelected(selected);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Similar in functionality to the default JFileChooser, except this
|
|
* chooser will pop up a "Do you want to overwrite..." dialog if the
|
|
* user selects a file that already exists.
|
|
*/
|
|
private class ValidatingFileChooser extends JFileChooser {
|
|
public void approveSelection() {
|
|
File selected = getSelectedFile();
|
|
boolean exists;
|
|
|
|
try {
|
|
exists = selected.exists();
|
|
} catch (SecurityException e) {
|
|
exists = false;
|
|
}
|
|
|
|
if (exists) {
|
|
int val = JOptionPane.showConfirmDialog(this,
|
|
getMsg("dialog.overwrite"),
|
|
getMsg("dialog.owtitle"),
|
|
JOptionPane.YES_NO_OPTION);
|
|
|
|
if (val == JOptionPane.YES_OPTION) {
|
|
super.approveSelection();
|
|
}
|
|
} else {
|
|
super.approveSelection();
|
|
}
|
|
}
|
|
}
|
|
}
|