Package org.apache.harmony.x.print

Source Code of org.apache.harmony.x.print.ServiceUIDialog$PagesButtonChangeListener

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

/*
* ServiceUIDialog class - the class for the PrintService selecting
* and page setup dialogs.
*
* This class can be used in the following cases:
*
* 1. ServiceUI.printDialog(...) method calls this class to show dialog for the
*    PrintServices selecting;
*
* 2. Default implementation of java.awt.prin.PrinterJob class may call this
*    class to show dialogs in printDialog(), printDialog
*    (PrintRequestAttributeSet), pageDialog(), pageDialog(PageFormat) methods.
*    (Please, see org.apache.harmony.x.print.awt.PSPrinterJob class and
*    org.apache.harmony.x.print.DefaultPrinterJob test class as examples of
*    ServiceUIDialog using for the awt.print printing)
*
*
* Our printing dialogs look like competitor dialogs, however there are some
* distinctions and problems there:
*
* 1. Internationalization - will we internationalize the dialogs? It is not
*    internationalized yet.
*
* 2. Icons for Orientation ("Page Setup" tab) and Sides ("Appearance" tab) -
*    how to obtain them?
*
* 3. How to select Media attribute ("Page Setup" tab)? Competitor dialogs
*    contain "Source" and "Size" comboboxes. "Source" combobox contains
*    MediaTray list and "Size" combobox contains all the others Medias
*    including non-standard (i.e. MediaSizeName, MediaName and all the others
*    but the MediaTray). Do we really need both these comboboxes? Which Media
*    (from "Size" or "Source" combobox) should we add into the result
*    attribute set? Specification says nothing. Now I made "Source" combobox
*    invisible and add all the Medias supported by the selected PrintService
*    into the "Size" combobox.
*
* 4. How to use Margins fields ("Left (mm)", "Right (mm)", "Top (mm)",
*    "Bottom (mm)" fields in the "Page Setup" tab)?
*    There is only one standard printing attribute related with paper margins
*    - MediaPrintableArea. It is a printing attribute used to distingwish
*    printable and not printable areas of media. However, this attribute is
*    not described as the edges of the paper: MediaPrintableArea is defined
*    as a rectangle with its x and y coordinates and its width and height. So,
*    this attribute depends on selected media size. But printing dialog
*    contains input fields for margins, not for printable area. In other
*    words, we can construct MediaPrintableArea attribute (using dialog
*    margins input fields) for the result attribute set only if we can get
*    selected Media width and height, i.e. if selected media is MediaSizeName
*    attribute. To avoid this problem, we launched additional (non-standard)
*    printing attribute - MediaMargins. We suppose that our standard print
*    services will support this attribute.
*    As a standard java attribute, MediaPrintableArea always should have
*    the first priority in case of conflict between MediaPrintableArea and
*    MediaMargins attributes. It means, that if we have MediaSizeName,
*    MediaPrintableArea and MediaMargins in print request attribute set, we
*    should use MediaSizeName + MediaPrintableArea to calculate margins.
*    However, if we can not get Media size for the required media (for
*    example, for MediaTray), we may work with Margins attribute, if
*    PrintSerevice supports MediaMargins.
*    Using of MediaMargins attribute is also very convinient if we are setting
*    page parameters (for example, in standard page dialog) and do not know
*    Media which will be used for the printing yet.
*    Please, see fillMarginsFields() method for more details about the
*    MediaPrintableArea and MediaMargins attributes using in dialog result
*    attribute set.
*    Please, see also comments for the MediaMargins class.
*
* 5. Specification says nothing about the using of "Properties" button,
*    however it reads that if print service provides any vendor extention,
*    this extention may be accessibly throw additional vendor supplied
*    dialog tab panel.
*    So, I made "Properties" button invisible now and added "Vendor Supplied"
*    tab instead. I make "Vendor supplied" tab visible if selected print
*    service provides some kinds of vendor extentions.
*
* 6. The main problem is that current MRTD version does not support many Swing
*    components yet, so this dialog can not work now.
*/

package org.apache.harmony.x.print;

import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Panel;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FilePermission;
import java.net.URI;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.util.Locale;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.ServiceUIFactory;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.TextSyntax;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.CopiesSupported;
import javax.print.attribute.standard.Destination;
import javax.print.attribute.standard.JobName;
import javax.print.attribute.standard.JobPriority;
import javax.print.attribute.standard.JobSheets;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterInfo;
import javax.print.attribute.standard.PrinterIsAcceptingJobs;
import javax.print.attribute.standard.PrinterMakeAndModel;
import javax.print.attribute.standard.RequestingUserName;
import javax.print.attribute.standard.SheetCollate;
import javax.print.attribute.standard.Sides;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.NumberFormatter;

import org.apache.harmony.x.print.attributes.MediaMargins;


public class ServiceUIDialog extends ServiceUIDialogTemplate {

    // State of dialog:
    public static int APPROVE_PRINT = 1;    // OK button was pressed
    public static int CANSEL_PRINT = -1;    // Cancel button was pressed
    public static int SETUP_ERROR = 2;      // Dialog Setup was finished with
                                            // error, dialog can not be shown
    public static int SETUP_OK = 3;         // Dialog setup was OK,
                                            // you can show the dialog
    int dialogResult = 0;                   // Current dialog status
   
    // Dialog type:
    public static int PRINT_DIALOG = 1;     // Dialog for PrintService selecting,
                                            // all dialog tabs are visible
    public static int PAGE_DIALOG = 2;      // Page setup dialog:
                                            // only PageSetup dialog tab is visible
    private int dialogType = PRINT_DIALOG;  // dialog type
   
    PrintService [] services = null;        // Print services array for the choice
   
    private DocFlavor flavor = null;        // DocFlavor for the dialog
   
    private PrintRequestAttributeSet attrs = null;     
                                            // AttributeSet for the dialog creation
    private PrintRequestAttributeSet newAttrs = null;  
                                            // Result AttributeSet
   
    PrintService myService = null;          // Last selected PrintService
   
    // Button groups:
    ButtonGroup prnRngGrp = null;
    ButtonGroup orientGrp = null;
    ButtonGroup colorGrp = null;
    ButtonGroup sidesGrp = null;
    ButtonGroup qualGrp = null;
   
    // Last selected Orientation
    OrientationRequested lastOrient = null;
   
    // True means that dialog fields were not initialized yet.
    boolean firstUse = true;
   
    // Do we have permitions for the Destination attribute using?
    private Permission destPermission =
        new FilePermission("<<ALL FILES>>", "read,write");
   
    //---------------------------------------------------------------------
    /*
     * Constructor for the PRINT_DIALOG dialog type.
     * The dialog is modal.
     * It can be called from javax.print.ServiceUI.printDialog(...) and from
     * printDialog(), printDialog(PrintRequestAttributeSet) methods of default
     * java.awt.print.PrinterJob class implementation.
     *
     * Parameters:
     *  gc - GraphicsConfiguration to select screen. If gc is null, default screen
     *       is used.
     *  x - x location of the dialog in screen coordinates
     *  y - y location of the dialog in screen coordinates
     *  services - PrintServices array to be browsable (should be non-null)
     *  defPrintService - initially selected PrintService index in services array
     *                    (should be more then 0 and less then services array
     *                    length)
     *  flavor - printed DocFlavor (may be null)
     *  attrs - Initial print request attribute set. It can not be null, but may be
     *          empty. On output this attribute set reflects changes made by user.
     *  owner - dialog owner, should be Frame or Dialog.
     *
     * Throws:
     *  HeadlessException if current graphics environment is headless
     *
     * Set dialogResult to SETUP_ERROR if HeadlessException was thrown, owner is
     * not Frame or Dialog object, services array is null or empty, defServiceIndex
     * is incorrect or attrs is null; set dialogResult to SETUP_OK otherwise.
    */
    public ServiceUIDialog(GraphicsConfiguration gc,
                           int x,
                           int y,
                           PrintService[] dialogServices,
                           int defServiceIndex,
                           DocFlavor dialogFlavor,
                           PrintRequestAttributeSet dialogAttrs,
                           Window owner)
    {
        if (GraphicsEnvironment.isHeadless()) {
            dialogResult = SETUP_ERROR;
            throw new HeadlessException();
        }
   
        if (owner instanceof Frame) {
            printDialog = new JDialog((Frame)owner, "Print", true, gc);
        } else if(owner instanceof Dialog) {
            printDialog=new JDialog((Dialog)owner, "Print", true, gc);
        } else {
            dialogResult = SETUP_ERROR;
        }
   
        if (printDialog != null) {
            printDialog.setSize(542, 444);
            printDialog.setLocation(x, y);
            printDialog.setContentPane(getPanel());
            printDialog.setResizable(false);
            dialogResult = setup(dialogServices,
                                 defServiceIndex,
                                 dialogFlavor,
                                 dialogAttrs);
        }
    }
   
