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

    1   /*
    2    * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package 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 = 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 (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 (Object o : msgs) {
  370                   addMessageComponents(container, cons, o, 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;
  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 class should be treated as a &quot;protected&quot; inner class.
  915        * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
  916        */
  917       public static class ButtonAreaLayout implements LayoutManager {
  918           protected boolean           syncAllWidths;
  919           protected int               padding;
  920           /** If true, children are lumped together in parent. */
  921           protected boolean           centersChildren;
  922           private int orientation;
  923           private boolean reverseButtons;
  924           /**
  925            * Indicates whether or not centersChildren should be used vs
  926            * the orientation. This is done for backward compatability
  927            * for subclassers.
  928            */
  929           private boolean useOrientation;
  930   
  931           public ButtonAreaLayout(boolean syncAllWidths, int padding) {
  932               this.syncAllWidths = syncAllWidths;
  933               this.padding = padding;
  934               centersChildren = true;
  935               useOrientation = false;
  936           }
  937   
  938           ButtonAreaLayout(boolean syncAllSizes, int padding, int orientation,
  939                            boolean reverseButtons) {
  940               this(syncAllSizes, padding);
  941               useOrientation = true;
  942               this.orientation = orientation;
  943               this.reverseButtons = reverseButtons;
  944           }
  945   
  946           public void setSyncAllWidths(boolean newValue) {
  947               syncAllWidths = newValue;
  948           }
  949   
  950           public boolean getSyncAllWidths() {
  951               return syncAllWidths;
  952           }
  953   
  954           public void setPadding(int newPadding) {
  955               this.padding = newPadding;
  956           }
  957   
  958           public int getPadding() {
  959               return padding;
  960           }
  961   
  962           public void setCentersChildren(boolean newValue) {
  963               centersChildren = newValue;
  964               useOrientation = false;
  965           }
  966   
  967           public boolean getCentersChildren() {
  968               return centersChildren;
  969           }
  970   
  971           private int getOrientation(Container container) {
  972               if (!useOrientation) {
  973                   return SwingConstants.CENTER;
  974               }
  975               if (container.getComponentOrientation().isLeftToRight()) {
  976                   return orientation;
  977               }
  978               switch (orientation) {
  979               case SwingConstants.LEFT:
  980                   return SwingConstants.RIGHT;
  981               case SwingConstants.RIGHT:
  982                   return SwingConstants.LEFT;
  983               case SwingConstants.CENTER:
  984                   return SwingConstants.CENTER;
  985               }
  986               return SwingConstants.LEFT;
  987           }
  988   
  989           public void addLayoutComponent(String string, Component comp) {
  990           }
  991   
  992           public void layoutContainer(Container container) {
  993               Component[]      children = container.getComponents();
  994   
  995               if(children != null && children.length > 0) {
  996                   int               numChildren = children.length;
  997                   Insets            insets = container.getInsets();
  998                   int maxWidth = 0;
  999                   int maxHeight = 0;
 1000                   int totalButtonWidth = 0;
 1001                   int x = 0;
 1002                   int xOffset = 0;
 1003                   boolean ltr = container.getComponentOrientation().
 1004                                           isLeftToRight();
 1005                   boolean reverse = (ltr) ? reverseButtons : !reverseButtons;
 1006   
 1007                   for(int counter = 0; counter < numChildren; counter++) {
 1008                       Dimension pref = children[counter].getPreferredSize();
 1009                       maxWidth = Math.max(maxWidth, pref.width);
 1010                       maxHeight = Math.max(maxHeight, pref.height);
 1011                       totalButtonWidth += pref.width;
 1012                   }
 1013                   if (getSyncAllWidths()) {
 1014                       totalButtonWidth = maxWidth * numChildren;
 1015                   }
 1016                   totalButtonWidth += (numChildren - 1) * padding;
 1017   
 1018                   switch (getOrientation(container)) {
 1019                   case SwingConstants.LEFT:
 1020                       x = insets.left;
 1021                       break;
 1022                   case SwingConstants.RIGHT:
 1023                       x = container.getWidth() - insets.right - totalButtonWidth;
 1024                       break;
 1025                   case SwingConstants.CENTER:
 1026                       if (getCentersChildren() || numChildren < 2) {
 1027                           x = (container.getWidth() - totalButtonWidth) / 2;
 1028                       }
 1029                       else {
 1030                           x = insets.left;
 1031                           if (getSyncAllWidths()) {
 1032                               xOffset = (container.getWidth() - insets.left -
 1033                                          insets.right - totalButtonWidth) /
 1034                                   (numChildren - 1) + maxWidth;
 1035                           }
 1036                           else {
 1037                               xOffset = (container.getWidth() - insets.left -
 1038                                          insets.right - totalButtonWidth) /
 1039                                         (numChildren - 1);
 1040                           }
 1041                       }
 1042                       break;
 1043                   }
 1044   
 1045                   for (int counter = 0; counter < numChildren; counter++) {
 1046                       int index = (reverse) ? numChildren - counter - 1 :
 1047                                   counter;
 1048                       Dimension pref = children[index].getPreferredSize();
 1049   
 1050                       if (getSyncAllWidths()) {
 1051                           children[index].setBounds(x, insets.top,
 1052                                                     maxWidth, maxHeight);
 1053                       }
 1054                       else {
 1055                           children[index].setBounds(x, insets.top, pref.width,
 1056                                                     pref.height);
 1057                       }
 1058                       if (xOffset != 0) {
 1059                           x += xOffset;
 1060                       }
 1061                       else {
 1062                           x += children[index].getWidth() + padding;
 1063                       }
 1064                   }
 1065               }
 1066           }
 1067   
 1068           public Dimension minimumLayoutSize(Container c) {
 1069               if(c != null) {
 1070                   Component[]       children = c.getComponents();
 1071   
 1072                   if(children != null && children.length > 0) {
 1073                       Dimension     aSize;
 1074                       int           numChildren = children.length;
 1075                       int           height = 0;
 1076                       Insets        cInsets = c.getInsets();
 1077                       int           extraHeight = cInsets.top + cInsets.bottom;
 1078                       int           extraWidth = cInsets.left + cInsets.right;
 1079   
 1080                       if (syncAllWidths) {
 1081                           int              maxWidth = 0;
 1082   
 1083                           for(int counter = 0; counter < numChildren; counter++){
 1084                               aSize = children[counter].getPreferredSize();
 1085                               height = Math.max(height, aSize.height);
 1086                               maxWidth = Math.max(maxWidth, aSize.width);
 1087                           }
 1088                           return new Dimension(extraWidth + (maxWidth * numChildren) +
 1089                                                (numChildren - 1) * padding,
 1090                                                extraHeight + height);
 1091                       }
 1092                       else {
 1093                           int        totalWidth = 0;
 1094   
 1095                           for(int counter = 0; counter < numChildren; counter++){
 1096                               aSize = children[counter].getPreferredSize();
 1097                               height = Math.max(height, aSize.height);
 1098                               totalWidth += aSize.width;
 1099                           }
 1100                           totalWidth += ((numChildren - 1) * padding);
 1101                           return new Dimension(extraWidth + totalWidth, extraHeight + height);
 1102                       }
 1103                   }
 1104               }
 1105               return new Dimension(0, 0);
 1106           }
 1107   
 1108           public Dimension preferredLayoutSize(Container c) {
 1109               return minimumLayoutSize(c);
 1110           }
 1111   
 1112           public void removeLayoutComponent(Component c) { }
 1113       }
 1114   
 1115   
 1116       /**
 1117        * This class should be treated as a &quot;protected&quot; inner class.
 1118        * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
 1119        */
 1120       public class PropertyChangeHandler implements PropertyChangeListener {
 1121           /**
 1122            * If the source of the PropertyChangeEvent <code>e</code> equals the
 1123            * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
 1124            * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
 1125            * validateComponent is invoked.
 1126            */
 1127           public void propertyChange(PropertyChangeEvent e) {
 1128               getHandler().propertyChange(e);
 1129           }
 1130       }
 1131   
 1132       /**
 1133        * Configures any necessary colors/fonts for the specified label
 1134        * used representing the message.
 1135        */
 1136       private void configureMessageLabel(JLabel label) {
 1137           Color color = (Color)DefaultLookup.get(optionPane, this,
 1138                                                  "OptionPane.messageForeground");
 1139           if (color != null) {
 1140               label.setForeground(color);
 1141           }
 1142           Font messageFont = (Font)DefaultLookup.get(optionPane, this,
 1143                                                      "OptionPane.messageFont");
 1144           if (messageFont != null) {
 1145               label.setFont(messageFont);
 1146           }
 1147       }
 1148   
 1149       /**
 1150        * Configures any necessary colors/fonts for the specified button
 1151        * used representing the button portion of the optionpane.
 1152        */
 1153       private void configureButton(JButton button) {
 1154           Font buttonFont = (Font)DefaultLookup.get(optionPane, this,
 1155                                               "OptionPane.buttonFont");
 1156           if (buttonFont != null) {
 1157               button.setFont(buttonFont);
 1158           }
 1159       }
 1160   
 1161       /**
 1162        * This class should be treated as a &quot;protected&quot; inner class.
 1163        * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
 1164        */
 1165       public class ButtonActionListener implements ActionListener {
 1166           protected int buttonIndex;
 1167   
 1168           public ButtonActionListener(int buttonIndex) {
 1169               this.buttonIndex = buttonIndex;
 1170           }
 1171   
 1172           public void actionPerformed(ActionEvent e) {
 1173               if (optionPane != null) {
 1174                   int optionType = optionPane.getOptionType();
 1175                   Object[] options = optionPane.getOptions();
 1176   
 1177                   /* If the option pane takes input, then store the input value
 1178                    * if custom options were specified, if the option type is
 1179                    * DEFAULT_OPTION, OR if option type is set to a predefined
 1180                    * one and the user chose the affirmative answer.
 1181                    */
 1182                   if (inputComponent != null) {
 1183                       if (options != null ||
 1184                           optionType == JOptionPane.DEFAULT_OPTION ||
 1185                           ((optionType == JOptionPane.YES_NO_OPTION ||
 1186                            optionType == JOptionPane.YES_NO_CANCEL_OPTION ||
 1187                            optionType == JOptionPane.OK_CANCEL_OPTION) &&
 1188                            buttonIndex == 0)) {
 1189                           resetInputValue();
 1190                       }
 1191                   }
 1192                   if (options == null) {
 1193                       if (optionType == JOptionPane.OK_CANCEL_OPTION &&
 1194                           buttonIndex == 1) {
 1195                           optionPane.setValue(Integer.valueOf(2));
 1196   
 1197                       } else {
 1198                           optionPane.setValue(Integer.valueOf(buttonIndex));
 1199                       }
 1200                   } else {
 1201                       optionPane.setValue(options[buttonIndex]);
 1202                   }
 1203               }
 1204           }
 1205       }
 1206   
 1207   
 1208       private class Handler implements ActionListener, MouseListener,
 1209                                        PropertyChangeListener {
 1210           //
 1211           // ActionListener
 1212           //
 1213           public void actionPerformed(ActionEvent e) {
 1214               optionPane.setInputValue(((JTextField)e.getSource()).getText());
 1215           }
 1216   
 1217   
 1218           //
 1219           // MouseListener
 1220           //
 1221           public void mouseClicked(MouseEvent e) {
 1222           }
 1223   
 1224           public void mouseReleased(MouseEvent e) {
 1225           }
 1226   
 1227           public void mouseEntered(MouseEvent e) {
 1228           }
 1229   
 1230           public void mouseExited(MouseEvent e) {
 1231           }
 1232   
 1233           public void mousePressed(MouseEvent e) {
 1234               if (e.getClickCount() == 2) {
 1235                   JList     list = (JList)e.getSource();
 1236                   int       index = list.locationToIndex(e.getPoint());
 1237   
 1238                   optionPane.setInputValue(list.getModel().getElementAt(index));
 1239               }
 1240           }
 1241   
 1242           //
 1243           // PropertyChangeListener
 1244           //
 1245           public void propertyChange(PropertyChangeEvent e) {
 1246               if(e.getSource() == optionPane) {
 1247                   // Option Pane Auditory Cue Activation
 1248                   // only respond to "ancestor" changes
 1249                   // the idea being that a JOptionPane gets a JDialog when it is
 1250                   // set to appear and loses it's JDialog when it is dismissed.
 1251                   if ("ancestor" == e.getPropertyName()) {
 1252                       JOptionPane op = (JOptionPane)e.getSource();
 1253                       boolean isComingUp;
 1254   
 1255                       // if the old value is null, then the JOptionPane is being
 1256                       // created since it didn't previously have an ancestor.
 1257                       if (e.getOldValue() == null) {
 1258                           isComingUp = true;
 1259                       } else {
 1260                           isComingUp = false;
 1261                       }
 1262   
 1263                       // figure out what to do based on the message type
 1264                       switch (op.getMessageType()) {
 1265                       case JOptionPane.PLAIN_MESSAGE:
 1266                           if (isComingUp) {
 1267                               BasicLookAndFeel.playSound(optionPane,
 1268                                                  "OptionPane.informationSound");
 1269                           }
 1270                           break;
 1271                       case JOptionPane.QUESTION_MESSAGE:
 1272                           if (isComingUp) {
 1273                               BasicLookAndFeel.playSound(optionPane,
 1274                                                "OptionPane.questionSound");
 1275                           }
 1276                           break;
 1277                       case JOptionPane.INFORMATION_MESSAGE:
 1278                           if (isComingUp) {
 1279                               BasicLookAndFeel.playSound(optionPane,
 1280                                                "OptionPane.informationSound");
 1281                           }
 1282                           break;
 1283                       case JOptionPane.WARNING_MESSAGE:
 1284                           if (isComingUp) {
 1285                               BasicLookAndFeel.playSound(optionPane,
 1286                                                "OptionPane.warningSound");
 1287                           }
 1288                           break;
 1289                       case JOptionPane.ERROR_MESSAGE:
 1290                           if (isComingUp) {
 1291                               BasicLookAndFeel.playSound(optionPane,
 1292                                                "OptionPane.errorSound");
 1293                           }
 1294                           break;
 1295                       default:
 1296                           System.err.println("Undefined JOptionPane type: " +
 1297                                              op.getMessageType());
 1298                           break;
 1299                       }
 1300                   }
 1301                   // Visual activity
 1302                   String         changeName = e.getPropertyName();
 1303   
 1304                   if(changeName == JOptionPane.OPTIONS_PROPERTY ||
 1305                      changeName == JOptionPane.INITIAL_VALUE_PROPERTY ||
 1306                      changeName == JOptionPane.ICON_PROPERTY ||
 1307                      changeName == JOptionPane.MESSAGE_TYPE_PROPERTY ||
 1308                      changeName == JOptionPane.OPTION_TYPE_PROPERTY ||
 1309                      changeName == JOptionPane.MESSAGE_PROPERTY ||
 1310                      changeName == JOptionPane.SELECTION_VALUES_PROPERTY ||
 1311                      changeName == JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY ||
 1312                      changeName == JOptionPane.WANTS_INPUT_PROPERTY) {
 1313                      uninstallComponents();
 1314                      installComponents();
 1315                      optionPane.validate();
 1316                   }
 1317                   else if (changeName == "componentOrientation") {
 1318                       ComponentOrientation o = (ComponentOrientation)e.getNewValue();
 1319                       JOptionPane op = (JOptionPane)e.getSource();
 1320                       if (o != e.getOldValue()) {
 1321                           op.applyComponentOrientation(o);
 1322                       }
 1323                   }
 1324               }
 1325           }
 1326       }
 1327   
 1328   
 1329       //
 1330       // Classes used when optionPane.getWantsInput returns true.
 1331       //
 1332   
 1333       /**
 1334        * A JTextField that allows you to specify an array of KeyStrokes that
 1335        * that will have their bindings processed regardless of whether or
 1336        * not they are registered on the JTextField. This is used as we really
 1337        * want the ActionListener to be notified so that we can push the
 1338        * change to the JOptionPane, but we also want additional bindings
 1339        * (those of the JRootPane) to be processed as well.
 1340        */
 1341       private static class MultiplexingTextField extends JTextField {
 1342           private KeyStroke[] strokes;
 1343   
 1344           MultiplexingTextField(int cols) {
 1345               super(cols);
 1346           }
 1347   
 1348           /**
 1349            * Sets the KeyStrokes that will be additional processed for
 1350            * ancestor bindings.
 1351            */
 1352           void setKeyStrokes(KeyStroke[] strokes) {
 1353               this.strokes = strokes;
 1354           }
 1355   
 1356           protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
 1357                                               int condition, boolean pressed) {
 1358               boolean processed = super.processKeyBinding(ks, e, condition,
 1359                                                           pressed);
 1360   
 1361               if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
 1362                   for (int counter = strokes.length - 1; counter >= 0;
 1363                            counter--) {
 1364                       if (strokes[counter].equals(ks)) {
 1365                           // Returning false will allow further processing
 1366                           // of the bindings, eg our parent Containers will get a
 1367                           // crack at them.
 1368                           return false;
 1369                       }
 1370                   }
 1371               }
 1372               return processed;
 1373           }
 1374       }
 1375   
 1376   
 1377   
 1378       /**
 1379        * Registered in the ActionMap. Sets the value of the option pane
 1380        * to <code>JOptionPane.CLOSED_OPTION</code>.
 1381        */
 1382       private static class Actions extends UIAction {
 1383           private static final String CLOSE = "close";
 1384   
 1385           Actions(String key) {
 1386               super(key);
 1387           }
 1388   
 1389           public void actionPerformed(ActionEvent e) {
 1390               if (getName() == CLOSE) {
 1391                   JOptionPane optionPane = (JOptionPane)e.getSource();
 1392   
 1393                   optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
 1394               }
 1395           }
 1396       }
 1397   
 1398   
 1399       /**
 1400        * This class is used to create the default buttons. This indirection is
 1401        * used so that addButtonComponents can tell which Buttons were created
 1402        * by us vs subclassers or from the JOptionPane itself.
 1403        */
 1404       private static class ButtonFactory {
 1405           private String text;
 1406           private int mnemonic;
 1407           private Icon icon;
 1408           private int minimumWidth = -1;
 1409   
 1410           ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) {
 1411               this.text = text;
 1412               this.mnemonic = mnemonic;
 1413               this.icon = icon;
 1414               this.minimumWidth = minimumWidth;
 1415           }
 1416   
 1417           JButton createButton() {
 1418               JButton button;
 1419   
 1420               if (minimumWidth > 0) {
 1421                   button = new ConstrainedButton(text, minimumWidth);
 1422               } else {
 1423                   button = new JButton(text);
 1424               }
 1425               if (icon != null) {
 1426                   button.setIcon(icon);
 1427               }
 1428               if (mnemonic != 0) {
 1429                   button.setMnemonic(mnemonic);
 1430               }
 1431               return button;
 1432           }
 1433   
 1434           private static class ConstrainedButton extends JButton {
 1435               int minimumWidth;
 1436   
 1437               ConstrainedButton(String text, int minimumWidth) {
 1438                   super(text);
 1439                   this.minimumWidth = minimumWidth;
 1440               }
 1441   
 1442               public Dimension getMinimumSize() {
 1443                   Dimension min = super.getMinimumSize();
 1444                   min.width = Math.max(min.width, minimumWidth);
 1445                   return min;
 1446               }
 1447   
 1448               public Dimension getPreferredSize() {
 1449                   Dimension pref = super.getPreferredSize();
 1450                   pref.width = Math.max(pref.width, minimumWidth);
 1451                   return pref;
 1452               }
 1453           }
 1454       }
 1455   }

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