/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

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.awt.print.PrinterJob;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
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;
import sun.print.SunPageSelection;
import java.awt.event.KeyEvent;
import java.net.URISyntaxException;
import java.lang.reflect.Field;


A class which implements a cross-platform print dialog.
Author: Chris Campbell
/** * A class which implements a cross-platform print dialog. * * @author Chris Campbell */
public class ServiceDialog extends JDialog implements ActionListener {
Waiting print status (user response pending).
/** * Waiting print status (user response pending). */
public final static int WAITING = 0;
Approve print status (user activated "Print" or "OK").
/** * Approve print status (user activated "Print" or "OK"). */
public final static int APPROVE = 1;
Cancel print status (user activated "Cancel");
/** * 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; private boolean isAWT = false; static { initResource(); }
Constructor for the "standard" print dialog (containing all relevant tabs)
/** * 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); }
Constructor for the "standard" print dialog (containing all relevant tabs)
/** * 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, Frame frame) { super(frame, getMsg("dialog.printtitle"), true, gc); initPrintDialog(x, y, services, defaultServiceIndex, flavor, attributes); }
Initialize print dialog.
/** * Initialize print dialog. */
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; SunPageSelection pages = (SunPageSelection)attributes.get(SunPageSelection.class); if (pages != null) { isAWT = true; } if (attributes.get(DialogOnTop.class) != null) { setAlwaysOnTop(true); } 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 = createExitButton("button.print", this); pnlSouth.add(btnApprove); getRootPane().setDefaultButton(btnApprove); btnCancel = createExitButton("button.cancel", this); handleEscKey(btnCancel); pnlSouth.add(btnCancel); c.add(pnlSouth, BorderLayout.SOUTH); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { dispose(CANCEL); } }); getAccessibleContext().setAccessibleDescription(getMsg("dialog.printtitle")); setResizable(false); setLocation(x, y); pack(); }
Constructor for the solitary "page setup" dialog
/** * 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); }
Constructor for the solitary "page setup" dialog
/** * Constructor for the solitary "page setup" dialog */
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); }
Initialize "page setup" dialog
/** * Initialize "page setup" dialog */
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); if (attributes.get(DialogOnTop.class) != null) { setAlwaysOnTop(true); } 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 = createExitButton("button.ok", this); pnlSouth.add(btnApprove); getRootPane().setDefaultButton(btnApprove); btnCancel = createExitButton("button.cancel", this); handleEscKey(btnCancel); pnlSouth.add(btnCancel); c.add(pnlSouth, BorderLayout.SOUTH); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { dispose(CANCEL); } }); getAccessibleContext().setAccessibleDescription(getMsg("dialog.pstitle")); setResizable(false); setLocation(x, y); pack(); }
Performs Cancel when Esc key is pressed.
/** * Performs Cancel when Esc key is pressed. */
private void handleEscKey(JButton btnCancel) { Action cancelKeyAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { dispose(CANCEL); } }; KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE, 0); InputMap inputMap = btnCancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = btnCancel.getActionMap(); if (inputMap != null && actionMap != null) { inputMap.put(cancelKeyStroke, "cancel"); actionMap.put("cancel", cancelKeyAction); } }
Returns the current status of the dialog (whether the user has selected the "Print" or "Cancel" button)
/** * 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.
/** * 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.
/** * 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)
/** * 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.isPrintToFileRequested()) { 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"
/** * 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)asOriginal.get(dstCategory); if (dst == null) { dst = (Destination)psCurrent.getDefaultAttributeValue(dstCategory); // "dst" should not be null. The following code // is only added to safeguard against a possible // buggy implementation of a PrintService having a // null default Destination. if (dst == null) { try { dst = new Destination(new URI("file:out.prn")); } catch (URISyntaxException e) { } } } } 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.setDialogTitle(getMsg("dialog.printtofile")); jfc.setDialogType(JFileChooser.SAVE_DIALOG); 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
/** * Updates each of the top level panels */
private void updatePanels() { pnlGeneral.updateInfo(); pnlPageSetup.updateInfo(); pnlAppearance.updateInfo(); }
Initialize ResourceBundle
/** * Initialize ResourceBundle */
public 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
/** * Returns message string from resource */
public static String getMsg(String key) { try { return removeMnemonics(messageRB.getString(key)); } catch (java.util.MissingResourceException e) { throw new Error("Fatal: Resource for ServiceUI is broken; " + "there is no " + key + " key in resource"); } } private static String removeMnemonics(String s) { int i = s.indexOf('&'); int len = s.length(); if (i < 0 || i == (len - 1)) { return s; } int j = s.indexOf('&', i+1); if (j == i+1) { if (j+1 == len) { return s.substring(0, i+1); // string ends with && } else { return s.substring(0, i+1) + removeMnemonics(s.substring(j+1)); } } // ok first & not double && if (i == 0) { return removeMnemonics(s.substring(1)); } else { return (s.substring(0, i) + removeMnemonics(s.substring(i+1))); } }
Returns mnemonic character from resource
/** * Returns mnemonic character from resource */
private static char getMnemonic(String key) { String str = messageRB.getString(key).replace("&&", ""); int index = str.indexOf('&'); if (0 <= index && index < str.length() - 1) { char c = str.charAt(index + 1); return Character.toUpperCase(c); } else { return (char)0; } }
Returns the mnemonic as a KeyEvent.VK constant from the resource.
/** * Returns the mnemonic as a KeyEvent.VK constant from the resource. */
static Class _keyEventClazz = null; private static int getVKMnemonic(String key) { String s = String.valueOf(getMnemonic(key)); if ( s == null || s.length() != 1) { return 0; } String vkString = "VK_" + s.toUpperCase(); try { if (_keyEventClazz == null) { _keyEventClazz= Class.forName("java.awt.event.KeyEvent", true, (ServiceDialog.class).getClassLoader()); } Field field = _keyEventClazz.getDeclaredField(vkString); int value = field.getInt(null); return value; } catch (Exception e) { } return 0; }
Returns URL for image resource
/** * Returns URL for image resource */
private static URL getImageResource(final String key) { URL url = (URL)java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { URL url = ServiceDialog.class.getResource( "resources/" + key); return url; } }); 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
/** * 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 JButton and sets its text, and ActionListener
/** * Creates a new JButton and sets its text, and ActionListener */
private static JButton createExitButton(String key, ActionListener al) { String str = getMsg(key); JButton btn = new JButton(str); btn.addActionListener(al); btn.getAccessibleContext().setAccessibleDescription(str); return btn; }
Creates a new JCheckBox and sets its text, mnemonic, and ActionListener
/** * 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
/** * 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"
/** * Creates a pop-up dialog for "no print service" */
public static void showNoPrintService(GraphicsConfiguration gc) { Frame dlgFrame = new Frame(gc); JOptionPane.showMessageDialog(dlgFrame, getMsg("dialog.noprintermsg")); dlgFrame.dispose(); }
Sets the constraints for the GridBagLayout and adds the Component to the given Container
/** * 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
/** * 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.
/** * 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 isPrintToFileRequested() { 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; private boolean filePermission; 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); lblStatus.setLabelFor(null); lblType = addLabel(getMsg("label.pstype"), gridbag, c); lblType.setLabelFor(null); c.gridwidth = 1; addToGB(new JLabel(getMsg("label.info"), JLabel.TRAILING), this, gridbag, c); c.gridwidth = GridBagConstraints.RELATIVE; lblInfo = new JLabel(); lblInfo.setLabelFor(null); addToGB(lblInfo, this, gridbag, c); c.gridwidth = GridBagConstraints.REMAINDER; cbPrintToFile = createCheckBox("checkbox.printtofile", this); addToGB(cbPrintToFile, this, gridbag, c); filePermission = allowedToPrintToFile(); } 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(); 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 { DocumentPropertiesUI docPropertiesUI = null; try { docPropertiesUI = (DocumentPropertiesUI)uiFactory.getUI (DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE, DocumentPropertiesUI.DOCPROPERTIESCLASSNAME); } catch (Exception ex) { } if (docPropertiesUI != null) { PrinterJobWrapper wrapper = (PrinterJobWrapper) asCurrent.get(PrinterJobWrapper.class); if (wrapper == null) { return; // should not happen, defensive only. } PrinterJob job = wrapper.getPrinterJob(); if (job == null) { return; // should not happen, defensive only. } PrintRequestAttributeSet newAttrs = docPropertiesUI.showDocumentProperties (job, ServiceDialog.this, psCurrent, asCurrent); if (newAttrs != null) { asCurrent.addAll(newAttrs); updatePanels(); } } } } } } 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; Destination dest = (Destination)asOriginal.get(Destination.class); // to preserve the state of Print To File if ((dest != null || isPrintToFileSelected()) && psCurrent.isAttributeCategorySupported( Destination.class)) { if (dest != null) { asCurrent.add(dest); } else { dest = (Destination)psCurrent. getDefaultAttributeValue(Destination.class); // "dest" should not be null. The following code // is only added to safeguard against a possible // buggy implementation of a PrintService having a // null default Destination. if (dest == null) { try { dest = new Destination(new URI("file:out.prn")); } catch (URISyntaxException ue) { } } if (dest != null) { asCurrent.add(dest); } } } else { asCurrent.remove(Destination.class); } } } } } 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
/** * 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.
/** * 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 = filePermission ? allowedToPrintToFile() : false; // 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 && dstSupported); // 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, rbSelect; 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); // Selection never seemed to work so I'm commenting this part. /* if (isAWT) { JPanel pnlMiddle = new JPanel(new FlowLayout(FlowLayout.LEADING)); rbSelect = createRadioButton("radiobutton.selection", this); bg.add(rbSelect); pnlMiddle.add(rbSelect); addToGB(pnlMiddle, 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); tfRangeFrom.getAccessibleContext().setAccessibleName( getMsg("radiobutton.rangepages")); 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); tfRangeTo.getAccessibleContext().setAccessibleName( getMsg("label.rangeto")); pnlBottom.add(tfRangeTo); addToGB(pnlBottom, this, gridbag, c); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); SunPageSelection select = SunPageSelection.ALL; setupRangeWidgets(); if (source == rbAll) { asCurrent.add(prAll); } else if (source == rbSelect) { select = SunPageSelection.SELECTION; } else if (source == rbPages || source == tfRangeFrom || source == tfRangeTo) { updateRangeAttribute(); select = SunPageSelection.RANGE; } if (isAWT) { asCurrent.add(select); } } 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) || isAWT) { prSupported = true; } SunPageSelection select = SunPageSelection.ALL; int min = 1; int max = 1; PageRanges pr = (PageRanges)asCurrent.get(prCategory); if (pr != null) { if (!pr.equals(prAll)) { select = SunPageSelection.RANGE; int[][] members = pr.getMembers(); if ((members.length > 0) && (members[0].length > 1)) { min = members[0][0]; max = members[0][1]; } } } if (isAWT) { select = (SunPageSelection)asCurrent.get( SunPageSelection.class); } if (select == SunPageSelection.ALL) { rbAll.setSelected(true); } else if (select == SunPageSelection.SELECTION) { // Comment this for now - rbSelect is not initialized // because Selection button is not added. // See PrintRangePanel above. //rbSelect.setSelected(true); } else { // RANGE rbPages.setSelected(true); } tfRangeFrom.setValue(new Integer(min)); tfRangeTo.setValue(new Integer(max)); 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.getAccessibleContext().setAccessibleName( getMsg("label.numcopies")); addToGB(lblCopies, this, gridbag, c); snModel = new SpinnerNumberModel(1, 1, 999, 1); spinCopies = new JSpinner(snModel); lblCopies.setLabelFor(spinCopies); // 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(); if (isAWT) { cbCollate.setEnabled(true); } else { 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.getSupportedAttributeValues( cpCategory, null, null); 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.
/** * 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); leftMargin.getAccessibleContext().setAccessibleName( getMsg("label.leftmargin")); rightMargin = new JFormattedTextField(nf); rightMargin.addFocusListener(this); rightMargin.addActionListener(this); rightMargin.getAccessibleContext().setAccessibleName( getMsg("label.rightmargin")); topMargin = new JFormattedTextField(nf); topMargin.addFocusListener(this); topMargin.addActionListener(this); topMargin.getAccessibleContext().setAccessibleName( getMsg("label.topmargin")); topMargin = new JFormattedTextField(nf); bottomMargin = new JFormattedTextField(nf); bottomMargin.addFocusListener(this); bottomMargin.addActionListener(this); bottomMargin.getAccessibleContext().setAccessibleName( getMsg("label.bottommargin")); topMargin = new JFormattedTextField(nf); 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() { if (isAWT) { leftMargin.setEnabled(false); rightMargin.setEnabled(false); topMargin.setEnabled(false); bottomMargin.setEnabled(false); lblLeft.setEnabled(false); lblRight.setEnabled(false); lblTop.setEnabled(false); lblBottom.setEnabled(false); return; } 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); MediaTray newTray = (MediaTray)sources.get(index - 1); Media m = (Media)asCurrent.get(Media.class); if (m == null || m instanceof MediaTray) { asCurrent.add(newTray); } else if (m instanceof MediaSizeName) { MediaSizeName msn = (MediaSizeName)m; Media def = (Media)psCurrent.getDefaultAttributeValue(Media.class); if (def instanceof MediaSizeName && def.equals(msn)) { asCurrent.add(newTray); } else { /* Non-default paper size, so need to store tray * as SunAlternateMedia */ asCurrent.add(new SunAlternateMedia(newTray)); } } } 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); if (isAWT) { cbSource.setEnabled(false); lblSource.setEnabled(false); } else { cbSource.setEnabled(mediaSupported); } if (mediaSupported) { Media medium = (Media)asCurrent.get(mdCategory); // initialize size selection to default Media defMedia = (Media)psCurrent.getDefaultAttributeValue(mdCategory); if (defMedia instanceof MediaSizeName) { cbSize.setSelectedIndex(sizes.size() > 0 ? sizes.indexOf(defMedia) : -1); } if (medium == null || !psCurrent.isAttributeValueSupported(medium, docFlavor, asCurrent)) { medium = defMedia; if (medium == null) { if (sizes.size() > 0) { medium = (Media)sizes.get(0); } } if (medium != null) { asCurrent.add(medium); } } 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))) { MediaTray mt = (MediaTray)sources.get(selIndex-1); if (medium instanceof MediaTray) { asCurrent.add(mt); } else { asCurrent.add(new SunAlternateMedia(mt)); } } } 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.png", true, bg, this); rbPortrait.addActionListener(this); addToGB(rbPortrait, this, gridbag, c); rbLandscape = new IconRadioButton("radiobutton.landscape", "orientLandscape.png", false, bg, this); rbLandscape.addActionListener(this); addToGB(rbLandscape, this, gridbag, c); rbRevPortrait = new IconRadioButton("radiobutton.revportrait", "orientRevPortrait.png", false, bg, this); rbRevPortrait.addActionListener(this); addToGB(rbRevPortrait, this, gridbag, c); rbRevLandscape = new IconRadioButton("radiobutton.revlandscape", "orientRevLandscape.png", 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 (isAWT) { pSupported = true; lSupported = true; } else 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 || !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory); // need to validate if default is not supported if ((or != null) && !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { or = null; Object values = psCurrent.getSupportedAttributeValues(orCategory, docFlavor, asCurrent); if (values instanceof OrientationRequested[]) { OrientationRequested[] orValues = (OrientationRequested[])values; if (orValues.length > 1) { // get the first in the list or = orValues[0]; } } } if (or == null) { or = OrientationRequested.PORTRAIT; } asCurrent.add(or); } 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.
/** * 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 (isAWT) { monoSupported = true; colorSupported = true; } else 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 (isAWT) { draftSupported = true; normalSupported = true; highSupported = true; } else 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.png", true, bg, this); rbOneSide.addActionListener(this); addToGB(rbOneSide, this, gridbag, c); rbTumble = new IconRadioButton("radiobutton.tumble", "tumble.png", false, bg, this); rbTumble.addActionListener(this); addToGB(rbTumble, this, gridbag, c); rbDuplex = new IconRadioButton("radiobutton.duplex", "duplex.png", 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")); pnlTop.add(lblPriority); snModel = new SpinnerNumberModel(1, 1, 100, 1); spinPriority = new JSpinner(snModel); lblPriority.setLabelFor(spinPriority); // REMIND ((JSpinner.NumberEditor)spinPriority.getEditor()).getTextField().setColumns(3); spinPriority.addChangeListener(this); pnlTop.add(spinPriority); c.anchor = GridBagConstraints.LINE_END; c.gridwidth = GridBagConstraints.REMAINDER; pnlTop.getAccessibleContext().setAccessibleName( getMsg("label.priority")); 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(); lblJobName.setLabelFor(tfJobName); tfJobName.addFocusListener(this); tfJobName.setFocusAccelerator(jmnemonic); tfJobName.getAccessibleContext().setAccessibleName( getMsg("label.jobname")); 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(); lblUserName.setLabelFor(tfUserName); tfUserName.addFocusListener(this); tfUserName.setFocusAccelerator(umnemonic); tfUserName.getAccessibleContext().setAccessibleName( getMsg("label.username")); 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 (!isAWT && 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 (!isAWT && 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.
/** * 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)); final URL imgURL = getImageResource(img); Icon icon = (Icon)java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { Icon icon = new ImageIcon(imgURL); return icon; } }); 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.
/** * 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; val = JOptionPane.showConfirmDialog(this, getMsg("dialog.overwrite"), getMsg("dialog.owtitle"), JOptionPane.YES_NO_OPTION); if (val != JOptionPane.YES_OPTION) { return; } } try { if (selected.createNewFile()) { selected.delete(); } } catch (IOException ioe) { JOptionPane.showMessageDialog(this, getMsg("dialog.writeerror")+" "+selected, getMsg("dialog.owtitle"), JOptionPane.WARNING_MESSAGE); return; } catch (SecurityException se) { //There is already file read/write access so at this point // only delete access is denied. Just ignore it because in // most cases the file created in createNewFile gets // overwritten anyway. } File pFile = selected.getParentFile(); if ((selected.exists() && (!selected.isFile() || !selected.canWrite())) || ((pFile != null) && (!pFile.exists() || (pFile.exists() && !pFile.canWrite())))) { JOptionPane.showMessageDialog(this, getMsg("dialog.writeerror")+" "+selected, getMsg("dialog.owtitle"), JOptionPane.WARNING_MESSAGE); return; } super.approveSelection(); } } }