    /*
     * Constructor for the PAGE_DIALOG dialog type.
     * The dialog is modal.
     * It can be called from pageDialog(), pageDialog(PageFormat) methods of
     * default java.awt.print.PrinterJob class implementation.
     *
     * Parameters:
     *  gc - GraphicsConfiguration to select screen. If gc is null, default screen
     *       is used.
     *  x - x location of the dialog in screen coordinates
     *  y - y location of the dialog in screen coordinates
     *  aService - print service for this page dialog
     *  attrs - initial print request attribute set. It can not be null, but may be
     *          empty. On output this attribute set reflects changes made by user.
     *          Attributes not related with page foemat settings are ignored.
     *  owner - dialog owner, should be Frame or Dialog.
     *
     * Throws:
     *  HeadlessException if current graphics environment is headless
     *
     * Set dialogResult to SETUP_ERROR if HeadlessException was thrown, owner is
     * not Frame or Dialog object, aService or attrs is null.
    */
    public ServiceUIDialog(GraphicsConfiguration gc,
                           int x,
                           int y,
                           PrintService aService,
                           PrintRequestAttributeSet dialogAttrs,
                           Window owner) {
   
        dialogType = PAGE_DIALOG;
   
        if (GraphicsEnvironment.isHeadless()) {
            dialogResult = SETUP_ERROR;
            throw new HeadlessException();
        }
   
        if (owner instanceof Frame) {
            printDialog = new JDialog((Frame)owner, "Print", true, gc);
        } else if (owner instanceof Dialog) {
            printDialog=new JDialog((Dialog)owner, "Print", true, gc);
        } else {
            dialogResult = SETUP_ERROR;
        }
   
        if (printDialog != null) {
            printDialog.setSize(530, 400);
            printDialog.setLocation(x, y);
            printDialog.setContentPane(getPageDialogPanel());
            printDialog.setResizable(false);
            dialogResult = pageSetup(aService, dialogAttrs);
        }
    }
   
