Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.swing.plaf.basic;
   27   
   28   import sun.swing.DefaultLookup;
   29   import sun.swing.UIAction;
   30   import javax.swing.border.Border;
   31   import javax.swing.border.EmptyBorder;
   32   import javax.swing;
   33   import javax.swing.event;
   34   import javax.swing.plaf.ActionMapUIResource;
   35   import javax.swing.plaf.ComponentUI;
   36   import javax.swing.plaf.OptionPaneUI;
   37   import java.awt;
   38   import java.awt.event;
   39   import java.beans.PropertyChangeEvent;
   40   import java.beans.PropertyChangeListener;
   41   import java.util.Locale;
   42   import java.security.AccessController;
   43   
   44   import sun.security.action.GetPropertyAction;
   45   
   46   
   47   /**
   48    * Provides the basic look and feel for a <code>JOptionPane</code>.
   49    * <code>BasicMessagePaneUI</code> provides a means to place an icon,
   50    * message and buttons into a <code>Container</code>.
   51    * Generally, the layout will look like:<p>
   52    * <pre>
   53    *        ------------------
   54    *        | i | message    |
   55    *        | c | message    |
   56    *        | o | message    |
   57    *        | n | message    |
   58    *        ------------------
   59    *        |     buttons    |
   60    *        |________________|
   61    * </pre>
   62    * icon is an instance of <code>Icon</code> that is wrapped inside a
   63    * <code>JLabel</code>.  The message is an opaque object and is tested
   64    * for the following: if the message is a <code>Component</code> it is
   65    * added to the <code>Container</code>, if it is an <code>Icon</code>
   66    * it is wrapped inside a <code>JLabel</code> and added to the
   67    * <code>Container</code> otherwise it is wrapped inside a <code>JLabel</code>.
   68    * <p>
   69    * The above layout is used when the option pane's
   70    * <code>ComponentOrientation</code> property is horizontal, left-to-right.
   71    * The layout will be adjusted appropriately for other orientations.
   72    * <p>
   73    * The <code>Container</code>, message, icon, and buttons are all
   74    * determined from abstract methods.
   75    *
   76    * @author James Gosling
   77    * @author Scott Violet
   78    * @author Amy Fowler
   79    */
   80   public class BasicOptionPaneUI extends OptionPaneUI {
   81   
   82       public static final int MinimumWidth = 262;
   83       public static final int MinimumHeight = 90;
   84   
   85       private static String newline;
   86   
   87       /**
   88        * <code>JOptionPane</code> that the receiver is providing the
   89        * look and feel for.
   90        */
   91       protected JOptionPane         optionPane;
   92   
   93       protected Dimension minimumSize;
   94   
   95       /** JComponent provide for input if optionPane.getWantsInput() returns
   96        * true. */
   97       protected JComponent          inputComponent;
   98   
   99       /** Component to receive focus when messaged with selectInitialValue. */
  100       protected Component           initialFocusComponent;
  101   
  102       /** This is set to true in validateComponent if a Component is contained
  103        * in either the message or the buttons. */
  104       protected boolean             hasCustomComponents;
  105   
  106       protected PropertyChangeListener propertyChangeListener;
  107   
  108       private Handler handler;
  109   
  110   
  111       static {
  112           newline = (String)java.security.AccessController.doPrivileged(
  113                                   new GetPropertyAction("line.separator"));
  114           if (newline == null) {
  115               newline = "\n";
  116           }
  117       }
  118   
  119       static void loadActionMap(LazyActionMap map) {
  120           map.put(new Actions(Actions.CLOSE));
  121           BasicLookAndFeel.installAudioActionMap(map);
  122       }
  123   
  124   
  125   
  126       /**
  127         * Creates a new BasicOptionPaneUI instance.
  128         */
  129       public static ComponentUI createUI(JComponent x) {
  130           return new BasicOptionPaneUI();
  131       }
  132   
  133       /**
  134         * Installs the receiver as the L&F for the passed in
  135         * <code>JOptionPane</code>.
  136         */
  137       public void installUI(JComponent c) {
  138           optionPane = (JOptionPane)c;
  139           installDefaults();
  140           optionPane.setLayout(createLayoutManager());
  141           installComponents();
  142           installListeners();
  143           installKeyboardActions();
  144       }
  145   
  146       /**
  147         * Removes the receiver from the L&F controller of the passed in split
  148         * pane.
  149         */
  150       public void uninstallUI(JComponent c) {
  151           uninstallComponents();
  152           optionPane.setLayout(null);
  153           uninstallKeyboardActions();
  154           uninstallListeners();
  155           uninstallDefaults();
  156           optionPane = null;
  157       }
  158   
  159       protected void installDefaults() {
  160           LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
  161                                            "OptionPane.foreground", "OptionPane.font");
  162           LookAndFeel.installBorder(optionPane, "OptionPane.border");
  163           minimumSize = UIManager.getDimension("OptionPane.minimumSize");
  164           LookAndFeel.installProperty(optionPane, "opaque", Boolean.TRUE);
  165       }
  166   
  167       protected void uninstallDefaults() {
  168           LookAndFeel.uninstallBorder(optionPane);
  169       }
  170   
  171       protected void installComponents() {
  172           optionPane.add(createMessageArea());
  173   
  174           Container separator = createSeparator();
  175           if (separator != null) {
  176               optionPane.add(separator);
  177           }
  178           optionPane.add(createButtonArea());
  179           optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
  180       }
  181   
  182       protected void uninstallComponents() {
  183           hasCustomComponents = false;
  184           inputComponent = null;
  185           initialFocusComponent = null;
  186           optionPane.removeAll();
  187       }
  188   
  189       protected LayoutManager createLayoutManager() {
  190           return new BoxLayout(optionPane, BoxLayout.Y_AXIS);
  191       }
  192   
  193       protected void installListeners() {
  194           if ((propertyChangeListener = createPropertyChangeListener()) != null) {
  195               optionPane.addPropertyChangeListener(propertyChangeListener);
  196           }
  197       }
  198   
  199       protected void uninstallListeners() {
  200           if (propertyChangeListener != null) {
  201               optionPane.removePropertyChangeListener(propertyChangeListener);
  202               propertyChangeListener = null;
  203           }
  204           handler = null;
  205       }
  206   
  207       protected PropertyChangeListener createPropertyChangeListener() {
  208           return getHandler();
  209       }
  210   
  211       private Handler getHandler() {
  212           if (handler == null) {
  213               handler = new Handler();
  214           }
  215           return handler;
  216       }
  217   
  218       protected void installKeyboardActions() {
  219           InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
  220   
  221           SwingUtilities.replaceUIInputMap(optionPane, JComponent.
  222                                          WHEN_IN_FOCUSED_WINDOW, map);
  223   
  224           LazyActionMap.installLazyActionMap(optionPane, BasicOptionPaneUI.class,
  225                                              "OptionPane.actionMap");
  226       }
  227   
  228       protected void uninstallKeyboardActions() {
  229           SwingUtilities.replaceUIInputMap(optionPane, JComponent.
  230                                          WHEN_IN_FOCUSED_WINDOW, null);
  231           SwingUtilities.replaceUIActionMap(optionPane, null);
  232       }
  233   
  234       InputMap getInputMap(int condition) {
  235           if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
  236               Object[] bindings = (Object[])DefaultLookup.get(
  237                                optionPane, this, "OptionPane.windowBindings");
  238               if (bindings != null) {
  239                   return LookAndFeel.makeComponentInputMap(optionPane, bindings);
  240               }
  241           }
  242           return null;
  243       }
  244   
  245       /**
  246        * Returns the minimum size the option pane should be. Primarily
  247        * provided for subclassers wishing to offer a different minimum size.
  248        */
  249       public Dimension getMinimumOptionPaneSize() {
  250           if (minimumSize == null) {
  251               return new Dimension(MinimumWidth, MinimumHeight);
  252           }
  253           return new Dimension(minimumSize.width,
  254                                minimumSize.height);
  255       }
  256   
  257       /**
  258        * If <code>c</code> is the <code>JOptionPane</code> the receiver
  259        * is contained in, the preferred
  260        * size that is returned is the maximum of the preferred size of
  261        * the <code>LayoutManager</code> for the <code>JOptionPane</code>, and
  262        * <code>getMinimumOptionPaneSize</code>.
  263        */
  264       public Dimension getPreferredSize(JComponent c) {
  265           if ((JOptionPane)c == optionPane) {
  266               Dimension            ourMin = getMinimumOptionPaneSize();
  267               LayoutManager        lm = c.getLayout();
  268   
  269               if (lm != null) {
  270                   Dimension         lmSize = lm.preferredLayoutSize(c);
  271   
  272                   if (ourMin != null)
  273                       return new Dimension
  274                           (Math.max(lmSize.width, ourMin.width),
  275                            Math.max(lmSize.height, ourMin.height));
  276                   return lmSize;
  277               }
  278               return ourMin;
  279           }
  280           return null;
  281       }
  282   
  283       /**
  284        * Messaged from installComponents to create a Container containing the
  285        * body of the message. The icon is the created by calling
  286        * <code>addIcon</code>.
  287        */
  288       protected Container createMessageArea() {
  289           JPanel top = new JPanel();
  290           Border topBorder = (Border)DefaultLookup.get(optionPane, this,
  291                                                "OptionPane.messageAreaBorder");
  292           if (topBorder != null) {
  293               top.setBorder(topBorder);
  294           }
  295           top.setLayout(new BorderLayout());
  296   
  297           /* Fill the body. */
  298           Container          body = new JPanel(new GridBagLayout());
  299           Container          realBody = new JPanel(new BorderLayout());
  300   
  301           body.setName("OptionPane.body");
  302           realBody.setName("OptionPane.realBody");
  303   
  304           if (getIcon() != null) {
  305               JPanel sep = new JPanel();
  306               sep.setName("OptionPane.separator");
  307               sep.setPreferredSize(new Dimension(15, 1));
  308               realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
  309           }
  310           realBody.add(body, BorderLayout.CENTER);
  311   
  312           GridBagConstraints cons = new GridBagConstraints();
  313           cons.gridx = cons.gridy = 0;
  314           cons.gridwidth = GridBagConstraints.REMAINDER;
  315           cons.gridheight = 1;
  316           cons.anchor = DefaultLookup.getInt(optionPane, this,
  317                         "OptionPane.messageAnchor", GridBagConstraints.CENTER);
  318           cons.insets = new Insets(0,0,3,0);
  319   
  320           addMessageComponents(body, cons, getMessage(),
  321                             getMaxCharactersPerLineCount(), false);
  322           top.add(realBody, BorderLayout.CENTER);
  323   
  324           addIcon(top);
  325           return top;
  326       }
  327   
  328       /**
  329        * Creates the appropriate object to represent <code>msg</code> and
  330        * places it into <code>container</code>. If <code>msg</code> is an
  331        * instance of Component, it is added directly, if it is an Icon,
  332        * a JLabel is created to represent it, otherwise a JLabel is
  333        * created for the string, if <code>d</code> is an Object[], this
  334        * method will be recursively invoked for the children.
  335        * <code>internallyCreated</code> is true if Objc is an instance
  336        * of Component and was created internally by this method (this is
  337        * used to correctly set hasCustomComponents only if !internallyCreated).
  338        */
  339       protected void addMessageComponents(Container container,
  340                                        GridBagConstraints cons,
  341                                        Object msg, int maxll,
  342                                        boolean internallyCreated) {
  343           if (msg == null) {
  344               return;
  345           }
  346           if (msg instanceof Component) {
  347               // To workaround problem where Gridbad will set child
  348               // to its minimum size if its preferred size will not fit
  349               // within allocated cells
  350               if (msg instanceof JScrollPane || msg instanceof JPanel) {
  351                   cons.fill = GridBagConstraints.BOTH;
  352                   cons.weighty = 1;
  353               } else {
  354                   cons.fill = GridBagConstraints.HORIZONTAL;
  355               }
  356               cons.weightx = 1;
  357   
  358               container.add((Component) msg, cons);
  359               cons.weightx = 0;
  360               cons.weighty = 0;
  361               cons.fill = GridBagConstraints.NONE;
  362               cons.gridy++;
  363               if (!internallyCreated) {
  364                   hasCustomComponents = true;
  365               }
  366   
  367           } else if (msg instanceof Object[]) {
  368               Object [] msgs = (Object[]) msg;
  369               for (int i = 0; i < msgs.length; i++) {
  370                   addMessageComponents(container, cons, msgs[i], maxll, false);
  371               }
  372   
  373           } else if (msg instanceof Icon) {
  374               JLabel label = new JLabel( (Icon)msg, SwingConstants.CENTER );
  375               configureMessageLabel(label);
  376               addMessageComponents(container, cons, label, maxll, true);
  377   
  378           } else {
  379               String s = msg.toString();
  380               int len = s.length();
  381               if (len <= 0) {
  382                   return;
  383               }
  384               int nl = -1;
  385               int nll = 0;
  386   
  387               if ((nl = s.indexOf(newline)) >= 0) {
  388                   nll = newline.length();
  389               } else if ((nl = s.indexOf("\r\n")) >= 0) {
  390                   nll = 2;
  391               } else if ((nl = s.indexOf('\n')) >= 0) {
  392                   nll = 1;
  393               }
  394               if (nl >= 0) {
  395                   // break up newlines
  396                   if (nl == 0) {
  397                       JPanel breakPanel = new JPanel() {
  398                           public Dimension getPreferredSize() {
  399                               Font       f = getFont();
  400   
  401                               if (f != null) {
  402                                   return new Dimension(1, f.getSize() + 2);
  403                               }
  404                               return new Dimension(0, 0);
  405                           }
  406                       };
  407                       breakPanel.setName("OptionPane.break");
  408                       addMessageComponents(container, cons, breakPanel, maxll,
  409                                            true);
  410                   } else {
  411                       addMessageComponents(container, cons, s.substring(0, nl),
  412                                         maxll, false);
  413                   }
  414                   addMessageComponents(container, cons, s.substring(nl + nll), maxll,
  415                                     false);
  416   
  417               } else if (len > maxll) {
  418                   Container c = Box.createVerticalBox();
  419                   c.setName("OptionPane.verticalBox");
  420                   burstStringInto(c, s, maxll);
  421                   addMessageComponents(container, cons, c, maxll, true );
  422   
  423               } else {
  424                   JLabel label;
  425                   label = new JLabel( s, JLabel.LEADING );
  426                   label.setName("OptionPane.label");
  427                   configureMessageLabel(label);
  428                   addMessageComponents(container, cons, label, maxll, true);
  429               }
  430           }
  431       }
  432   
  433       /**
  434        * Returns the message to display from the JOptionPane the receiver is
  435        * providing the look and feel for.
  436        */
  437       protected Object getMessage() {
  438           inputComponent = null;
  439           if (optionPane != null) {
  440               if (optionPane.getWantsInput()) {
  441                   /* Create a user component to capture the input. If the
  442                      selectionValues are non null the component and there
  443                      are < 20 values it'll be a combobox, if non null and
  444                      >= 20, it'll be a list, otherwise it'll be a textfield. */
  445                   Object             message = optionPane.getMessage();
  446                   Object[]           sValues = optionPane.getSelectionValues();
  447                   Object             inputValue = optionPane
  448                                              .getInitialSelectionValue();
  449                   JComponent         toAdd;
  450   
  451                   if (sValues != null) {
  452                       if (sValues.length < 20) {
  453                           JComboBox            cBox = new JComboBox();
  454   
  455                           cBox.setName("OptionPane.comboBox");
  456                           for(int counter = 0, maxCounter = sValues.length;
  457                               counter < maxCounter; counter++) {
  458                               cBox.addItem(sValues[counter]);
  459                           }
  460                           if (inputValue != null) {
  461                               cBox.setSelectedItem(inputValue);
  462                           }
  463                           inputComponent = cBox;
  464                           toAdd = cBox;
  465   
  466                       } else {
  467                           JList                list = new JList(sValues);
  468                           JScrollPane          sp = new JScrollPane(list);
  469   
  470                           sp.setName("OptionPane.scrollPane");
  471                           list.setName("OptionPane.list");
  472                           list.setVisibleRowCount(10);
  473                           list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  474                           if(inputValue != null)
  475                               list.setSelectedValue(inputValue, true);
  476                           list.addMouseListener(getHandler());
  477                           toAdd = sp;
  478                           inputComponent = list;
  479                       }
  480   
  481                   } else {
  482                       MultiplexingTextField   tf = new MultiplexingTextField(20);
  483   
  484                       tf.setName("OptionPane.textField");
  485                       tf.setKeyStrokes(new KeyStroke[] {
  486                                        KeyStroke.getKeyStroke("ENTER") } );
  487                       if (inputValue != null) {
  488                           String inputString = inputValue.toString();
  489                           tf.setText(inputString);
  490                           tf.setSelectionStart(0);
  491                           tf.setSelectionEnd(inputString.length());
  492                       }
  493                       tf.addActionListener(getHandler());
  494                       toAdd = inputComponent = tf;
  495                   }
  496   
  497                   Object[]           newMessage;
  498   
  499                   if (message == null) {
  500                       newMessage = new Object[1];
  501                       newMessage[0] = toAdd;
  502   
  503                   } else {
  504                       newMessage = new Object[2];
  505                       newMessage[0] = message;
  506                       newMessage[1] = toAdd;
  507                   }
  508                   return newMessage;
  509               }
  510               return optionPane.getMessage();
  511           }
  512           return null;
  513       }
  514   
  515       /**
  516        * Creates and adds a JLabel representing the icon returned from
  517        * <code>getIcon</code> to <code>top</code>. This is messaged from
  518        * <code>createMessageArea</code>
  519        */
  520       protected void addIcon(Container top) {
  521           /* Create the icon. */
  522           Icon                  sideIcon = getIcon();
  523   
  524           if (sideIcon != null) {
  525               JLabel            iconLabel = new JLabel(sideIcon);
  526   
  527               iconLabel.setName("OptionPane.iconLabel");
  528               iconLabel.setVerticalAlignment(SwingConstants.TOP);
  529               top.add(iconLabel, BorderLayout.BEFORE_LINE_BEGINS);
  530           }
  531       }
  532   
  533       /**
  534        * Returns the icon from the JOptionPane the receiver is providing
  535        * the look and feel for, or the default icon as returned from
  536        * <code>getDefaultIcon</code>.
  537        */
  538       protected Icon getIcon() {
  539           Icon      mIcon = (optionPane == null ? null : optionPane.getIcon());
  540   
  541           if(mIcon == null && optionPane != null)
  542               mIcon = getIconForType(optionPane.getMessageType());
  543           return mIcon;
  544       }
  545   
  546       /**
  547        * Returns the icon to use for the passed in type.
  548        */
  549       protected Icon getIconForType(int messageType) {
  550           if(messageType < 0 || messageType > 3)
  551               return null;
  552           String propertyName = null;
  553           switch(messageType) {
  554           case 0:
  555               propertyName = "OptionPane.errorIcon";
  556               break;
  557           case 1:
  558               propertyName = "OptionPane.informationIcon";
  559               break;
  560           case 2:
  561               propertyName = "OptionPane.warningIcon";
  562               break;
  563           case 3:
  564               propertyName = "OptionPane.questionIcon";
  565               break;
  566           }
  567           if (propertyName != null) {
  568               return (Icon)DefaultLookup.get(optionPane, this, propertyName);
  569           }
  570           return null;
  571       }
  572   
  573       /**
  574        * Returns the maximum number of characters to place on a line.
  575        */
  576       protected int getMaxCharactersPerLineCount() {
  577           return optionPane.getMaxCharactersPerLineCount();
  578       }
  579   
  580      /**
  581        * Recursively creates new JLabel instances to represent <code>d</code>.
  582        * Each JLabel instance is added to <code>c</code>.
  583        */
  584       protected void burstStringInto(Container c, String d, int maxll) {
  585           // Primitive line wrapping
  586           int len = d.length();
  587           if (len <= 0)
  588               return;
  589           if (len > maxll) {
  590               int p = d.lastIndexOf(' ', maxll);
  591               if (p <= 0)
  592                   p = d.indexOf(' ', maxll);
  593               if (p > 0 && p < len) {
  594                   burstStringInto(c, d.substring(0, p), maxll);
  595                   burstStringInto(c, d.substring(p + 1), maxll);
  596                   return;
  597               }
  598           }
  599           JLabel label = new JLabel(d, JLabel.LEFT);
  600           label.setName("OptionPane.label");
  601           configureMessageLabel(label);
  602           c.add(label);
  603       }
  604   
  605       protected Container createSeparator() {
  606           return null;
  607       }
  608   
  609       /**
  610        * Creates and returns a Container containing the buttons. The buttons
  611        * are created by calling <code>getButtons</code>.
  612        */
  613       protected Container createButtonArea() {
  614           JPanel bottom = new JPanel();
  615           Border border = (Border)DefaultLookup.get(optionPane, this,
  616                                             "OptionPane.buttonAreaBorder");
  617           bottom.setName("OptionPane.buttonArea");
  618           if (border != null) {
  619               bottom.setBorder(border);
  620           }
  621           bottom.setLayout(new ButtonAreaLayout(
  622              DefaultLookup.getBoolean(optionPane, this,
  623                                       "OptionPane.sameSizeButtons", true),
  624              DefaultLookup.getInt(optionPane, this, "OptionPane.buttonPadding",
  625                                   6),
  626              DefaultLookup.getInt(optionPane, this,
  627                           "OptionPane.buttonOrientation", SwingConstants.CENTER),
  628              DefaultLookup.getBoolean(optionPane, this, "OptionPane.isYesLast",
  629                                       false)));
  630           addButtonComponents(bottom, getButtons(), getInitialValueIndex());
  631           return bottom;
  632       }
  633   
  634       /**
  635        * Creates the appropriate object to represent each of the objects in
  636        * <code>buttons</code> and adds it to <code>container</code>. This
  637        * differs from addMessageComponents in that it will recurse on
  638        * <code>buttons</code> and that if button is not a Component
  639        * it will create an instance of JButton.
  640        */
  641       protected void addButtonComponents(Container container, Object[] buttons,
  642                                    int initialIndex) {
  643           if (buttons != null && buttons.length > 0) {
  644               boolean            sizeButtonsToSame = getSizeButtonsToSameWidth();
  645               boolean            createdAll = true;
  646               int                numButtons = buttons.length;
  647               JButton[]          createdButtons = null;
  648               int                maxWidth = 0;
  649   
  650               if (sizeButtonsToSame) {
  651                   createdButtons = new JButton[numButtons];
  652               }
  653   
  654               for(int counter = 0; counter < numButtons; counter++) {
  655                   Object       button = buttons[counter];
  656                   Component    newComponent;
  657   
  658                   if (button instanceof Component) {
  659                       createdAll = false;
  660                       newComponent = (Component)button;
  661                       container.add(newComponent);
  662                       hasCustomComponents = true;
  663   
  664                   } else {
  665                       JButton      aButton;
  666   
  667                       if (button instanceof ButtonFactory) {
  668                           aButton = ((ButtonFactory)button).createButton();
  669                       }
  670                       else if (button instanceof Icon)
  671                           aButton = new JButton((Icon)button);
  672                       else
  673                           aButton = new JButton(button.toString());
  674   
  675                       aButton.setName("OptionPane.button");
  676                       aButton.setMultiClickThreshhold(DefaultLookup.getInt(
  677                             optionPane, this, "OptionPane.buttonClickThreshhold",
  678                             0));
  679                       configureButton(aButton);
  680   
  681                       container.add(aButton);
  682   
  683                       ActionListener buttonListener = createButtonActionListener(counter);
  684                       if (buttonListener != null) {
  685                           aButton.addActionListener(buttonListener);
  686                       }
  687                       newComponent = aButton;
  688                   }
  689                   if (sizeButtonsToSame && createdAll &&
  690                      (newComponent instanceof JButton)) {
  691                       createdButtons[counter] = (JButton)newComponent;
  692                       maxWidth = Math.max(maxWidth,
  693                                           newComponent.getMinimumSize().width);
  694                   }
  695                   if (counter == initialIndex) {
  696                       initialFocusComponent = newComponent;
  697                       if (initialFocusComponent instanceof JButton) {
  698                           JButton defaultB = (JButton)initialFocusComponent;
  699                           defaultB.addHierarchyListener(new HierarchyListener() {
  700                               public void hierarchyChanged(HierarchyEvent e) {
  701                                   if ((e.getChangeFlags() &
  702                                           HierarchyEvent.PARENT_CHANGED) != 0) {
  703                                       JButton defaultButton = (JButton) e.getComponent();
  704                                       JRootPane root =
  705                                               SwingUtilities.getRootPane(defaultButton);
  706                                       if (root != null) {
  707                                           root.setDefaultButton(defaultButton);
  708                                       }
  709                                   }
  710                               }
  711                           });
  712                       }
  713                   }
  714               }
  715               ((ButtonAreaLayout)container.getLayout()).
  716                                 setSyncAllWidths((sizeButtonsToSame && createdAll));
  717               /* Set the padding, windows seems to use 8 if <= 2 components,
  718                  otherwise 4 is used. It may actually just be the size of the
  719                  buttons is always the same, not sure. */
  720               if (DefaultLookup.getBoolean(optionPane, this,
  721                      "OptionPane.setButtonMargin", true) && sizeButtonsToSame &&
  722                      createdAll) {
  723                   JButton               aButton;
  724                   int                   padSize;
  725   
  726                   padSize = (numButtons <= 2? 8 : 4);
  727   
  728                   for(int counter = 0; counter < numButtons; counter++) {
  729                       aButton = createdButtons[counter];
  730                       aButton.setMargin(new Insets(2, padSize, 2, padSize));
  731                   }
  732               }
  733           }
  734       }
  735   
  736       protected ActionListener createButtonActionListener(int buttonIndex) {
  737           return new ButtonActionListener(buttonIndex);
  738       }
  739   
  740       /**
  741        * Returns the buttons to display from the JOptionPane the receiver is
  742        * providing the look and feel for. If the JOptionPane has options
  743        * set, they will be provided, otherwise if the optionType is
  744        * YES_NO_OPTION, yesNoOptions is returned, if the type is
  745        * YES_NO_CANCEL_OPTION yesNoCancelOptions is returned, otherwise
  746        * defaultButtons are returned.
  747        */
  748       protected Object[] getButtons() {
  749           if (optionPane != null) {
  750               Object[] suppliedOptions = optionPane.getOptions();
  751   
  752               if (suppliedOptions == null) {
  753                   Object[] defaultOptions;
  754                   int type = optionPane.getOptionType();
  755                   Locale l = optionPane.getLocale();
  756                   int minimumWidth =
  757                       DefaultLookup.getInt(optionPane, this,
  758                                           "OptionPane.buttonMinimumWidth",-1);
  759                   if (type == JOptionPane.YES_NO_OPTION) {
  760                       defaultOptions = new ButtonFactory[2];
  761                       defaultOptions[0] = new ButtonFactory(
  762                           UIManager.getString("OptionPane.yesButtonText", l),
  763                           getMnemonic("OptionPane.yesButtonMnemonic", l),
  764                           (Icon)DefaultLookup.get(optionPane, this,
  765                                             "OptionPane.yesIcon"), minimumWidth);
  766                       defaultOptions[1] = new ButtonFactory(
  767                           UIManager.getString("OptionPane.noButtonText", l),
  768                           getMnemonic("OptionPane.noButtonMnemonic", l),
  769                           (Icon)DefaultLookup.get(optionPane, this,
  770                                             "OptionPane.noIcon"), minimumWidth);
  771                   } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) {
  772                       defaultOptions = new ButtonFactory[3];
  773                       defaultOptions[0] = new ButtonFactory(
  774                           UIManager.getString("OptionPane.yesButtonText", l),
  775                           getMnemonic("OptionPane.yesButtonMnemonic", l),
  776                           (Icon)DefaultLookup.get(optionPane, this,
  777                                             "OptionPane.yesIcon"), minimumWidth);
  778                       defaultOptions[1] = new ButtonFactory(
  779                           UIManager.getString("OptionPane.noButtonText",l),
  780                           getMnemonic("OptionPane.noButtonMnemonic", l),
  781                           (Icon)DefaultLookup.get(optionPane, this,
  782                                             "OptionPane.noIcon"), minimumWidth);
  783                       defaultOptions[2] = new ButtonFactory(
  784                           UIManager.getString("OptionPane.cancelButtonText",l),
  785                           getMnemonic("OptionPane.cancelButtonMnemonic", l),
  786                           (Icon)DefaultLookup.get(optionPane, this,
  787                                             "OptionPane.cancelIcon"), minimumWidth);
  788                   } else if (type == JOptionPane.OK_CANCEL_OPTION) {
  789                       defaultOptions = new ButtonFactory[2];
  790                       defaultOptions[0] = new ButtonFactory(
  791                           UIManager.getString("OptionPane.okButtonText",l),
  792                           getMnemonic("OptionPane.okButtonMnemonic", l),
  793                           (Icon)DefaultLookup.get(optionPane, this,
  794                                             "OptionPane.okIcon"), minimumWidth);
  795                       defaultOptions[1] = new ButtonFactory(
  796                           UIManager.getString("OptionPane.cancelButtonText",l),
  797                           getMnemonic("OptionPane.cancelButtonMnemonic", l),
  798                           (Icon)DefaultLookup.get(optionPane, this,
  799                                             "OptionPane.cancelIcon"), minimumWidth);
  800                   } else {
  801                       defaultOptions = new ButtonFactory[1];
  802                       defaultOptions[0] = new ButtonFactory(
  803                           UIManager.getString("OptionPane.okButtonText",l),
  804                           getMnemonic("OptionPane.okButtonMnemonic", l),
  805                           (Icon)DefaultLookup.get(optionPane, this,
  806                                             "OptionPane.okIcon"), minimumWidth);
  807                   }
  808                   return defaultOptions;
  809   
  810               }
  811               return suppliedOptions;
  812           }
  813           return null;
  814       }
  815   
  816       private int getMnemonic(String key, Locale l) {
  817           String value = (String)UIManager.get(key, l);
  818   
  819           if (value == null) {
  820               return 0;
  821           }
  822           try {
  823               return Integer.parseInt(value);
  824           }
  825           catch (NumberFormatException nfe) { }
  826           return 0;
  827       }
  828   
  829       /**
  830        * Returns true, basic L&F wants all the buttons to have the same
  831        * width.
  832        */
  833       protected boolean getSizeButtonsToSameWidth() {
  834           return true;
  835       }
  836   
  837       /**
  838        * Returns the initial index into the buttons to select. The index
  839        * is calculated from the initial value from the JOptionPane and
  840        * options of the JOptionPane or 0.
  841        */
  842       protected int getInitialValueIndex() {
  843           if (optionPane != null) {
  844               Object             iv = optionPane.getInitialValue();
  845               Object[]           options = optionPane.getOptions();
  846   
  847               if(options == null) {
  848                   return 0;
  849               }
  850               else if(iv != null) {
  851                   for(int counter = options.length - 1; counter >= 0; counter--){
  852                       if(options[counter].equals(iv))
  853                           return counter;
  854                   }
  855               }
  856           }
  857           return -1;
  858       }
  859   
  860       /**
  861        * Sets the input value in the option pane the receiver is providing
  862        * the look and feel for based on the value in the inputComponent.
  863        */
  864       protected void resetInputValue() {
  865           if(inputComponent != null && (inputComponent instanceof JTextField)) {
  866               optionPane.setInputValue(((JTextField)inputComponent).getText());
  867   
  868           } else if(inputComponent != null &&
  869                     (inputComponent instanceof JComboBox)) {
  870               optionPane.setInputValue(((JComboBox)inputComponent)
  871                                        .getSelectedItem());
  872           } else if(inputComponent != null) {
  873               optionPane.setInputValue(((JList)inputComponent)
  874                                        .getSelectedValue());
  875           }
  876       }
  877   
  878   
  879       /**
  880        * If inputComponent is non-null, the focus is requested on that,
  881        * otherwise request focus on the default value
  882        */
  883       public void selectInitialValue(JOptionPane op) {
  884           if (inputComponent != null)
  885               inputComponent.requestFocus();
  886           else {
  887               if (initialFocusComponent != null)
  888                   initialFocusComponent.requestFocus();
  889   
  890               if (initialFocusComponent instanceof JButton) {
  891                   JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
  892                   if (root != null) {
  893                       root.setDefaultButton((JButton)initialFocusComponent);
  894                   }
  895               }
  896           }
  897       }
  898   
  899       /**
  900        * Returns true if in the last call to validateComponent the message
  901        * or buttons contained a subclass of Component.
  902        */
  903       public boolean containsCustomComponents(JOptionPane op) {
  904           return hasCustomComponents;
  905       }
  906   
  907   
  908       /**
  909        * <code>ButtonAreaLayout</code> behaves in a similar manner to
  910        * <code>FlowLayout</code>. It lays out all components from left to
  911        * right. If <code>syncAllWidths</code> is true, the widths of each
  912        * component will be set to the largest preferred size width.
  913        *
  914        * This inner class is marked &quot;public&quot; due to a compiler bug.
  915        * This class should be treated as a &quot;protected&quot; inner class.
  916        * Instantiate it only within subclasses of BasicOptionPaneUI.
  917        */
  918       public static class ButtonAreaLayout implements LayoutManager {
  919           protected boolean           syncAllWidths;
  920           protected int               padding;
  921           /** If true, children are lumped together in parent. */
  922           protected boolean           centersChildren;
  923           private int orientation;
  924           private boolean reverseButtons;
  925           /**
  926            * Indicates whether or not centersChildren should be used vs
  927            * the orientation. This is done for backward compatability
  928            * for subclassers.
  929            */
  930           private boolean useOrientation;
  931   
  932           public ButtonAreaLayout(boolean syncAllWidths, int padding) {
  933               this.syncAllWidths = syncAllWidths;
  934               this.padding = padding;
  935               centersChildren = true;
  936               useOrientation = false;
  937           }
  938   
  939           ButtonAreaLayout(boolean syncAllSizes, int padding, int orientation,
  940                            boolean reverseButtons) {
  941               this(syncAllSizes, padding);
  942               useOrientation = true;
  943               this.orientation = orientation;
  944               this.reverseButtons = reverseButtons;
  945           }
  946   
  947           public void setSyncAllWidths(boolean newValue) {
  948               syncAllWidths = newValue;
  949           }
  950   
  951           public boolean getSyncAllWidths() {
  952               return syncAllWidths;
  953           }
  954   
  955           public void setPadding(int newPadding) {
  956               this.padding = newPadding;
  957           }
  958   
  959           public int getPadding() {
  960               return padding;
  961           }
  962   
  963           public void setCentersChildren(boolean newValue) {
  964               centersChildren = newValue;
  965               useOrientation = false;
  966           }
  967   
  968           public boolean getCentersChildren() {
  969               return centersChildren;
  970           }
  971   
  972           private int getOrientation(Container container) {
  973               if (!useOrientation) {
  974                   return SwingConstants.CENTER;
  975               }
  976               if (container.getComponentOrientation().isLeftToRight()) {
  977                   return orientation;
  978               }
  979               switch (orientation) {
  980               case SwingConstants.LEFT:
  981                   return SwingConstants.RIGHT;
  982               case SwingConstants.RIGHT:
  983                   return SwingConstants.LEFT;
  984               case SwingConstants.CENTER:
  985                   return SwingConstants.CENTER;
  986               }
  987               return SwingConstants.LEFT;
  988           }
  989   
  990           public void addLayoutComponent(String string, Component comp) {
  991           }
  992   
  993           public void layoutContainer(Container container) {
  994               Component[]      children = container.getComponents();
  995   
  996               if(children != null && children.length > 0) {
  997                   int               numChildren = children.length;
  998                   Insets            insets = container.getInsets();
  999                   int maxWidth = 0;
 1000                   int maxHeight = 0;
 1001                   int totalButtonWidth = 0;
 1002                   int x = 0;
 1003                   int xOffset = 0;
 1004                   boolean ltr = container.getComponentOrientation().
 1005                                           isLeftToRight();
 1006                   boolean reverse = (ltr) ? reverseButtons : !reverseButtons;
 1007   
 1008                   for(int counter = 0; counter < numChildren; counter++) {
 1009                       Dimension pref = children[counter].getPreferredSize();
 1010                       maxWidth = Math.max(maxWidth, pref.width);
 1011                       maxHeight = Math.max(maxHeight, pref.height);
 1012                       totalButtonWidth += pref.width;
 1013                   }
 1014                   if (getSyncAllWidths()) {
 1015                       totalButtonWidth = maxWidth * numChildren;
 1016                   }
 1017                   totalButtonWidth += (numChildren - 1) * padding;
 1018   
 1019                   switch (getOrientation(container)) {
 1020                   case SwingConstants.LEFT:
 1021                       x = insets.left;
 1022                       break;
 1023                   case SwingConstants.RIGHT:
 1024                       x = container.getWidth() - insets.right - totalButtonWidth;
 1025                       break;
 1026                   case SwingConstants.CENTER:
 1027                       if (getCentersChildren() || numChildren < 2) {
 1028                           x = (container.getWidth() - totalButtonWidth) / 2;
 1029                       }
 1030                       else {
 1031                           x = insets.left;
 1032                           if (getSyncAllWidths()) {
 1033                               xOffset = (container.getWidth() - insets.left -
 1034                                          insets.right - totalButtonWidth) /
 1035                                   (numChildren - 1) + maxWidth;
 1036                           }
 1037                           else {
 1038                               xOffset = (container.getWidth() - insets.left -
 1039                                          insets.right - totalButtonWidth) /
 1040                                         (numChildren - 1);
 1041                           }
 1042                       }
 1043                       break;
 1044                   }
 1045   
 1046                   for (int counter = 0; counter < numChildren; counter++) {
 1047                       int index = (reverse) ? numChildren - counter - 1 :
 1048                                   counter;
 1049                       Dimension pref = children[index].getPreferredSize();
 1050   
 1051                       if (getSyncAllWidths()) {
 1052                           children[index].setBounds(x, insets.top,
 1053                                                     maxWidth, maxHeight);
 1054                       }
 1055                       else {
 1056                           children[index].setBounds(x, insets.top, pref.width,
 1057                                                     pref.height);
 1058                       }
 1059                       if (xOffset != 0) {
 1060                           x += xOffset;
 1061                       }
 1062                       else {
 1063                           x += children[index].getWidth() + padding;
 1064                       }
 1065                   }
 1066               }
 1067           }
 1068   
 1069           public Dimension minimumLayoutSize(Container c) {
 1070               if(c != null) {
 1071                   Component[]       children = c.getComponents();
 1072   
 1073                   if(children != null && children.length > 0) {
 1074                       Dimension     aSize;
 1075                       int           numChildren = children.length;
 1076                       int           height = 0;
 1077                       Insets        cInsets = c.getInsets();
 1078                       int           extraHeight = cInsets.top + cInsets.bottom;
 1079                       int           extraWidth = cInsets.left + cInsets.right;
 1080   
 1081                       if (syncAllWidths) {
 1082                           int              maxWidth = 0;
 1083   
 1084                           for(int counter = 0; counter < numChildren; counter++){
 1085                               aSize = children[counter].getPreferredSize();
 1086                               height = Math.max(height, aSize.height);
 1087                               maxWidth = Math.max(maxWidth, aSize.width);
 1088                           }
 1089                           return new Dimension(extraWidth + (maxWidth * numChildren) +
 1090                                                (numChildren - 1) * padding,
 1091                                                extraHeight + height);
 1092                       }
 1093                       else {
 1094                           int        totalWidth = 0;
 1095   
 1096                           for(int counter = 0; counter < numChildren; counter++){
 1097                               aSize = children[counter].getPreferredSize();
 1098                               height = Math.max(height, aSize.height);
 1099                               totalWidth += aSize.width;
 1100                           }
 1101                           totalWidth += ((numChildren - 1) * padding);
 1102                           return new Dimension(extraWidth + totalWidth, extraHeight + height);
 1103                       }
 1104                   }
 1105               }
 1106               return new Dimension(0, 0);
 1107           }
 1108   
 1109           public Dimension preferredLayoutSize(Container c) {
 1110               return minimumLayoutSize(c);
 1111           }
 1112   
 1113           public void removeLayoutComponent(Component c) { }
 1114       }
 1115   
 1116   
 1117       /**
 1118        * This inner class is marked &quot;public&quot; due to a compiler bug.
 1119        * This class should be treated as a &quot;protected&quot; inner class.
 1120        * Instantiate it only within subclasses of BasicOptionPaneUI.
 1121        */
 1122       public class PropertyChangeHandler implements PropertyChangeListener {
 1123           /**
 1124            * If the source of the PropertyChangeEvent <code>e</code> equals the
 1125            * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
 1126            * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
 1127            * validateComponent is invoked.
 1128            */
 1129           public void propertyChange(PropertyChangeEvent e) {
 1130               getHandler().propertyChange(e);
 1131           }
 1132       }
 1133   
 1134       /**
 1135        * Configures any necessary colors/fonts for the specified label
 1136        * used representing the message.
 1137        */
 1138       private void configureMessageLabel(JLabel label) {
 1139           Color color = (Color)DefaultLookup.get(optionPane, this,
 1140                                                  "OptionPane.messageForeground");
 1141           if (color != null) {
 1142               label.setForeground(color);
 1143           }
 1144           Font messageFont = (Font)DefaultLookup.get(optionPane, this,
 1145                                                      "OptionPane.messageFont");
 1146           if (messageFont != null) {
 1147               label.setFont(messageFont);
 1148           }
 1149       }
 1150   
 1151       /**
 1152        * Configures any necessary colors/fonts for the specified button
 1153        * used representing the button portion of the optionpane.
 1154        */
 1155       private void configureButton(JButton button) {
 1156           Font buttonFont = (Font)DefaultLookup.get(optionPane, this,
 1157                                               "OptionPane.buttonFont");
 1158           if (buttonFont != null) {
 1159               button.setFont(buttonFont);
 1160           }
 1161       }
 1162   
 1163       /**
 1164        * This inner class is marked &quot;public&quot; due to a compiler bug.
 1165        * This class should be treated as a &quot;protected&quot; inner class.
 1166        * Instantiate it only within subclasses of BasicOptionPaneUI.
 1167        */
 1168       public class ButtonActionListener implements ActionListener {
 1169           protected int buttonIndex;
 1170   
 1171           public ButtonActionListener(int buttonIndex) {
 1172               this.buttonIndex = buttonIndex;
 1173           }
 1174   
 1175           public void actionPerformed(ActionEvent e) {
 1176               if (optionPane != null) {
 1177                   int optionType = optionPane.getOptionType();
 1178                   Object[] options = optionPane.getOptions();
 1179   
 1180                   /* If the option pane takes input, then store the input value
 1181                    * if custom options were specified, if the option type is
 1182                    * DEFAULT_OPTION, OR if option type is set to a predefined
 1183                    * one and the user chose the affirmative answer.
 1184                    */
 1185                   if (inputComponent != null) {
 1186                       if (options != null ||
 1187                           optionType == JOptionPane.DEFAULT_OPTION ||
 1188                           ((optionType == JOptionPane.YES_NO_OPTION ||
 1189                            optionType == JOptionPane.YES_NO_CANCEL_OPTION ||
 1190                            optionType == JOptionPane.OK_CANCEL_OPTION) &&
 1191                            buttonIndex == 0)) {
 1192                           resetInputValue();
 1193                       }
 1194                   }
 1195                   if (options == null) {
 1196                       if (optionType == JOptionPane.OK_CANCEL_OPTION &&
 1197                           buttonIndex == 1) {
 1198                           optionPane.setValue(Integer.valueOf(2));
 1199   
 1200                       } else {
 1201                           optionPane.setValue(Integer.valueOf(buttonIndex));
 1202                       }
 1203                   } else {
 1204                       optionPane.setValue(options[buttonIndex]);
 1205                   }
 1206               }
 1207           }
 1208       }
 1209   
 1210   
 1211       private class Handler implements ActionListener, MouseListener,
 1212                                        PropertyChangeListener {
 1213           //
 1214           // ActionListener
 1215           //
 1216           public void actionPerformed(ActionEvent e) {
 1217               optionPane.setInputValue(((JTextField)e.getSource()).getText());
 1218           }
 1219   
 1220   
 1221           //
 1222           // MouseListener
 1223           //
 1224           public void mouseClicked(MouseEvent e) {
 1225           }
 1226   
 1227           public void mouseReleased(MouseEvent e) {
 1228           }
 1229   
 1230           public void mouseEntered(MouseEvent e) {
 1231           }
 1232   
 1233           public void mouseExited(MouseEvent e) {
 1234           }
 1235   
 1236           public void mousePressed(MouseEvent e) {
 1237               if (e.getClickCount() == 2) {
 1238                   JList     list = (JList)e.getSource();
 1239                   int       index = list.locationToIndex(e.getPoint());
 1240   
 1241                   optionPane.setInputValue(list.getModel().getElementAt(index));
 1242               }
 1243           }
 1244   
 1245           //
 1246           // PropertyChangeListener
 1247           //
 1248           public void propertyChange(PropertyChangeEvent e) {
 1249               if(e.getSource() == optionPane) {
 1250                   // Option Pane Auditory Cue Activation
 1251                   // only respond to "ancestor" changes
 1252                   // the idea being that a JOptionPane gets a JDialog when it is
 1253                   // set to appear and loses it's JDialog when it is dismissed.
 1254                   if ("ancestor" == e.getPropertyName()) {
 1255                       JOptionPane op = (JOptionPane)e.getSource();
 1256                       boolean isComingUp;
 1257   
 1258                       // if the old value is null, then the JOptionPane is being
 1259                       // created since it didn't previously have an ancestor.
 1260                       if (e.getOldValue() == null) {
 1261                           isComingUp = true;
 1262                       } else {
 1263                           isComingUp = false;
 1264                       }
 1265   
 1266                       // figure out what to do based on the message type
 1267                       switch (op.getMessageType()) {
 1268                       case JOptionPane.PLAIN_MESSAGE:
 1269                           if (isComingUp) {
 1270                               BasicLookAndFeel.playSound(optionPane,
 1271                                                  "OptionPane.informationSound");
 1272                           }
 1273                           break;
 1274                       case JOptionPane.QUESTION_MESSAGE:
 1275                           if (isComingUp) {
 1276                               BasicLookAndFeel.playSound(optionPane,
 1277                                                "OptionPane.questionSound");
 1278                           }
 1279                           break;
 1280                       case JOptionPane.INFORMATION_MESSAGE:
 1281                           if (isComingUp) {
 1282                               BasicLookAndFeel.playSound(optionPane,
 1283                                                "OptionPane.informationSound");
 1284                           }
 1285                           break;
 1286                       case JOptionPane.WARNING_MESSAGE:
 1287                           if (isComingUp) {
 1288                               BasicLookAndFeel.playSound(optionPane,
 1289                                                "OptionPane.warningSound");
 1290                           }
 1291                           break;
 1292                       case JOptionPane.ERROR_MESSAGE:
 1293                           if (isComingUp) {
 1294                               BasicLookAndFeel.playSound(optionPane,
 1295                                                "OptionPane.errorSound");
 1296                           }
 1297                           break;
 1298                       default:
 1299                           System.err.println("Undefined JOptionPane type: " +
 1300                                              op.getMessageType());
 1301                           break;
 1302                       }
 1303                   }
 1304                   // Visual activity
 1305                   String         changeName = e.getPropertyName();
 1306   
 1307                   if(changeName == JOptionPane.OPTIONS_PROPERTY ||
 1308                      changeName == JOptionPane.INITIAL_VALUE_PROPERTY ||
 1309                      changeName == JOptionPane.ICON_PROPERTY ||
 1310                      changeName == JOptionPane.MESSAGE_TYPE_PROPERTY ||
 1311                      changeName == JOptionPane.OPTION_TYPE_PROPERTY ||
 1312                      changeName == JOptionPane.MESSAGE_PROPERTY ||
 1313                      changeName == JOptionPane.SELECTION_VALUES_PROPERTY ||
 1314                      changeName == JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY ||
 1315                      changeName == JOptionPane.WANTS_INPUT_PROPERTY) {
 1316                      uninstallComponents();
 1317                      installComponents();
 1318                      optionPane.validate();
 1319                   }
 1320                   else if (changeName == "componentOrientation") {
 1321                       ComponentOrientation o = (ComponentOrientation)e.getNewValue();
 1322                       JOptionPane op = (JOptionPane)e.getSource();
 1323                       if (o != (ComponentOrientation)e.getOldValue()) {
 1324                           op.applyComponentOrientation(o);
 1325                       }
 1326                   }
 1327               }
 1328           }
 1329       }
 1330   
 1331   
 1332       //
 1333       // Classes used when optionPane.getWantsInput returns true.
 1334       //
 1335   
 1336       /**
 1337        * A JTextField that allows you to specify an array of KeyStrokes that
 1338        * that will have their bindings processed regardless of whether or
 1339        * not they are registered on the JTextField. This is used as we really
 1340        * want the ActionListener to be notified so that we can push the
 1341        * change to the JOptionPane, but we also want additional bindings
 1342        * (those of the JRootPane) to be processed as well.
 1343        */
 1344       private static class MultiplexingTextField extends JTextField {
 1345           private KeyStroke[] strokes;
 1346   
 1347           MultiplexingTextField(int cols) {
 1348               super(cols);
 1349           }
 1350   
 1351           /**
 1352            * Sets the KeyStrokes that will be additional processed for
 1353            * ancestor bindings.
 1354            */
 1355           void setKeyStrokes(KeyStroke[] strokes) {
 1356               this.strokes = strokes;
 1357           }
 1358   
 1359           protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
 1360                                               int condition, boolean pressed) {
 1361               boolean processed = super.processKeyBinding(ks, e, condition,
 1362                                                           pressed);
 1363   
 1364               if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
 1365                   for (int counter = strokes.length - 1; counter >= 0;
 1366                            counter--) {
 1367                       if (strokes[counter].equals(ks)) {
 1368                           // Returning false will allow further processing
 1369                           // of the bindings, eg our parent Containers will get a
 1370                           // crack at them.
 1371                           return false;
 1372                       }
 1373                   }
 1374               }
 1375               return processed;
 1376           }
 1377       }
 1378   
 1379   
 1380   
 1381       /**
 1382        * Registered in the ActionMap. Sets the value of the option pane
 1383        * to <code>JOptionPane.CLOSED_OPTION</code>.
 1384        */
 1385       private static class Actions extends UIAction {
 1386           private static final String CLOSE = "close";
 1387   
 1388           Actions(String key) {
 1389               super(key);
 1390           }
 1391   
 1392           public void actionPerformed(ActionEvent e) {
 1393               if (getName() == CLOSE) {
 1394                   JOptionPane optionPane = (JOptionPane)e.getSource();
 1395   
 1396                   optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
 1397               }
 1398           }
 1399       }
 1400   
 1401   
 1402       /**
 1403        * This class is used to create the default buttons. This indirection is
 1404        * used so that addButtonComponents can tell which Buttons were created
 1405        * by us vs subclassers or from the JOptionPane itself.
 1406        */
 1407       private static class ButtonFactory {
 1408           private String text;
 1409           private int mnemonic;
 1410           private Icon icon;
 1411           private int minimumWidth = -1;
 1412   
 1413           ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) {
 1414               this.text = text;
 1415               this.mnemonic = mnemonic;
 1416               this.icon = icon;
 1417               this.minimumWidth = minimumWidth;
 1418           }
 1419   
 1420           JButton createButton() {
 1421               JButton button = null;
 1422   
 1423               if (minimumWidth > 0) {
 1424                   button = new ConstrainedButton(text, minimumWidth);
 1425               } else {
 1426                   button = new JButton(text);
 1427               }
 1428               if (icon != null) {
 1429                   button.setIcon(icon);
 1430               }
 1431               if (mnemonic != 0) {
 1432                   button.setMnemonic(mnemonic);
 1433               }
 1434               return button;
 1435           }
 1436   
 1437           private static class ConstrainedButton extends JButton {
 1438               int minimumWidth;
 1439   
 1440               ConstrainedButton(String text, int minimumWidth) {
 1441                   super(text);
 1442                   this.minimumWidth = minimumWidth;
 1443               }
 1444   
 1445               public Dimension getMinimumSize() {
 1446                   Dimension min = super.getMinimumSize();
 1447                   min.width = Math.max(min.width, minimumWidth);
 1448                   return min;
 1449               }
 1450   
 1451               public Dimension getPreferredSize() {
 1452                   Dimension pref = super.getPreferredSize();
 1453                   pref.width = Math.max(pref.width, minimumWidth);
 1454                   return pref;
 1455               }
 1456           }
 1457       }
 1458   }

Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]