    // ---------------------------------------------------------------------
    /*
     * Shows the dialog if the dialog fields were successfully initialized before
    */
    public void show() {
        if (dialogResult == SETUP_OK) {
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    printDialog.show();
                    return null;
                }
            });      
        }
    }
   
    //---------------------------------------------------------------------
    /*
     * Initialization for PRINT_DIALOG dialog
     *
      * Parameters:
     *  services - PrintServices array to be browsable
     *  defPrintService - initially selected PrintService index in services array
     *  flavor - printed DocFlavor (may be null)
     *  attrs - Initial print request attribute set.
     *
     * Set dialogResult to SETUP_ERROR services array is null or empty,
     * defServiceIndex is incorrect or attrs is null; set dialogResult to SETUP_OK
     * otherwise.
    */
    private int setup(PrintService[] dialogServices,
                      int defServiceIndex,
                      DocFlavor dialogFlavor,
                      PrintRequestAttributeSet dialogAttrs)
    {
        if ((dialogServices == null)
                || (dialogServices.length <= 0)
                || (defServiceIndex < 0)
                || (defServiceIndex >= dialogServices.length)
                || (dialogAttrs == null)) {
            return SETUP_ERROR;
        }
   
        services = dialogServices;
        flavor = dialogFlavor;
        attrs = dialogAttrs;
        this.myService = services[defServiceIndex];
        if (servicesBox.getItemCount() <= 0) {
            for (int i = 0; i < services.length; i++) {
                servicesBox.addItem(services[i].getName());
            }
        }
        newAttrs = new HashPrintRequestAttributeSet(attrs);
   
        prepareDialog();        // Prepare dialog
        servicesBox.setSelectedIndex(defServiceIndex)
                                // Select default PrintService and
                                // initialize dialog fields
        firstUse = false;                              
        return SETUP_OK;
    }
   
    /*
     * Initialization for PAGE_DIALOG dialog
     * 
     * Parameters:
     *  aService - print service for this page dialog
     *  attrs - initial print request attribute set.
     *
     * Set dialogResult to SETUP_ERROR if aService or attrs is null.
    */
    private int pageSetup(PrintService aService,
                          PrintRequestAttributeSet requestAttrs)
    {
        myService = (aService == null
                ? PrintServiceLookup.lookupDefaultPrintService()
                : aService;
       
        if ((requestAttrs == null) || (aService == null)) {
            return SETUP_ERROR;
        }
       
        attrs = requestAttrs;
        newAttrs = new HashPrintRequestAttributeSet(attrs);
        myService = aService;
       
        prepareDialog();        // prepare dialog
        fillPageSetupFields()// Initialize dialog fields
        firstUse = false;
        return SETUP_OK;
    }
   
    /*
     * Dialog preparing: create button groups, add listeners to components, etc.
     * This method logically should belong to the ServiceUIDialogTemplate class,
     * however I place it in ServiceUIDialog because ServiceUIDialogTemplated was
     * generated automatically by Eclipse Visual Editor
    */
    private void prepareDialog() {
        JRadioButton [] orientArr = new JRadioButton [] {
                    portraitBtn, landscapeBtn, rvportraitBtn, rvlandscapeBtn };   
        organizeButtonGroup(orientGrp, orientArr);
   
        sourceBox.setVisible(false);
        sourceLabel.setVisible(false);
       
        if (dialogType == PRINT_DIALOG) {
            JRadioButton [] rangesArr  = new JRadioButton[] {
                    allRngBtn, pageRngBtn };
            JRadioButton [] colorsArr  = new JRadioButton[] { monoBtn, colorBtn };
            JRadioButton [] sidesArr   = new JRadioButton[] {
                    oneSideBtn, tumbleBtn, duplexBtn };
            JRadioButton [] qualityArr = new JRadioButton[] {
                    draftBtn, normalBtn, highBtn };
           
            organizeButtonGroup(prnRngGrp, rangesArr);
            organizeButtonGroup(colorGrp, colorsArr);
            organizeButtonGroup(sidesGrp,sidesArr);
            organizeButtonGroup(qualGrp, qualityArr);
           
            propertiesBtn.setVisible(false);
   
            prtSpinner.setModel(new SpinnerNumberModel(1, 1, 100, 1));
           
            cpSpinner.addChangeListener(new CopiesChangeListener());
            allRngBtn.addChangeListener(new PagesButtonChangeListener());
            pageRngBtn.addChangeListener(new PagesButtonChangeListener());
            servicesBox.addActionListener(new ServicesActionListener());
        }
   
        portraitBtn.addChangeListener(new OrientationChangeListener());
        landscapeBtn.addChangeListener(new OrientationChangeListener());
        rvportraitBtn.addChangeListener(new OrientationChangeListener());
        rvlandscapeBtn.addChangeListener(new OrientationChangeListener());
        printBtn.addActionListener(new OKButtonListener());
        cancelBtn.addActionListener(new cancelButtonListener());
       
        printDialog.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                dialogResult = CANSEL_PRINT;
            }
        });
    }
   
    /*
     * Adds all JRadioButtons from "buttons" array to "group" ButtonGroup
     */
    private void organizeButtonGroup(ButtonGroup group, JRadioButton[] buttons) {
        group = new ButtonGroup();
        for (int i = 0; i< buttons.length; i++) {
            group.add(buttons[i]);
        }
    }
   
    //---------------------------------------------------------------------
   
    /*
     * ActionListener for the PrintServices combo box:
     * Update all dialog fields if new print service is selected.
     * As the user browses print services, attributes and values are copied to new
     * display. If user select a print service which does not support particular
     * attribute value, default attribute for this print service is used instead.
     * Unsupported attributes fields are disabled for the selected print service.
    */
    class ServicesActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (firstUse 
                    || (myService != services[servicesBox.getSelectedIndex()])) {
                myService = services[servicesBox.getSelectedIndex()];
               
                fillGeneralFields();        // General standard tab
                fillPageSetupFields();      // Page Setup standard tab
                fillAppearanceFields();     // Appearance standard tab
                fillVendorSuppliedTab();    // vendor supplied tab (if exists)
            }
        }
    } /* End of ServiceActionListener class */
   
    //---------------------------------------------------------------------
    /*
     *General tab fields filling after PrintService selecting
    */
    void fillGeneralFields() {
        fillStatusField();
        fillTypeField();
        fillInfoField();
        filltoFileBox();
        fillCopiesFields();
        fillPrintRangeFields();
    }
   
    /*
     * "Status" field from "General" tab:
     * If selected print service does not support PrinterIsAcceptingJobs attribute,
     * "Status" field is empty. Otherwise, it is "Accepting jobs" if
     * PrinterIsAcceptingJob attribute for this print service is ACCEPTING_JOBS; or
     * "Not accepting jobs" if PrinterIsAcceptingJobs is NOT_ACCEPTING_JOBS. 
    */
    void fillStatusField() {
        String text;
        PrinterIsAcceptingJobs job = (PrinterIsAcceptingJobs)
                myService.getAttribute(PrinterIsAcceptingJobs.class);
        if (job != null) {
            text = job.equals(PrinterIsAcceptingJobs.ACCEPTING_JOBS)
                   ? "Accepting jobs"
                   : "Not accepting jobs";
        } else {
            text = "";
        }
   
        statusText.setText(text);
    }
   
    /*
     * "Type" field from "General" tab:
     * This field contains PrinterMakeAndModel attribute of selected print service
     * or is empty if service does not support PrinterMakeAndModel.
    */
    void fillTypeField() {
        PrinterMakeAndModel type = (PrinterMakeAndModel)
                myService.getAttribute(PrinterMakeAndModel.class);
        typeText.setText(type == null ? "" : type.getValue());
    }
   
    /*
     * "Info" field from "General" tab:
     * This field contains PrinterInfo attribute of selected print service
     * or is empty if service does not support PrinterInfo.
    */
    void fillInfoField() {
        PrinterInfo info = (PrinterInfo) myService.getAttribute(PrinterInfo.class);
        infoText.setText(info == null ? "" : info.getValue());
    }
   
    /*
     * "Print to file" combobox from "General" tab:
     * This combobox will be enabled if Destination attribute is supported by
     * selected print service and user can write to file.
    */
    void filltoFileBox() {
        if (firstUse && attrs.containsKey(Destination.class)) {
            toFileBox.setSelected(true);
        }
        toFileBox.setEnabled(checkFilePermission(destPermission)
                && myService.isAttributeCategorySupported(Destination.class));
    }
   
    /*
     * Checks if the user has given permission
     */
    boolean checkFilePermission(Permission permission) {
        SecurityManager manager = System.getSecurityManager();
        if (manager != null) {
            try {
                manager.checkPermission(permission);
                return true;
            }
            catch(SecurityException e) {
                return false;
            }
        }
        return true;
    }
   
    /*
     * Copies and Collate fields
    */
    void fillCopiesFields() {
        fillCopiesSpinner();
        fillCollateBox();
    }
   
    /*
     * "Number of copies" spinner from "General" tab:
     * It is enabled if selected printer supports Copies attribute. Maximum and
     * minimum values of the spinner are minimum and maximum supported Copies
     * values for selected print service.
    */
    void fillCopiesSpinner() {
        boolean isEnabled = myService.isAttributeCategorySupported(Copies.class);
       
        copiesLabel.setEnabled(isEnabled);
        cpSpinner.setEnabled(isEnabled);
   
        if (firstUse && !isEnabled) {
            int value = (attrs.containsKey(Copies.class)
                    ? ((Copies)(attrs.get(Copies.class))).getValue() : 1);
            cpSpinner.setModel(new SpinnerNumberModel(value, value, value, 1));
        }
   
        if (isEnabled) {
            int value = (firstUse && attrs.containsKey(Copies.class
                        ? ((Copies) (attrs.get(Copies.class))).getValue() 
                        : ((Integer) cpSpinner.getValue()).intValue());
            CopiesSupported supported = (CopiesSupported) myService
                    .getSupportedAttributeValues(Copies.class, flavor, attrs);
            Copies defaul = (Copies)
                    myService.getDefaultAttributeValue(Copies.class);
           
            if(supported == null) {
                /*
                 * It is incorrect situation, however it is possible: Copies
                 * category is supported, but there are no supported values. I
                 * suppose that only default Copies value is supported in this
                 * case. If default Copies value is null - I suppose that default
                 * and supported value is 1 Copy only.
                */
                supported = new CopiesSupported( (defaul == null)
                        ? defaul.getValue()
                        : 1);
            }
           
            int [][] range = supported.getMembers();
           
            if (!supported.contains(value)) {
                value = (((defaul == null)
                                || (!supported.contains(defaul.getValue())))
                        ? range[0][0]
                        : defaul.getValue());
            }
           
            cpSpinner.setModel(
                    new SpinnerNumberModel(value, range[0][0], range[0][1], 1));
        }
    }
   
    /*
     * Change listener for "Number of copies" spinner.
     * "Collate" combobox is enabled if Copies > 1 only
    */
    class CopiesChangeListener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            fillCollateBox();
        }
    }
   
    /*
     * "Collate" combobox from "General" tab.
     * This box will be enabled if more then one SheetCollate attribute
     * is supported by selected print service and "Number of copies" value > 1
    */
    void fillCollateBox() {
        boolean isSupported =
            myService.isAttributeCategorySupported(SheetCollate.class);
        SheetCollate [] supported = (SheetCollate []) (myService
                .getSupportedAttributeValues(SheetCollate.class, flavor, attrs));
        Attribute attr = attrs.get(SheetCollate.class);
        int spinnerValue = ((Integer) cpSpinner.getValue()).intValue();
       
        if ((supported == null) || !isSupported) {
            if (attrs.containsKey(SheetCollate.class)) {
                collateBox.setSelected(attr.equals(SheetCollate.COLLATED));
            }
        } else {
            boolean isValueSupported = myService.isAttributeValueSupported(
                    SheetCollate.COLLATED, flavor, attrs);
            if (attrs.containsKey(SheetCollate.class) && isValueSupported) {
                collateBox.setSelected(attr.equals(SheetCollate.COLLATED));
            } else {
                Object defaul =
                        myService.getDefaultAttributeValue(SheetCollate.class);
                collateBox.setSelected(defaul != null
                        ? defaul.equals(SheetCollate.COLLATED)
                        : true);
            }
        }
   
        collateBox.setEnabled(isSupported
                           && (spinnerValue > 1)
                           && (!(supported == null || supported.length <= 1)));
    }
   
    /*
     * "Print ranges" fields from "General" tab.
     * "From" and "to" text fields are enabled only if "Pages" radiobutton is
     * selected. If attr set does not contain PageRanges attribute, default value
     * is always "All".
    */
    void fillPrintRangeFields() {
        if (firstUse) {
            if (attrs.containsKey(PageRanges.class)) {
                PageRanges aRange = (PageRanges) (attrs.get(PageRanges.class));
                int [][] range = aRange.getMembers();
                fromTxt.setText(range.length > 0
                        ? Integer.toString(range[0][0]) : "1");
                toTxt.setText(range.length > 0
                        ? Integer.toString(range[0][1]) : "1");
                pageRngBtn.setSelected(true);
            } else {
                allRngBtn.setSelected(true);
                fromTxt.setEnabled(false);
                toTxt.setEnabled(false);
                fromTxt.setText("1");
                toTxt.setText("1");
                toLabel.setEnabled(false);
            }
        }
    }
   
    /*
     * Change listener for "Print Ranges" fields:
     * Range fields are enabled only if not all the pages should be printed, i.e.
     * if "Pages" button is selected. 
     */
    class PagesButtonChangeListener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            fromTxt.setEnabled(pageRngBtn.isSelected());
            toTxt.setEnabled(pageRngBtn.isSelected());
            toLabel.setEnabled(pageRngBtn.isSelected());
        }
    } /* End of PagesButtonChangeListener class */
   
    //---------------------------------------------------------------------
    /*
     * Page Setup fields filling after PrintService selecting
    */
    void fillPageSetupFields() {
        fillMediaFields();
        fillOrientationFields();
        fillMarginsFields();
    }
   
    /*
     * "Size" and "Source" comboboxes from "Page Setup" tab.
     *
     * I made "Source" combobox invisible because it is unclear how to work with
     * two different Media comboboxes in one dialog (please, see comments in the
     * beginning of the ServiceUIDialog class for more details).
     * Probably, we will need to change it in the future.
     *
     * "Size" combobox contains all medias supported by the selected print service.
     * It is disabled if given service does not support Media attribute or
     * supported media list is empty.
    */
    void fillMediaFields() {
        if (myService.isAttributeCategorySupported(Media.class)) {
            Media [] mediaList = (Media []) myService
                    .getSupportedAttributeValues(Media.class, flavor, attrs);
            Media oldMedia = (sizeBox.getItemCount() <= 0)
                    ? null
                    : (Media)sizeBox.getSelectedItem();
   
            sizeBox.removeAllItems();
            if ((mediaList != null) && (mediaList.length > 0)) {
                for(int i = 0; i < mediaList.length; i++) {
                    sizeBox.addItem(mediaList[i]);
                }
                selectMedia(oldMedia);
            }
            sizeBox.setEnabled((mediaList != null) && (mediaList.length > 0));
            sizeLabel.setEnabled((mediaList != null) && (mediaList.length > 0));
        } else {
            sizeBox.setEnabled(false);
            sizeLabel.setEnabled(false);
        }
        sizeBox.updateUI();
    }
   
    /*
     * Selects media in "Sizes" combobox. Selected media is previously
     * selected Media if it is supported by current print service.
     * Otherwise selected media Media from attrs (if it is supported) or default
     * Media for selected service.
    */
    void selectMedia(Media oldMedia) {
        if (sizeBox.getItemCount() > 0) {   
           
            /* if media was not set - get it from attributes */
            if ((oldMedia == null) && attrs.containsKey(Media.class)) {
                oldMedia = (Media) attrs.get(Media.class);
            }
            sizeBox.setSelectedItem(oldMedia);
       
            if ((sizeBox.getSelectedIndex() < 0)
                    || (!sizeBox.getSelectedItem().equals(oldMedia))) {
                Object media = myService.getDefaultAttributeValue(Media.class);
                if (media != null) {
                    sizeBox.setSelectedItem(media);
                }
            }
           
            /* select first media if there is still no selection */
            if (sizeBox.getSelectedIndex() < 0) {
                sizeBox.setSelectedIndex(0);
            }
        }
    }
   
    /*
     * "Orientation" radiobuttons from "Page Setup" tab.
     * All these buttons are disabled if selected print service does not support
     * OrientationRequested attribute. Only supported by service orientations
     * are enabled.
    */
    void fillOrientationFields() {
       
        OrientationRequested orient =
                (OrientationRequested) attrs.get(OrientationRequested.class);
        boolean isSupported =
                myService.isAttributeCategorySupported(OrientationRequested.class);
   
        OrientationRequested [] supportedList = (isSupported
                ? (OrientationRequested []) myService.getSupportedAttributeValues(
                        OrientationRequested.class, flavor, attrs)
                : null);
       
        enableOrient(supportedList);
         
        /* Select orientation at first time (orientation from attributes set or
           default orientation for this Print Service) */
        if (firstUse) {
            if (orient != null) {
                selectOrient(orient);  
            } else {
                OrientationRequested defaul = (OrientationRequested)
                    myService.getDefaultAttributeValue(OrientationRequested.class);
                selectOrient(isSupported ? defaul : null);
            }
        }
   
        /* Select orientation if previosly selected button is disabled now */
        if (supportedList != null) {
            OrientationRequested oldValue = getOrient();
            if (!orientEnabled(oldValue)) {
                selectOrient(orientEnabled(orient) ? orient : supportedList[0]);
            }
        }
    }
   
    /*
     * Select "Orientation" button corresponding to the given orientation
    */
    private void selectOrient(OrientationRequested par) {
        if (par == null) {
            par = OrientationRequested.PORTRAIT;
        }
        if (par.equals(OrientationRequested.LANDSCAPE)) {
            landscapeBtn.setSelected(true);
        } else if (par.equals(OrientationRequested.REVERSE_LANDSCAPE)) {
            rvlandscapeBtn.setSelected(true);
        } else if (par.equals(OrientationRequested.REVERSE_PORTRAIT)) {
            rvportraitBtn.setSelected(true);
        } else {
            portraitBtn.setSelected(true);
        }
    }
   
    /*
     enable/disable corresponding "Orientation" buttons
    */
    private void enableOrient(OrientationRequested[] list) {
        portraitBtn.setEnabled(false);
        landscapeBtn.setEnabled(false);
        rvportraitBtn.setEnabled(false);
        rvlandscapeBtn.setEnabled(false);
       
        if (list != null) {
            for (int i = 0; i < list.length; i++) {
                if (list[i].equals(OrientationRequested.LANDSCAPE)) {
                    landscapeBtn.setEnabled(true);
                } else if (list[i].equals(OrientationRequested.PORTRAIT)) {
                    portraitBtn.setEnabled(true);
                } else if (list[i].equals(OrientationRequested.REVERSE_LANDSCAPE)) {
                    rvlandscapeBtn.setEnabled(true);
                } else if (list[i].equals(OrientationRequested.REVERSE_PORTRAIT)) {
                    rvportraitBtn.setEnabled(true);
                }
            }
        }
    }
   
    /*
     * get selected orientation
    */
    OrientationRequested getOrient() {
        if (portraitBtn.isSelected()) {
            return OrientationRequested.PORTRAIT;
        } else if (landscapeBtn.isSelected()) {
            return OrientationRequested.LANDSCAPE;
        } else if (rvportraitBtn.isSelected()) {
            return OrientationRequested.REVERSE_PORTRAIT;
        } else if (rvlandscapeBtn.isSelected()) {
            return OrientationRequested.REVERSE_LANDSCAPE;
        } else {
            return null;
        }
    }
   
    /*
     * returns true if button for the given orientation is enabled
    */
    private boolean orientEnabled(OrientationRequested par) {
        if (par == null) {
            return false;
        } else if (par.equals(OrientationRequested.LANDSCAPE)) {
            return landscapeBtn.isEnabled();
        } else if (par.equals(OrientationRequested.PORTRAIT)) {
            return portraitBtn.isEnabled();
        } else if (par.equals(OrientationRequested.REVERSE_LANDSCAPE)) {
            return rvlandscapeBtn.isEnabled();
        } else if (par.equals(OrientationRequested.REVERSE_PORTRAIT)) {
            return rvportraitBtn.isEnabled();
        } else {
            return false;
        }
    }
   
    /*
     * return true if at least one orientation button is enabled,
     * i.e. at least one OrientationRequested attribute is supported.
    */
    private boolean isOrientSupported() {
        return landscapeBtn.isEnabled()
                || portraitBtn.isEnabled()
                || rvlandscapeBtn.isEnabled()
                || rvportraitBtn.isEnabled();
    }
   
    /*
     * Change listener for "Orientation" buttons:
     * "Margins" fields should be updated after the orientation is changed.
    */
    class OrientationChangeListener implements ChangeListener {
   
        public void stateChanged(ChangeEvent e) {
            OrientationRequested now = getOrient();
       
            if ((lastOrient != null) && (now != null) && (!lastOrient.equals(now))) {
                /* if orientation was really changed */
               
                String txt = leftTxt.getText();
       
                if ((lastOrient.equals(OrientationRequested.PORTRAIT)
                                && now.equals(OrientationRequested.LANDSCAPE))
                        || (lastOrient.equals(OrientationRequested.LANDSCAPE
                                && now.equals(OrientationRequested.REVERSE_PORTRAIT))
                        || (lastOrient.equals(OrientationRequested.REVERSE_PORTRAIT)
                                && now.equals(OrientationRequested.REVERSE_LANDSCAPE))
                        || (lastOrient.equals(OrientationRequested.REVERSE_LANDSCAPE)
                                && now.equals(OrientationRequested.PORTRAIT))) {
                    leftTxt.setText(bottomTxt.getText());
                    bottomTxt.setText(rightTxt.getText());
                    rightTxt.setText(topTxt.getText());
                    topTxt.setText(txt);
       
                } else if ((lastOrient.equals(OrientationRequested.PORTRAIT)
                                && now.equals(OrientationRequested.REVERSE_PORTRAIT))
                        || (lastOrient.equals(OrientationRequested.LANDSCAPE)
                                && now.equals(OrientationRequested.REVERSE_LANDSCAPE))
                        || (lastOrient.equals(OrientationRequested.REVERSE_PORTRAIT)
                                && now.equals(OrientationRequested.PORTRAIT))
                        || (lastOrient.equals(OrientationRequested.REVERSE_LANDSCAPE)
                                && now.equals(OrientationRequested.LANDSCAPE))) {
                    leftTxt.setText(rightTxt.getText());
                    rightTxt.setText(txt);
                    txt = topTxt.getText();
                    topTxt.setText(bottomTxt.getText());
                    bottomTxt.setText(txt);
               
                } else {
                    leftTxt.setText(topTxt.getText());
                    topTxt.setText(rightTxt.getText());
                    rightTxt.setText(bottomTxt.getText());
                    bottomTxt.setText(txt);
                }
            }
           
            if (now != null) {
                lastOrient = now;
            }
        }
    } /* End of OrientationChangeListener class */
   
    /*
     * "Margins" fields from "Page Setup" tab.
     *
     * These fields are related with Media, MediaPrintableArea and MediaMargins
     * attributes.
     * These fields are enabled if selected print service supports MediaMargins
     * attribute, or service supports Media + MediaPrintebleArea attributes and at
     * lease one Media is supported. They are also always enabled if this is a
     * PAGE_DIALOG.
     *
     * Meaning of this fields should be updated if Orientation is changed.
     *
     * When we initialize the dialog at first time, "Margins" values are
     * calculated using the following algorithm:
     *
     *  * 1. If MediaPrintableArea + Media attributes are supported, attrs set
     *    contains MediaPrintableArea and Media, Media attribute from attrs is
     *    supported by selected print service and this is MediaSizeName object
     *    (i.e. we can get size of this Media) and margins may be correctly
     *    calculated using these Media and MediaMargins attributes - we get
     *    margins from these Media and MediaPrintableArea.
     * 2. If margins fields are not defined yet and MediaMargins is supported by
     *    selected service or this is a page setup dialog, we get MediaMargins from
     *    attribute set (if it is present) or default MediaMargins for selected
     *    print service (if service has default MediaMargins)
     * 3. If margins fields are not defined yet, try to obtain MediaMargins from
     *    selected Media and default MediaPrintebleArea (if it is present) for
     *    selected print service. If margins can be calculated - fill "Margins"
     *    fields with these meanings.
     * 4. If margins fields are not defined yet, we set them just to some default
     *    meanings (25.4 mm).
     * 
     * Please, see also comments in the beginning of the ServiceUIDialog class.
    */
    void fillMarginsFields() {
        boolean isMediaSupported =
                myService.isAttributeCategorySupported(Media.class);
        boolean isPaSupported = myService
                .isAttributeCategorySupported(MediaPrintableArea.class);
        boolean isMarginsSupported = myService
                .isAttributeCategorySupported(MediaMargins.class);
       
        /* We enable margins fields if this is a PAGE_DIALOG or Media and
           MediaPrintableArea attributes are supported or MediaMargins attribute is
           supported by selected PrintService */
        boolean isMarginsEnabled = ((dialogType == PAGE_DIALOG)
                || isMarginsSupported 
                || (isMediaSupported
                        && isPaSupported
                        && (sizeBox.getSelectedItem() != null)));
       
        enableMargins(isMarginsEnabled);
   
        if (firstUse) {
            /* set margins at first time */
            MediaMargins margins = null;    // Margins for the dialog Margins fields
   
            if (isMarginsEnabled) { // Margins fields are enabled and can be edited
               
                Media selectedMedia = (Media) sizeBox.getSelectedItem();
                boolean isMediaSizeSelected = (selectedMedia == null)
                    ? false :
                    selectedMedia.getClass().isAssignableFrom(MediaSizeName.class);
                MediaSize selectedSize = isMediaSizeSelected
                    ? MediaSize.getMediaSizeForName((MediaSizeName) selectedMedia)
                    : null;
               
                if (isMediaSupported
                        && isPaSupported
                        && attrs.containsKey(Media.class)
                        && attrs.containsKey(MediaPrintableArea.class)
                        && attrs.get(Media.class).equals(selectedMedia)
                        && isMediaSizeSelected) {      
                    /* p.1 - see fillMarginsFields() comments above*/  
                    try {
                        MediaPrintableArea attrsPA = (MediaPrintableArea)
                                attrs.get(MediaPrintableArea.class);
                        margins = new MediaMargins(selectedSize, attrsPA);
                    } catch(IllegalArgumentException e) {
                        /*
                         * If we are unable to get correct margins values from the
                         * given MediaPrintableArea (attrsPA) and MediaSize
                         * (selectedSize), we just ignore this case
                         */
                    }
                }
   
                if ((margins == null)
                        && (isMarginsSupported || (dialogType == PAGE_DIALOG))) {
                    /* p.2 - see fillMarginsFields() comments above*/  
                    margins = (MediaMargins) (attrs.containsKey(MediaMargins.class)
                         ? attrs.get(MediaMargins.class)
                         : myService.getDefaultAttributeValue(MediaMargins.class));
                }
   
                if ((margins == null
                        && isPaSupported 
                        && isMediaSupported
                        && isMediaSizeSelected) {
                    /* p.3 - see fillMarginsFields() comments above*/  
                    try {
                        MediaPrintableArea defaultPA = (MediaPrintableArea)
                                myService.getDefaultAttributeValue(
                                        MediaPrintableArea.class);
                        if ((defaultPA != null) && (selectedSize != null)) {
                            margins = new MediaMargins(selectedSize, defaultPA);
                        }
                    } catch (IllegalArgumentException e) {
                        /*
                         * If we are unable to get correct margins value from the
                         * default MediaPrintableArea (defPA) for this service and
                         * MediaSize (selectedSize), we just ignoew this case.
                         */
                    }
                }
   
                if (margins == null) {
                    /* Just 25.4 mm margins! */
                    margins = new MediaMargins(25.4F, 25.4F, 25.4F, 25.4F,
                            MediaMargins.MM);
                }
   
            } else {   
                /* Margins fields are disabled, but we always set them to some
                   default meanings (25.4 mm) */
                margins = (attrs.containsKey(MediaMargins.class
                     ? (MediaMargins) attrs.get(MediaMargins.class)
                     : new MediaMargins(25.4F, 25.4F, 25.4F, 25.4F,
                             MediaMargins.MM));
            }
            setMargins(margins);
        }
    }
   
    /*
     * Enable/disable all Margins fields
     */
    private void enableMargins(boolean flg) {
        leftLabel.setEnabled(flg);
        rightLabel.setEnabled(flg);
        topLabel.setEnabled(flg);
        bottomLabel.setEnabled(flg);
        leftTxt.setEnabled(flg);
        rightTxt.setEnabled(flg);
        topTxt.setEnabled(flg);
        bottomTxt.setEnabled(flg);
    }
   
    /*
     * Set Margins dialog fields in accordance with the given MediaMargins object
    */
    private void setMargins(MediaMargins margins) {
        NumberFormatter fmt = getFloatFormatter();
        try {
            leftTxt.setText(fmt.valueToString(
                    new Float(margins.getX1(MediaMargins.MM))));
            rightTxt.setText(fmt.valueToString(
                    new Float(margins.getX2(MediaMargins.MM))));
            topTxt.setText(fmt.valueToString(
                    new Float(margins.getY1(MediaMargins.MM))));
            bottomTxt.setText(fmt.valueToString(
                    new Float(margins.getY2(MediaMargins.MM))));
        } catch (ParseException e) {
            /* Ignore incorrect float format */
        }
    }
   
    //---------------------------------------------------------------------
    /*
     * "Apparance" tab fields filling after new PrintService selecting
    */
    void fillAppearanceFields() {
        fillColorFields();
        fillQualityFields();
        fillSidesFields();
        fillJobAttributesFields();
    }
   
    /*
     * "Color" panel radiobuttons from "Appearance" tab.
     * The buttons are enabled only if selected service supports both COLOR and
     * MONOCHROME Chromaticity attributes. 
    */
    void fillColorFields() {
        boolean lastIsMonochrome = getLastColor();  
      
        monoBtn.setEnabled(false);
        colorBtn.setEnabled(false);
   
        if (myService.isAttributeCategorySupported(Chromaticity.class)) {
            Chromaticity [] supported = (Chromaticity []) (myService
                  .getSupportedAttributeValues(Chromaticity.class, flavor, attrs));
            if (supported != null) {
                if (supported.length == 1) {
                    lastIsMonochrome = setMonochrome(
                            (supported[0]).equals(Chromaticity.MONOCHROME));
                } else if (supported.length > 1) {
                    monoBtn.setEnabled(true);
                    colorBtn.setEnabled(true);
                }
            }
        }
   
        if (lastIsMonochrome) {
            monoBtn.setSelected(true);
        } else {
            colorBtn.setSelected(true);
        }
    }
   
    /*
     * get last selected Chromaticity button
     */
    private boolean getLastColor() {
        if (firstUse) {
            if (attrs.containsKey(Chromaticity.class)) {
                Attribute value = attrs.get(Chromaticity.class);
                return value.equals(Chromaticity.MONOCHROME);
            }
           
            Object defaul = myService.getDefaultAttributeValue(Chromaticity.class);
            return (myService.isAttributeCategorySupported(Chromaticity.class)
                        && (defaul != null))
                    ? defaul.equals(Chromaticity.MONOCHROME)
                    : true;
        }
   
        return monoBtn.isSelected();
    }
   
    private boolean setMonochrome(boolean flg) {
        monoBtn.setEnabled(flg);
        colorBtn.setEnabled(!flg);
        return flg;
    }
   
    /*
     * "Quality" panel radiobuttons from "Appearance" tab
     * Only supported by selected print service PrintQualities are enabled. 
    */
    void fillQualityFields() {
        PrintQuality quality = (PrintQuality) attrs.get(PrintQuality.class);
        if (firstUse) {
            selectQualityButton(quality);
        }
   
        PrintQuality [] aList = (
                myService.isAttributeCategorySupported(PrintQuality.class)
                ? (PrintQuality []) myService
                    .getSupportedAttributeValues(PrintQuality.class, flavor, attrs)
                : null);
        enableQualityButtons(aList);    /* enable qualities which are supported */
   
        /* select quality */
        if ((aList != null) && (!qualityIsEnabled(getSelectedQuality()))) {
            selectQualityButton(qualityIsEnabled(quality)
                    ? quality
                    : (PrintQuality) (myService
                            .getDefaultAttributeValue(PrintQuality.class)));
        }
    }
   
    /*
     * select "Quality" button for the given PrintQuality attribute
    */
    private void selectQualityButton(PrintQuality par) {
        if (par == null) {
            par = PrintQuality.NORMAL;
        }
        if (par.equals(PrintQuality.DRAFT)) {
            draftBtn.setSelected(true);
        } else if (par.equals(PrintQuality.HIGH)) {
            highBtn.setSelected(true);
        } else {
            normalBtn.setSelected(true);
        }
    }
   
    /*
     * enable "Quality" buttons for the PrintQuality attributes from the given list
    */
    private void enableQualityButtons(PrintQuality [] list) {
        normalBtn.setEnabled(false);
        draftBtn.setEnabled(false);
        highBtn.setEnabled(false);
    
        if (list != null) {
            for (int i = 0; i < list.length; i++) {
                if (list[i].equals(PrintQuality.DRAFT)) {
                    draftBtn.setEnabled(true);
                } else if (list[i].equals(PrintQuality.NORMAL)) {
                    normalBtn.setEnabled(true);
                } else if (list[i].equals(PrintQuality.HIGH)) {
                    highBtn.setEnabled(true);
                }
            }
        }
    }
   
    /*
     * return PrintQuality attribute for the selected "Quality" button
    */
    private PrintQuality getSelectedQuality() {
        if (normalBtn.isSelected()) {
            return PrintQuality.NORMAL;
        } else if (draftBtn.isSelected()) {
            return PrintQuality.DRAFT;
        } else if (highBtn.isSelected()) {
            return PrintQuality.HIGH;
        } else {
            return null;
        }
    }
   
    /*
     * returns true if "Quality" button for the given PrintQuality attribute
     * enabled
    */
    private boolean qualityIsEnabled(PrintQuality par) {
        if (par == null) {
            return false;
        } else if (par.equals(PrintQuality.NORMAL)) {
            return normalBtn.isEnabled();
        } else if (par.equals(PrintQuality.DRAFT)) {
            return draftBtn.isEnabled();
        } else if (par.equals(PrintQuality.HIGH)) {
            return highBtn.isEnabled();
        } else {
            return false;
        }
    }
   
    /*
     * returns true if at least one "Quality" button enabled
    */
    private boolean isQualitySupported() {
        return (normalBtn.isEnabled()
             || draftBtn.isEnabled()  
             || highBtn.isEnabled());
    }
   
    /*
     * "Sides" panel radiobuttons from "Appearance" tab
     * Only supported by selected print service Sides are enabled. 
    */
    void fillSidesFields() {
        Sides side = (Sides) attrs.get(Sides.class);
        if (firstUse) {
            selectSidesButton(side);
        }
   
        Sides [] aList = (myService.isAttributeCategorySupported(Sides.class)
                ? (Sides []) (myService.getSupportedAttributeValues(
                        Sides.class, flavor, attrs))
                : null);
        enableSidesButtons(aList);
   
        if ((aList != null) && !sideIsEnabled(getSelectedSide())) {
            selectSidesButton(sideIsEnabled(side)
                    ? side 
                    : (Sides) (myService.getDefaultAttributeValue(Sides.class)));
        }
    }
   
    /*
     * Select "Sides" button for the given Sides attribute
    */
    private void selectSidesButton(Sides par) {
        if (par == null) {
            par = Sides.ONE_SIDED;
        }
        if (par.equals(Sides.TUMBLE)
                || par.equals(Sides.TWO_SIDED_SHORT_EDGE)) {
            tumbleBtn.setSelected(true);
        } else if (par.equals(Sides.DUPLEX
                || par.equals(Sides.TWO_SIDED_LONG_EDGE)) {
            duplexBtn.setSelected(true);
        } else {
            oneSideBtn.setSelected(true);
        }
    }
   
    /*
     * enable "Sides" buttons for the Sides attributes from the given list
    */
    private void enableSidesButtons(Sides [] list) {
        oneSideBtn.setEnabled(false);
        duplexBtn.setEnabled(false);
        tumbleBtn.setEnabled(false);
       
        if (list != null) {
            for (int i = 0; i < list.length; i++) {
                if (list[i].equals(Sides.ONE_SIDED)) {
                    oneSideBtn.setEnabled(true);
                } else if (list[i].equals(Sides.DUPLEX)
                        || list[i].equals(Sides.TWO_SIDED_LONG_EDGE)) {
                    duplexBtn.setEnabled(true);
                } else if (list[i].equals(Sides.TUMBLE)
                        || list[i].equals(Sides.TWO_SIDED_SHORT_EDGE)) {
                    tumbleBtn.setEnabled(true);
                }
            }
        }
    }
   
    /*
     * returns Sides attribute object for the selected "Sides" button
    */
    private Sides getSelectedSide() {
        if (oneSideBtn.isSelected()) {
            return Sides.ONE_SIDED;
        } else if (duplexBtn.isSelected()) {
            return Sides.DUPLEX;
        } else if (tumbleBtn.isSelected()) {
            return Sides.TUMBLE;
        } else {
            return null;
        }
    }
   
    /*
     * returns true if "Sides" button for this Sides attribute enabled
    */
    private boolean sideIsEnabled(Sides par) {
        if (par == null) {
            return false;
        } else if (par.equals(Sides.ONE_SIDED)) {
            return oneSideBtn.isEnabled();
        } else if (par.equals(Sides.DUPLEX) ||
                   par.equals(Sides.TWO_SIDED_LONG_EDGE)) {
            return duplexBtn.isEnabled();
        } else if (par.equals(Sides.TUMBLE) ||
                   par.equals(Sides.TWO_SIDED_SHORT_EDGE)) {
            return tumbleBtn.isEnabled();
        } else {
            return false;
        }
    }
   
    /*
     * returns true if at least one "Sides" button is enabled
     * (that means at least one Sides attribute supported)
    */
    private boolean isSidesSupported() {
        return (oneSideBtn.isEnabled()
             || duplexBtn.isEnabled()
             || tumbleBtn.isEnabled());
    }
   
    /*
     * "Job Attribute" panel fields from "Appearance" tab
    */
    void fillJobAttributesFields() {
        fillBannerPageField();
        fillPriorityField();
        fillJobNameField();
        fillUserNameField();
    }
   
    /*
     * "Banner Page" checkbox from "Appearance" tab.
     * This checkbox is enabled if selected print service supports more then one
     * JobSheets attributes. This checkbox is selected if it is corresponds to
     * JobSheets.STANDARD attribute and unselected otherwise.
    */
    void fillBannerPageField() {
        JobSheets [] supported =
                (myService.isAttributeCategorySupported(JobSheets.class)
                ? (JobSheets[]) (myService.getSupportedAttributeValues(
                        JobSheets.class, flavor, attrs))
                : null);
        Attribute value = attrs.get(JobSheets.class);
   
        if ((supported != null) && (supported.length == 0)) {
            supported = null;
        }
   
        if (supported == null) {
            /* if PrintService does not supported any JobSheets, set current
               meaning from attribute set (if present) and disable checkbox */
            if (firstUse && attrs.containsKey(JobSheets.class)) {
                bannerBox.setSelected(value.equals(JobSheets.STANDARD));
            }
        } else {
            if (supported.length == 1) {
                bannerBox.setSelected(supported[0] == JobSheets.STANDARD);
            } else if (attrs.containsKey(JobSheets.class)) {
                bannerBox.setSelected(value.equals(JobSheets.STANDARD));
            else {
                Object def = myService.getDefaultAttributeValue(JobSheets.class);
                bannerBox.setSelected(def == null
                        ? false
                        : def.equals(JobSheets.STANDARD));
            }
        }
        bannerBox.setEnabled((supported != null) && (supported.length > 1));
    }
   
    /*
     * "Priority" spinner from "Appearance" tab.
     * It is enabled if selected print service supports JobPriority attribute.
    */
    void fillPriorityField() {
        boolean enabled =
                myService.isAttributeCategorySupported(JobPriority.class);
        priorityLabel.setEnabled(enabled);
        prtSpinner.setEnabled(enabled);
   
        if (firstUse) {
            if (attrs.containsKey(JobPriority.class)) {
                JobPriority value = (JobPriority) (attrs.get(JobPriority.class));
                prtSpinner.setValue(new Integer(value.getValue()));
            } else {
                if (enabled) {
                    JobPriority defaul = (JobPriority)  (
                            myService.getDefaultAttributeValue(JobPriority.class));
                    prtSpinner.setValue (defaul == null
                            ? new Integer(1)
                            : new Integer(defaul.getValue()));
                } else {
                    prtSpinner.setValue(new Integer(1));
                }
            }
        }
    }
   
    /*
     * "Job Name" text field from "Appearance" tab
     * It is enabled if selected print service supports JobName attribute.
    */
    void fillJobNameField() {
        boolean supported = myService.isAttributeCategorySupported(JobName.class);
        jobNameTxt.setEnabled(supported);
        jobNameLabel.setEnabled(supported);
   
        if (firstUse && attrs.containsKey(JobName.class)) {
            jobNameTxt.setText(((TextSyntax) attrs.get(JobName.class)).getValue());
        }
      
        if(supported && (jobNameTxt.getText().length() <= 0)) {
            TextSyntax txt = (TextSyntax)
                    (myService.getDefaultAttributeValue(JobName.class));
            jobNameTxt.setText(txt == null ? "" : txt.getValue());
        }
    }
   
    /*
     * "User Name" text field from "Appaerance" tab
     * It is enabled if selected print service supports RequestingUserName
     * attribute.
    */
    void fillUserNameField() {
        boolean flg =
            myService.isAttributeCategorySupported(RequestingUserName.class);
        userNameTxt.setEnabled(flg);
        userNameLabel.setEnabled(flg);
       
        if (firstUse && attrs.containsKey(RequestingUserName.class)) {
            userNameTxt.setText(((TextSyntax)
                    attrs.get(RequestingUserName.class)).getValue());
        }
      
        if (flg && (userNameTxt.getText().length() <= 0)) {
            RequestingUserName defaul = (RequestingUserName) (myService
                    .getDefaultAttributeValue(RequestingUserName.class));
            userNameTxt.setText(defaul==null ? "" : (String) (defaul.getValue()));
        }
    }
   
    //---------------------------------------------------------------------
    /*
     * We add Vendor supplied tab to the dialog panel if selected print service has
     * UIFactory and this factory has MAIN_UIROLE Panel or JComponent.
    */
    void fillVendorSuppliedTab() {
        ServiceUIFactory factory = myService.getServiceUIFactory();
   
        if (tabbedPane.getTabCount() > 3) {
            tabbedPane.remove(3);
        }
       
        if (factory != null) {
            JComponent swingUI = (JComponent) factory.getUI(
                    ServiceUIFactory.MAIN_UIROLE, ServiceUIFactory.JCOMPONENT_UI);
            if (swingUI != null) {
                tabbedPane.addTab("Vendor Supplied", swingUI);
                tabbedPane.setMnemonicAt(3, 'V');
            } else {
                Panel panelUI = (Panel) factory.getUI(ServiceUIFactory.MAIN_UIROLE,
                                                      ServiceUIFactory.PANEL_UI);
                if (panelUI != null) {
                    tabbedPane.addTab("Vendor Supplied", panelUI);
                    tabbedPane.setMnemonicAt(3, 'V');
                }
            }
        }
    }
   
    //---------------------------------------------------------------------
    /*
     * ActionListener for "Print" button:
     * if we can get correct result attribute set (newAttrs),
     * hides the dialog and set dialog result to APPROVE_PRINT
     */
    class OKButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (updateAttributes()) {   // form result attribute set for the dialog
                dialogResult = APPROVE_PRINT;
                printDialog.hide();
            }
        }
    } /* End of OKButtonListener */
   
    /*
     * ActionListener for "Cancel" button:
     * hides the dialog and set dialog result to CANCEL_PRINT.
     * This method does not change dialog result attribute set (newAttrs)
     */
    class cancelButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            dialogResult = CANSEL_PRINT;
            printDialog.hide();
        }
    } /* End of cancelButtonListener */
   
    /*
     * returns current dialogResult
     */
    public int getResult() {
        return dialogResult;
    }
   
    /*
     * returns result attribute set.
     */
    public PrintRequestAttributeSet getAttributes() {
        return newAttrs;
    }
   
    /*
     * returns result PrintService if dialogResult is APPROVE_PRINT
     */
    public PrintService getPrintService() {
        return (dialogResult == APPROVE_PRINT) ? myService : null;
    }
   
    /*
     * returns dialog's PrintServices list
     */
    public PrintService [] getServices() {
        return services;
    }
   
    /*
     * returns last selected PrintService
     */
    public PrintService getSelectedService() {
        return myService;
    }
   
    /*
     * returns dialog's docflavor
     */
    public DocFlavor getFlavor() {
        return flavor;
    }
   
    //---------------------------------------------------------------------
    /*
     * Getting result attribute set after OK button click
    */
    protected boolean updateAttributes() {
        newAttrs = new HashPrintRequestAttributeSet(attrs);
        if (dialogType == PRINT_DIALOG) {
            updateCopies();
            updateCollate();
            if (!updatePrintRange()) {
                JOptionPane.showMessageDialog(printDialog,
                                              "Incorrect Print Range!",
                                              "Incorrect parameter",
                                              JOptionPane.ERROR_MESSAGE);
                return false;
            }
            updateColor();
            updateQuality();
            updateSides();
            updateBannerPage();
            updatePriority();
            updateJobName();
            updateUserName();
            updatePrintToFile();
        }
        updateMedia();
        updateOrientation();
        if (!updateMargins()) {
            JOptionPane.showMessageDialog(printDialog,
                                          "Incorrect margins!",
                                          "Incorrect parameter",
                                          JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }
   
    /*
     * Select output file and add/update Destination attribute to the result
     * attribute set if "Print to file" box is enabled and selected.
     * Remove Destination attribute otherwise.
    */
    private void updatePrintToFile() {
        if (toFileBox.isEnabled() && toFileBox.isSelected()) {     
           
            Destination dest = (Destination)
                        (newAttrs.containsKey(Destination.class)
                    ? newAttrs.get(Destination.class)    
                    : myService.getDefaultAttributeValue(Destination.class));
            File file = null;
            DestinationChooser chooser = new DestinationChooser();
   
            if (dest == null) {
                dest = new Destination((new File("out.prn")).toURI());
                /* Default file name for the output file is "out.prn" */
            }
           
            try {
                file = new File(dest.getURI());
            } catch (Exception e) {
                file = new File("out.prn");
           
           
            chooser.setSelectedFile(file);
            chooser.setDialogTitle("Print to file");
            int chooserResult = chooser.showDialog(printDialog, "OK");
            if (chooserResult == JFileChooser.APPROVE_OPTION) {
                try {
                    URI selectedFile = chooser.getSelectedFile().toURI();
                    newAttrs.add(new Destination(selectedFile));
                } catch (Exception e) {
                    removeAttribute(Destination.class);
                }
            }
        } else {
            removeAttribute(Destination.class);
        }
    }
   
    /*
     * Add/update Copies attribute to the result attribute set if "Number of
     * copies" spinner is enabled. Remove Copies attribute otherwise.
    */
    private void updateCopies() {
        if (cpSpinner.isEnabled()) {
            int copiesValue = ((SpinnerNumberModel)
                    (cpSpinner.getModel())).getNumber().intValue();
            newAttrs.add(new Copies(copiesValue));
        } else {
            removeAttribute(Copies.class);
        }
    }
   
    /*
     * Add/update SheetCollate attribute to the result attribute set if "Collate"
     * checkbox is enabled. Remove SheetCollate attribute otherwise.
    */
    private void updateCollate() {
        if (collateBox.isEnabled()) {
            newAttrs.add(collateBox.isSelected()
                    ? SheetCollate.COLLATED
                    : SheetCollate.UNCOLLATED);
        } else {
            removeAttribute(SheetCollate.class);
        }
    }
   
    /*
     * Add/update PageRanges attribute to the result attribute set if "Pages"
     * radiobutton is selected and enabled and "from" <= "to". Remove PageRanges
     * otherwise. "All" is always default print range, so we do not need to add
     * PageRanges to the result attribute set if "All" button is selected.
     *
     * Returns false if "from" > "to" or "from" or "to" have incorrect number
     * format.
    */
    protected boolean updatePrintRange() {
        if (pageRngBtn.isEnabled() && pageRngBtn.isSelected()) {
            try {
                int fromValue = Integer.valueOf(fromTxt.getText()).intValue();
                int toValue = Integer.valueOf(toTxt.getText()).intValue();
                if (fromValue > toValue) {
                    throw new NumberFormatException();
                }
                newAttrs.add(new PageRanges(fromValue, toValue));
            } catch (NumberFormatException e) {
                return false;
            } catch (IllegalArgumentException e) {
                return false;           
            }
        } else {
            removeAttribute(PageRanges.class);
        }
        return true;
    }
   
    /*
     * Add Media attribute to result attribute set if "Size" combobox is enabled,
     * remove Media otherwise.
    */
    private void updateMedia() {
        if (sizeBox.isEnabled() && (sizeBox.getItemCount() > 0)) {
            newAttrs.add((Media) (sizeBox.getSelectedItem()));
        } else {
            removeAttribute(Media.class);
        }
    }
   
    /*
     * Add OrientationRequested attribute if selected service supports Orientation
     * attribute, remove OrientationRequested otherwise
    */
    private void updateOrientation() {
        if (isOrientSupported()) {
            newAttrs.add(getOrient());
        } else {
            removeAttribute(OrientationRequested.class);
        }
    }
   
    /*
     * If Margins fields are disabled, remove MediaPrintableArea and MediaMargins
     * from the result attribute set and returns true.
     * Otherwise try to add/update MediaPrintableArea attribute if print service
     * supports MediaPrintableArea, try to add/update MediaMargins attribute if
     * service supports MediaMargins attribute.
     *
     * Returns false if margins fields have incorrect number format or margins too
     * big for selected Media.
    */
    private boolean updateMargins() {
        float x1;
        float y1;
        float x2;
        float y2;   
        NumberFormatter format = getFloatFormatter();
   
        if (!leftTxt.isEnabled()) {
            removeAttribute(MediaPrintableArea.class);
            removeAttribute(MediaMargins.class);
            return true;
        }
   
        try {
            x1 = ((Float) format.stringToValue(leftTxt.getText())).floatValue();
            x2 = ((Float) format.stringToValue(rightTxt.getText())).floatValue();
            y1 = ((Float) format.stringToValue(topTxt.getText())).floatValue();
            y2 = ((Float) format.stringToValue(bottomTxt.getText())).floatValue();
        } catch(ParseException e) {
            return false;
        }
   
        if (sizeBox.isEnabled()
             && (sizeBox.getSelectedItem() instanceof MediaSizeName)
             && myService.isAttributeCategorySupported(MediaPrintableArea.class)) {
            MediaSize mediaSize = MediaSize.getMediaSizeForName(
                    (MediaSizeName) sizeBox.getSelectedItem());
            float paperWidth = mediaSize.getX(Size2DSyntax.MM);
            float paperHeight = mediaSize.getY(Size2DSyntax.MM);
            if ((x1 + x2 >= paperWidth) || (y1 + y2 >= paperHeight)) {
                return false;
            }
            newAttrs.add(new MediaPrintableArea(x1,
                                                y1,
                                                paperWidth - x1 - x2,
                                                paperHeight - y1 - y2,
                                                MediaPrintableArea.MM));
        } else {
            removeAttribute(MediaPrintableArea.class);
        }
   
        if (myService.isAttributeCategorySupported(MediaMargins.class)) {
            newAttrs.add(new MediaMargins(x1, y1, x2, y2, MediaMargins.MM));
        } else {
            removeAttribute(MediaMargins.class);
        }
        return true;
    }
   
    /*
     * Add/update Chromaticity attribute to the result attribute set if needed.
     * Remove Chromaticity otherwise.
    */
    private void updateColor() {
        if (monoBtn.isEnabled() && monoBtn.isSelected()) {
            newAttrs.add(Chromaticity.MONOCHROME);
        } else if (colorBtn.isEnabled() && colorBtn.isSelected()) {
            newAttrs.add(Chromaticity.COLOR);
        } else {
            removeAttribute(Chromaticity.class);
        }
    }
   
    /*
     * Add/update PrintQuality attribute to the result attribute set if print
     * service supports PrintQuality. Remove PrintQuality otherwise.
    */
    private void updateQuality() {
        if (isQualitySupported()) {
            newAttrs.add(getSelectedQuality());
        } else {
            removeAttribute(PrintQuality.class);
        }
    }
   
    /*
     * Add/update Sides attribute to the result attribute set if print service
     * supports Sides. Remove Sides otherwise.
    */
    private void updateSides() {
        if (isSidesSupported()) {
            newAttrs.add(getSelectedSide());
        } else {
            removeAttribute(Sides.class);
        }
    }
   
    /*
     * Add/update JobSheets attribute to the result attribute set if "Banner Page"
     * combobox box is enabled. Remove JobSheets otherwise.
    */
    private void updateBannerPage() {
        if (bannerBox.isEnabled()) {
            newAttrs.add(bannerBox.isSelected() 
                    ? JobSheets.STANDARD
                    : JobSheets.NONE);
        } else {
            removeAttribute(JobSheets.class);
        }
    }
   
    /*
     * Add/update JobPriority attribute to the result attribute set if "Priority"
     * spinner is enabled. Remove JobPriority otherwise.
    */
    private void updatePriority() {
        if (prtSpinner.isEnabled()) {
            int priority = ((Integer) (prtSpinner.getValue())).intValue();
            newAttrs.add(new JobPriority(priority));
        } else {
            removeAttribute(JobPriority.class);
        }
    }
   
    /*
     * Add/update JobName attribute to the result attribute set if "Job name" field
     * is enabled and is not empty. Remove JobName otherwise.
    */
    private void updateJobName() {
        if (jobNameTxt.isEnabled()) {
            String name = jobNameTxt.getText();
            if (name.length() == 0) {
                removeAttribute(JobName.class);
            } else {
                newAttrs.add(new JobName(name, Locale.getDefault()));
            }
        } else {
            removeAttribute(JobName.class);
        }
    }
   
    /*
     * Add/update JobName attribute to the result attribute set if "User name"
     * field is enabled and is not empty. Remove UserName otherwise.
    */
    private void updateUserName() {
        if (userNameTxt.isEnabled()) {
            String name = userNameTxt.getText();
            if (name.length() == 0) {
                removeAttribute(RequestingUserName.class);
            } else {
                newAttrs.add(new RequestingUserName(name, Locale.getDefault()));
            }
        } else {
            removeAttribute(RequestingUserName.class);
        }
    }
   
    private void removeAttribute(Class cls) {
        if (newAttrs.containsKey(cls)) {
            newAttrs.remove(cls);
        }
    }
   
    //---------------------------------------------------------------------
    /*
     * Panel for the Page Setup dialog
    */
    private JPanel getPageDialogPanel() {
        JPanel pageDialogPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gridBagConstraints182 = new GridBagConstraints();
        GridBagConstraints gridBagConstraints172 = new GridBagConstraints();
        pageDialogPanel.setPreferredSize(new java.awt.Dimension(100, 100));
        pageDialogPanel.setSize(532, 389);
        gridBagConstraints172.gridx = 0;
        gridBagConstraints172.gridy = 1;
        gridBagConstraints172.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints172.gridwidth = 3;
        gridBagConstraints182.gridx = 0;
        gridBagConstraints182.gridy = 0;
        gridBagConstraints182.weightx = 1.0;
        gridBagConstraints182.weighty = 1.0;
        gridBagConstraints182.fill = java.awt.GridBagConstraints.BOTH;
        pageDialogPanel.add(getButtonsPanel(), gridBagConstraints172);
        pageDialogPanel.add(getPageSetupPanel(), gridBagConstraints182);
        return pageDialogPanel;
    }
   
    //---------------------------------------------------------------------
    /*
     * JFileChooser for the selecting file for the Destination attribute.
     * Shows confirm message if the selected file is always exists
     */
    private class DestinationChooser extends JFileChooser {
       
        private static final long serialVersionUID = 5429146989329327138L;
       
        public void approveSelection() {
            boolean doesFileExists = false; // Does selected file exist?
            boolean result = true;      // File selection result
           
            try {
                doesFileExists = getSelectedFile().exists();
            } catch (Exception e) {
                /* if exception was thrown, fileExists flag remains false */
            }
           
            if (doesFileExists) {
                FilePermission delPermission = new FilePermission(
                        getSelectedFile().getAbsolutePath(), "delete");
                if (checkFilePermission(delPermission)) {
                    String msg = "File " + getSelectedFile() + " is already exists.\n" +
                                 "Do you want to overwrite it?";
                    int approveDelete = JOptionPane.showConfirmDialog(
                            null, "File exists!", msg, JOptionPane.YES_NO_OPTION);
                    result = (approveDelete == JOptionPane.YES_OPTION);          
                } else {
                    JOptionPane.showMessageDialog(
                            null, "Can not delete file " + getSelectedFile());
                    result = false;
                }
            }
       
            if (result) {
                super.approveSelection();
            }
        }
    } /* End of DestinationChooser class */
} /* End of ServiceUIDialog class */
 
TOP

Related Classes of org.apache.harmony.x.print.ServiceUIDialog$PagesButtonChangeListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.