alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (BasicOptionPaneUI.java)

This example Java source code file (BasicOptionPaneUI.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

actionlistener, awt, bean, buttonarealayout, buttonfactory, component, container, dimension, event, gui, icon, jbutton, jlabel, joptionpane, jpanel, multiplexingtextfield, object, plaf, string, swing

The BasicOptionPaneUI.java Java example source code

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

package javax.swing.plaf.basic;

import sun.swing.DefaultLookup;
import sun.swing.UIAction;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.OptionPaneUI;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import java.security.AccessController;

import sun.security.action.GetPropertyAction;


/**
 * Provides the basic look and feel for a <code>JOptionPane.
 * <code>BasicMessagePaneUI provides a means to place an icon,
 * message and buttons into a <code>Container.
 * Generally, the layout will look like:
 * <pre>
 *        ------------------
 *        | i | message    |
 *        | c | message    |
 *        | o | message    |
 *        | n | message    |
 *        ------------------
 *        |     buttons    |
 *        |________________|
 * </pre>
 * icon is an instance of <code>Icon that is wrapped inside a
 * <code>JLabel.  The message is an opaque object and is tested
 * for the following: if the message is a <code>Component it is
 * added to the <code>Container, if it is an Icon
 * it is wrapped inside a <code>JLabel and added to the
 * <code>Container otherwise it is wrapped inside a JLabel.
 * <p>
 * The above layout is used when the option pane's
 * <code>ComponentOrientation property is horizontal, left-to-right.
 * The layout will be adjusted appropriately for other orientations.
 * <p>
 * The <code>Container, message, icon, and buttons are all
 * determined from abstract methods.
 *
 * @author James Gosling
 * @author Scott Violet
 * @author Amy Fowler
 */
public class BasicOptionPaneUI extends OptionPaneUI {

    public static final int MinimumWidth = 262;
    public static final int MinimumHeight = 90;

    private static String newline;

    /**
     * <code>JOptionPane that the receiver is providing the
     * look and feel for.
     */
    protected JOptionPane         optionPane;

    protected Dimension minimumSize;

    /** JComponent provide for input if optionPane.getWantsInput() returns
     * true. */
    protected JComponent          inputComponent;

    /** Component to receive focus when messaged with selectInitialValue. */
    protected Component           initialFocusComponent;

    /** This is set to true in validateComponent if a Component is contained
     * in either the message or the buttons. */
    protected boolean             hasCustomComponents;

    protected PropertyChangeListener propertyChangeListener;

    private Handler handler;


    static {
        newline = java.security.AccessController.doPrivileged(
                                new GetPropertyAction("line.separator"));
        if (newline == null) {
            newline = "\n";
        }
    }

    static void loadActionMap(LazyActionMap map) {
        map.put(new Actions(Actions.CLOSE));
        BasicLookAndFeel.installAudioActionMap(map);
    }



    /**
      * Creates a new BasicOptionPaneUI instance.
      */
    public static ComponentUI createUI(JComponent x) {
        return new BasicOptionPaneUI();
    }

    /**
      * Installs the receiver as the L&F for the passed in
      * <code>JOptionPane.
      */
    public void installUI(JComponent c) {
        optionPane = (JOptionPane)c;
        installDefaults();
        optionPane.setLayout(createLayoutManager());
        installComponents();
        installListeners();
        installKeyboardActions();
    }

    /**
      * Removes the receiver from the L&F controller of the passed in split
      * pane.
      */
    public void uninstallUI(JComponent c) {
        uninstallComponents();
        optionPane.setLayout(null);
        uninstallKeyboardActions();
        uninstallListeners();
        uninstallDefaults();
        optionPane = null;
    }

    protected void installDefaults() {
        LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
                                         "OptionPane.foreground", "OptionPane.font");
        LookAndFeel.installBorder(optionPane, "OptionPane.border");
        minimumSize = UIManager.getDimension("OptionPane.minimumSize");
        LookAndFeel.installProperty(optionPane, "opaque", Boolean.TRUE);
    }

    protected void uninstallDefaults() {
        LookAndFeel.uninstallBorder(optionPane);
    }

    protected void installComponents() {
        optionPane.add(createMessageArea());

        Container separator = createSeparator();
        if (separator != null) {
            optionPane.add(separator);
        }
        optionPane.add(createButtonArea());
        optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
    }

    protected void uninstallComponents() {
        hasCustomComponents = false;
        inputComponent = null;
        initialFocusComponent = null;
        optionPane.removeAll();
    }

    protected LayoutManager createLayoutManager() {
        return new BoxLayout(optionPane, BoxLayout.Y_AXIS);
    }

    protected void installListeners() {
        if ((propertyChangeListener = createPropertyChangeListener()) != null) {
            optionPane.addPropertyChangeListener(propertyChangeListener);
        }
    }

    protected void uninstallListeners() {
        if (propertyChangeListener != null) {
            optionPane.removePropertyChangeListener(propertyChangeListener);
            propertyChangeListener = null;
        }
        handler = null;
    }

    protected PropertyChangeListener createPropertyChangeListener() {
        return getHandler();
    }

    private Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    }

    protected void installKeyboardActions() {
        InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

        SwingUtilities.replaceUIInputMap(optionPane, JComponent.
                                       WHEN_IN_FOCUSED_WINDOW, map);

        LazyActionMap.installLazyActionMap(optionPane, BasicOptionPaneUI.class,
                                           "OptionPane.actionMap");
    }

    protected void uninstallKeyboardActions() {
        SwingUtilities.replaceUIInputMap(optionPane, JComponent.
                                       WHEN_IN_FOCUSED_WINDOW, null);
        SwingUtilities.replaceUIActionMap(optionPane, null);
    }

    InputMap getInputMap(int condition) {
        if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
            Object[] bindings = (Object[])DefaultLookup.get(
                             optionPane, this, "OptionPane.windowBindings");
            if (bindings != null) {
                return LookAndFeel.makeComponentInputMap(optionPane, bindings);
            }
        }
        return null;
    }

    /**
     * Returns the minimum size the option pane should be. Primarily
     * provided for subclassers wishing to offer a different minimum size.
     */
    public Dimension getMinimumOptionPaneSize() {
        if (minimumSize == null) {
            return new Dimension(MinimumWidth, MinimumHeight);
        }
        return new Dimension(minimumSize.width,
                             minimumSize.height);
    }

    /**
     * If <code>c is the JOptionPane the receiver
     * is contained in, the preferred
     * size that is returned is the maximum of the preferred size of
     * the <code>LayoutManager for the JOptionPane, and
     * <code>getMinimumOptionPaneSize.
     */
    public Dimension getPreferredSize(JComponent c) {
        if (c == optionPane) {
            Dimension            ourMin = getMinimumOptionPaneSize();
            LayoutManager        lm = c.getLayout();

            if (lm != null) {
                Dimension         lmSize = lm.preferredLayoutSize(c);

                if (ourMin != null)
                    return new Dimension
                        (Math.max(lmSize.width, ourMin.width),
                         Math.max(lmSize.height, ourMin.height));
                return lmSize;
            }
            return ourMin;
        }
        return null;
    }

    /**
     * Messaged from installComponents to create a Container containing the
     * body of the message. The icon is the created by calling
     * <code>addIcon.
     */
    protected Container createMessageArea() {
        JPanel top = new JPanel();
        Border topBorder = (Border)DefaultLookup.get(optionPane, this,
                                             "OptionPane.messageAreaBorder");
        if (topBorder != null) {
            top.setBorder(topBorder);
        }
        top.setLayout(new BorderLayout());

        /* Fill the body. */
        Container          body = new JPanel(new GridBagLayout());
        Container          realBody = new JPanel(new BorderLayout());

        body.setName("OptionPane.body");
        realBody.setName("OptionPane.realBody");

        if (getIcon() != null) {
            JPanel sep = new JPanel();
            sep.setName("OptionPane.separator");
            sep.setPreferredSize(new Dimension(15, 1));
            realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
        }
        realBody.add(body, BorderLayout.CENTER);

        GridBagConstraints cons = new GridBagConstraints();
        cons.gridx = cons.gridy = 0;
        cons.gridwidth = GridBagConstraints.REMAINDER;
        cons.gridheight = 1;
        cons.anchor = DefaultLookup.getInt(optionPane, this,
                      "OptionPane.messageAnchor", GridBagConstraints.CENTER);
        cons.insets = new Insets(0,0,3,0);

        addMessageComponents(body, cons, getMessage(),
                          getMaxCharactersPerLineCount(), false);
        top.add(realBody, BorderLayout.CENTER);

        addIcon(top);
        return top;
    }

    /**
     * Creates the appropriate object to represent <code>msg and
     * places it into <code>container. If msg is an
     * instance of Component, it is added directly, if it is an Icon,
     * a JLabel is created to represent it, otherwise a JLabel is
     * created for the string, if <code>d is an Object[], this
     * method will be recursively invoked for the children.
     * <code>internallyCreated is true if Objc is an instance
     * of Component and was created internally by this method (this is
     * used to correctly set hasCustomComponents only if !internallyCreated).
     */
    protected void addMessageComponents(Container container,
                                     GridBagConstraints cons,
                                     Object msg, int maxll,
                                     boolean internallyCreated) {
        if (msg == null) {
            return;
        }
        if (msg instanceof Component) {
            // To workaround problem where Gridbad will set child
            // to its minimum size if its preferred size will not fit
            // within allocated cells
            if (msg instanceof JScrollPane || msg instanceof JPanel) {
                cons.fill = GridBagConstraints.BOTH;
                cons.weighty = 1;
            } else {
                cons.fill = GridBagConstraints.HORIZONTAL;
            }
            cons.weightx = 1;

            container.add((Component) msg, cons);
            cons.weightx = 0;
            cons.weighty = 0;
            cons.fill = GridBagConstraints.NONE;
            cons.gridy++;
            if (!internallyCreated) {
                hasCustomComponents = true;
            }

        } else if (msg instanceof Object[]) {
            Object [] msgs = (Object[]) msg;
            for (Object o : msgs) {
                addMessageComponents(container, cons, o, maxll, false);
            }

        } else if (msg instanceof Icon) {
            JLabel label = new JLabel( (Icon)msg, SwingConstants.CENTER );
            configureMessageLabel(label);
            addMessageComponents(container, cons, label, maxll, true);

        } else {
            String s = msg.toString();
            int len = s.length();
            if (len <= 0) {
                return;
            }
            int nl;
            int nll = 0;

            if ((nl = s.indexOf(newline)) >= 0) {
                nll = newline.length();
            } else if ((nl = s.indexOf("\r\n")) >= 0) {
                nll = 2;
            } else if ((nl = s.indexOf('\n')) >= 0) {
                nll = 1;
            }
            if (nl >= 0) {
                // break up newlines
                if (nl == 0) {
                    JPanel breakPanel = new JPanel() {
                        public Dimension getPreferredSize() {
                            Font       f = getFont();

                            if (f != null) {
                                return new Dimension(1, f.getSize() + 2);
                            }
                            return new Dimension(0, 0);
                        }
                    };
                    breakPanel.setName("OptionPane.break");
                    addMessageComponents(container, cons, breakPanel, maxll,
                                         true);
                } else {
                    addMessageComponents(container, cons, s.substring(0, nl),
                                      maxll, false);
                }
                addMessageComponents(container, cons, s.substring(nl + nll), maxll,
                                  false);

            } else if (len > maxll) {
                Container c = Box.createVerticalBox();
                c.setName("OptionPane.verticalBox");
                burstStringInto(c, s, maxll);
                addMessageComponents(container, cons, c, maxll, true );

            } else {
                JLabel label;
                label = new JLabel( s, JLabel.LEADING );
                label.setName("OptionPane.label");
                configureMessageLabel(label);
                addMessageComponents(container, cons, label, maxll, true);
            }
        }
    }

    /**
     * Returns the message to display from the JOptionPane the receiver is
     * providing the look and feel for.
     */
    protected Object getMessage() {
        inputComponent = null;
        if (optionPane != null) {
            if (optionPane.getWantsInput()) {
                /* Create a user component to capture the input. If the
                   selectionValues are non null the component and there
                   are < 20 values it'll be a combobox, if non null and
                   >= 20, it'll be a list, otherwise it'll be a textfield. */
                Object             message = optionPane.getMessage();
                Object[]           sValues = optionPane.getSelectionValues();
                Object             inputValue = optionPane
                                           .getInitialSelectionValue();
                JComponent         toAdd;

                if (sValues != null) {
                    if (sValues.length < 20) {
                        JComboBox            cBox = new JComboBox();

                        cBox.setName("OptionPane.comboBox");
                        for(int counter = 0, maxCounter = sValues.length;
                            counter < maxCounter; counter++) {
                            cBox.addItem(sValues[counter]);
                        }
                        if (inputValue != null) {
                            cBox.setSelectedItem(inputValue);
                        }
                        inputComponent = cBox;
                        toAdd = cBox;

                    } else {
                        JList                list = new JList(sValues);
                        JScrollPane          sp = new JScrollPane(list);

                        sp.setName("OptionPane.scrollPane");
                        list.setName("OptionPane.list");
                        list.setVisibleRowCount(10);
                        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                        if(inputValue != null)
                            list.setSelectedValue(inputValue, true);
                        list.addMouseListener(getHandler());
                        toAdd = sp;
                        inputComponent = list;
                    }

                } else {
                    MultiplexingTextField   tf = new MultiplexingTextField(20);

                    tf.setName("OptionPane.textField");
                    tf.setKeyStrokes(new KeyStroke[] {
                                     KeyStroke.getKeyStroke("ENTER") } );
                    if (inputValue != null) {
                        String inputString = inputValue.toString();
                        tf.setText(inputString);
                        tf.setSelectionStart(0);
                        tf.setSelectionEnd(inputString.length());
                    }
                    tf.addActionListener(getHandler());
                    toAdd = inputComponent = tf;
                }

                Object[]           newMessage;

                if (message == null) {
                    newMessage = new Object[1];
                    newMessage[0] = toAdd;

                } else {
                    newMessage = new Object[2];
                    newMessage[0] = message;
                    newMessage[1] = toAdd;
                }
                return newMessage;
            }
            return optionPane.getMessage();
        }
        return null;
    }

    /**
     * Creates and adds a JLabel representing the icon returned from
     * <code>getIcon to top. This is messaged from
     * <code>createMessageArea
     */
    protected void addIcon(Container top) {
        /* Create the icon. */
        Icon                  sideIcon = getIcon();

        if (sideIcon != null) {
            JLabel            iconLabel = new JLabel(sideIcon);

            iconLabel.setName("OptionPane.iconLabel");
            iconLabel.setVerticalAlignment(SwingConstants.TOP);
            top.add(iconLabel, BorderLayout.BEFORE_LINE_BEGINS);
        }
    }

    /**
     * Returns the icon from the JOptionPane the receiver is providing
     * the look and feel for, or the default icon as returned from
     * <code>getDefaultIcon.
     */
    protected Icon getIcon() {
        Icon      mIcon = (optionPane == null ? null : optionPane.getIcon());

        if(mIcon == null && optionPane != null)
            mIcon = getIconForType(optionPane.getMessageType());
        return mIcon;
    }

    /**
     * Returns the icon to use for the passed in type.
     */
    protected Icon getIconForType(int messageType) {
        if(messageType < 0 || messageType > 3)
            return null;
        String propertyName = null;
        switch(messageType) {
        case 0:
            propertyName = "OptionPane.errorIcon";
            break;
        case 1:
            propertyName = "OptionPane.informationIcon";
            break;
        case 2:
            propertyName = "OptionPane.warningIcon";
            break;
        case 3:
            propertyName = "OptionPane.questionIcon";
            break;
        }
        if (propertyName != null) {
            return (Icon)DefaultLookup.get(optionPane, this, propertyName);
        }
        return null;
    }

    /**
     * Returns the maximum number of characters to place on a line.
     */
    protected int getMaxCharactersPerLineCount() {
        return optionPane.getMaxCharactersPerLineCount();
    }

   /**
     * Recursively creates new JLabel instances to represent <code>d.
     * Each JLabel instance is added to <code>c.
     */
    protected void burstStringInto(Container c, String d, int maxll) {
        // Primitive line wrapping
        int len = d.length();
        if (len <= 0)
            return;
        if (len > maxll) {
            int p = d.lastIndexOf(' ', maxll);
            if (p <= 0)
                p = d.indexOf(' ', maxll);
            if (p > 0 && p < len) {
                burstStringInto(c, d.substring(0, p), maxll);
                burstStringInto(c, d.substring(p + 1), maxll);
                return;
            }
        }
        JLabel label = new JLabel(d, JLabel.LEFT);
        label.setName("OptionPane.label");
        configureMessageLabel(label);
        c.add(label);
    }

    protected Container createSeparator() {
        return null;
    }

    /**
     * Creates and returns a Container containing the buttons. The buttons
     * are created by calling <code>getButtons.
     */
    protected Container createButtonArea() {
        JPanel bottom = new JPanel();
        Border border = (Border)DefaultLookup.get(optionPane, this,
                                          "OptionPane.buttonAreaBorder");
        bottom.setName("OptionPane.buttonArea");
        if (border != null) {
            bottom.setBorder(border);
        }
        bottom.setLayout(new ButtonAreaLayout(
           DefaultLookup.getBoolean(optionPane, this,
                                    "OptionPane.sameSizeButtons", true),
           DefaultLookup.getInt(optionPane, this, "OptionPane.buttonPadding",
                                6),
           DefaultLookup.getInt(optionPane, this,
                        "OptionPane.buttonOrientation", SwingConstants.CENTER),
           DefaultLookup.getBoolean(optionPane, this, "OptionPane.isYesLast",
                                    false)));
        addButtonComponents(bottom, getButtons(), getInitialValueIndex());
        return bottom;
    }

    /**
     * Creates the appropriate object to represent each of the objects in
     * <code>buttons and adds it to container. This
     * differs from addMessageComponents in that it will recurse on
     * <code>buttons and that if button is not a Component
     * it will create an instance of JButton.
     */
    protected void addButtonComponents(Container container, Object[] buttons,
                                 int initialIndex) {
        if (buttons != null && buttons.length > 0) {
            boolean            sizeButtonsToSame = getSizeButtonsToSameWidth();
            boolean            createdAll = true;
            int                numButtons = buttons.length;
            JButton[]          createdButtons = null;
            int                maxWidth = 0;

            if (sizeButtonsToSame) {
                createdButtons = new JButton[numButtons];
            }

            for(int counter = 0; counter < numButtons; counter++) {
                Object       button = buttons[counter];
                Component    newComponent;

                if (button instanceof Component) {
                    createdAll = false;
                    newComponent = (Component)button;
                    container.add(newComponent);
                    hasCustomComponents = true;

                } else {
                    JButton      aButton;

                    if (button instanceof ButtonFactory) {
                        aButton = ((ButtonFactory)button).createButton();
                    }
                    else if (button instanceof Icon)
                        aButton = new JButton((Icon)button);
                    else
                        aButton = new JButton(button.toString());

                    aButton.setName("OptionPane.button");
                    aButton.setMultiClickThreshhold(DefaultLookup.getInt(
                          optionPane, this, "OptionPane.buttonClickThreshhold",
                          0));
                    configureButton(aButton);

                    container.add(aButton);

                    ActionListener buttonListener = createButtonActionListener(counter);
                    if (buttonListener != null) {
                        aButton.addActionListener(buttonListener);
                    }
                    newComponent = aButton;
                }
                if (sizeButtonsToSame && createdAll &&
                   (newComponent instanceof JButton)) {
                    createdButtons[counter] = (JButton)newComponent;
                    maxWidth = Math.max(maxWidth,
                                        newComponent.getMinimumSize().width);
                }
                if (counter == initialIndex) {
                    initialFocusComponent = newComponent;
                    if (initialFocusComponent instanceof JButton) {
                        JButton defaultB = (JButton)initialFocusComponent;
                        defaultB.addHierarchyListener(new HierarchyListener() {
                            public void hierarchyChanged(HierarchyEvent e) {
                                if ((e.getChangeFlags() &
                                        HierarchyEvent.PARENT_CHANGED) != 0) {
                                    JButton defaultButton = (JButton) e.getComponent();
                                    JRootPane root =
                                            SwingUtilities.getRootPane(defaultButton);
                                    if (root != null) {
                                        root.setDefaultButton(defaultButton);
                                    }
                                }
                            }
                        });
                    }
                }
            }
            ((ButtonAreaLayout)container.getLayout()).
                              setSyncAllWidths((sizeButtonsToSame && createdAll));
            /* Set the padding, windows seems to use 8 if <= 2 components,
               otherwise 4 is used. It may actually just be the size of the
               buttons is always the same, not sure. */
            if (DefaultLookup.getBoolean(optionPane, this,
                   "OptionPane.setButtonMargin", true) && sizeButtonsToSame &&
                   createdAll) {
                JButton               aButton;
                int                   padSize;

                padSize = (numButtons <= 2? 8 : 4);

                for(int counter = 0; counter < numButtons; counter++) {
                    aButton = createdButtons[counter];
                    aButton.setMargin(new Insets(2, padSize, 2, padSize));
                }
            }
        }
    }

    protected ActionListener createButtonActionListener(int buttonIndex) {
        return new ButtonActionListener(buttonIndex);
    }

    /**
     * Returns the buttons to display from the JOptionPane the receiver is
     * providing the look and feel for. If the JOptionPane has options
     * set, they will be provided, otherwise if the optionType is
     * YES_NO_OPTION, yesNoOptions is returned, if the type is
     * YES_NO_CANCEL_OPTION yesNoCancelOptions is returned, otherwise
     * defaultButtons are returned.
     */
    protected Object[] getButtons() {
        if (optionPane != null) {
            Object[] suppliedOptions = optionPane.getOptions();

            if (suppliedOptions == null) {
                Object[] defaultOptions;
                int type = optionPane.getOptionType();
                Locale l = optionPane.getLocale();
                int minimumWidth =
                    DefaultLookup.getInt(optionPane, this,
                                        "OptionPane.buttonMinimumWidth",-1);
                if (type == JOptionPane.YES_NO_OPTION) {
                    defaultOptions = new ButtonFactory[2];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.yesButtonText", l),
                        getMnemonic("OptionPane.yesButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.yesIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.noButtonText", l),
                        getMnemonic("OptionPane.noButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.noIcon"), minimumWidth);
                } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) {
                    defaultOptions = new ButtonFactory[3];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.yesButtonText", l),
                        getMnemonic("OptionPane.yesButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.yesIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.noButtonText",l),
                        getMnemonic("OptionPane.noButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.noIcon"), minimumWidth);
                    defaultOptions[2] = new ButtonFactory(
                        UIManager.getString("OptionPane.cancelButtonText",l),
                        getMnemonic("OptionPane.cancelButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.cancelIcon"), minimumWidth);
                } else if (type == JOptionPane.OK_CANCEL_OPTION) {
                    defaultOptions = new ButtonFactory[2];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.okButtonText",l),
                        getMnemonic("OptionPane.okButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.okIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.cancelButtonText",l),
                        getMnemonic("OptionPane.cancelButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.cancelIcon"), minimumWidth);
                } else {
                    defaultOptions = new ButtonFactory[1];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.okButtonText",l),
                        getMnemonic("OptionPane.okButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.okIcon"), minimumWidth);
                }
                return defaultOptions;

            }
            return suppliedOptions;
        }
        return null;
    }

    private int getMnemonic(String key, Locale l) {
        String value = (String)UIManager.get(key, l);

        if (value == null) {
            return 0;
        }
        try {
            return Integer.parseInt(value);
        }
        catch (NumberFormatException nfe) { }
        return 0;
    }

    /**
     * Returns true, basic L&F wants all the buttons to have the same
     * width.
     */
    protected boolean getSizeButtonsToSameWidth() {
        return true;
    }

    /**
     * Returns the initial index into the buttons to select. The index
     * is calculated from the initial value from the JOptionPane and
     * options of the JOptionPane or 0.
     */
    protected int getInitialValueIndex() {
        if (optionPane != null) {
            Object             iv = optionPane.getInitialValue();
            Object[]           options = optionPane.getOptions();

            if(options == null) {
                return 0;
            }
            else if(iv != null) {
                for(int counter = options.length - 1; counter >= 0; counter--){
                    if(options[counter].equals(iv))
                        return counter;
                }
            }
        }
        return -1;
    }

    /**
     * Sets the input value in the option pane the receiver is providing
     * the look and feel for based on the value in the inputComponent.
     */
    protected void resetInputValue() {
        if(inputComponent != null && (inputComponent instanceof JTextField)) {
            optionPane.setInputValue(((JTextField)inputComponent).getText());

        } else if(inputComponent != null &&
                  (inputComponent instanceof JComboBox)) {
            optionPane.setInputValue(((JComboBox)inputComponent)
                                     .getSelectedItem());
        } else if(inputComponent != null) {
            optionPane.setInputValue(((JList)inputComponent)
                                     .getSelectedValue());
        }
    }


    /**
     * If inputComponent is non-null, the focus is requested on that,
     * otherwise request focus on the default value
     */
    public void selectInitialValue(JOptionPane op) {
        if (inputComponent != null)
            inputComponent.requestFocus();
        else {
            if (initialFocusComponent != null)
                initialFocusComponent.requestFocus();

            if (initialFocusComponent instanceof JButton) {
                JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
                if (root != null) {
                    root.setDefaultButton((JButton)initialFocusComponent);
                }
            }
        }
    }

    /**
     * Returns true if in the last call to validateComponent the message
     * or buttons contained a subclass of Component.
     */
    public boolean containsCustomComponents(JOptionPane op) {
        return hasCustomComponents;
    }


    /**
     * <code>ButtonAreaLayout behaves in a similar manner to
     * <code>FlowLayout. It lays out all components from left to
     * right. If <code>syncAllWidths is true, the widths of each
     * component will be set to the largest preferred size width.
     *
     * This class should be treated as a "protected" inner class.
     * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
     */
    public static class ButtonAreaLayout implements LayoutManager {
        protected boolean           syncAllWidths;
        protected int               padding;
        /** If true, children are lumped together in parent. */
        protected boolean           centersChildren;
        private int orientation;
        private boolean reverseButtons;
        /**
         * Indicates whether or not centersChildren should be used vs
         * the orientation. This is done for backward compatibility
         * for subclassers.
         */
        private boolean useOrientation;

        public ButtonAreaLayout(boolean syncAllWidths, int padding) {
            this.syncAllWidths = syncAllWidths;
            this.padding = padding;
            centersChildren = true;
            useOrientation = false;
        }

        ButtonAreaLayout(boolean syncAllSizes, int padding, int orientation,
                         boolean reverseButtons) {
            this(syncAllSizes, padding);
            useOrientation = true;
            this.orientation = orientation;
            this.reverseButtons = reverseButtons;
        }

        public void setSyncAllWidths(boolean newValue) {
            syncAllWidths = newValue;
        }

        public boolean getSyncAllWidths() {
            return syncAllWidths;
        }

        public void setPadding(int newPadding) {
            this.padding = newPadding;
        }

        public int getPadding() {
            return padding;
        }

        public void setCentersChildren(boolean newValue) {
            centersChildren = newValue;
            useOrientation = false;
        }

        public boolean getCentersChildren() {
            return centersChildren;
        }

        private int getOrientation(Container container) {
            if (!useOrientation) {
                return SwingConstants.CENTER;
            }
            if (container.getComponentOrientation().isLeftToRight()) {
                return orientation;
            }
            switch (orientation) {
            case SwingConstants.LEFT:
                return SwingConstants.RIGHT;
            case SwingConstants.RIGHT:
                return SwingConstants.LEFT;
            case SwingConstants.CENTER:
                return SwingConstants.CENTER;
            }
            return SwingConstants.LEFT;
        }

        public void addLayoutComponent(String string, Component comp) {
        }

        public void layoutContainer(Container container) {
            Component[]      children = container.getComponents();

            if(children != null && children.length > 0) {
                int               numChildren = children.length;
                Insets            insets = container.getInsets();
                int maxWidth = 0;
                int maxHeight = 0;
                int totalButtonWidth = 0;
                int x = 0;
                int xOffset = 0;
                boolean ltr = container.getComponentOrientation().
                                        isLeftToRight();
                boolean reverse = (ltr) ? reverseButtons : !reverseButtons;

                for(int counter = 0; counter < numChildren; counter++) {
                    Dimension pref = children[counter].getPreferredSize();
                    maxWidth = Math.max(maxWidth, pref.width);
                    maxHeight = Math.max(maxHeight, pref.height);
                    totalButtonWidth += pref.width;
                }
                if (getSyncAllWidths()) {
                    totalButtonWidth = maxWidth * numChildren;
                }
                totalButtonWidth += (numChildren - 1) * padding;

                switch (getOrientation(container)) {
                case SwingConstants.LEFT:
                    x = insets.left;
                    break;
                case SwingConstants.RIGHT:
                    x = container.getWidth() - insets.right - totalButtonWidth;
                    break;
                case SwingConstants.CENTER:
                    if (getCentersChildren() || numChildren < 2) {
                        x = (container.getWidth() - totalButtonWidth) / 2;
                    }
                    else {
                        x = insets.left;
                        if (getSyncAllWidths()) {
                            xOffset = (container.getWidth() - insets.left -
                                       insets.right - totalButtonWidth) /
                                (numChildren - 1) + maxWidth;
                        }
                        else {
                            xOffset = (container.getWidth() - insets.left -
                                       insets.right - totalButtonWidth) /
                                      (numChildren - 1);
                        }
                    }
                    break;
                }

                for (int counter = 0; counter < numChildren; counter++) {
                    int index = (reverse) ? numChildren - counter - 1 :
                                counter;
                    Dimension pref = children[index].getPreferredSize();

                    if (getSyncAllWidths()) {
                        children[index].setBounds(x, insets.top,
                                                  maxWidth, maxHeight);
                    }
                    else {
                        children[index].setBounds(x, insets.top, pref.width,
                                                  pref.height);
                    }
                    if (xOffset != 0) {
                        x += xOffset;
                    }
                    else {
                        x += children[index].getWidth() + padding;
                    }
                }
            }
        }

        public Dimension minimumLayoutSize(Container c) {
            if(c != null) {
                Component[]       children = c.getComponents();

                if(children != null && children.length > 0) {
                    Dimension     aSize;
                    int           numChildren = children.length;
                    int           height = 0;
                    Insets        cInsets = c.getInsets();
                    int           extraHeight = cInsets.top + cInsets.bottom;
                    int           extraWidth = cInsets.left + cInsets.right;

                    if (syncAllWidths) {
                        int              maxWidth = 0;

                        for(int counter = 0; counter < numChildren; counter++){
                            aSize = children[counter].getPreferredSize();
                            height = Math.max(height, aSize.height);
                            maxWidth = Math.max(maxWidth, aSize.width);
                        }
                        return new Dimension(extraWidth + (maxWidth * numChildren) +
                                             (numChildren - 1) * padding,
                                             extraHeight + height);
                    }
                    else {
                        int        totalWidth = 0;

                        for(int counter = 0; counter < numChildren; counter++){
                            aSize = children[counter].getPreferredSize();
                            height = Math.max(height, aSize.height);
                            totalWidth += aSize.width;
                        }
                        totalWidth += ((numChildren - 1) * padding);
                        return new Dimension(extraWidth + totalWidth, extraHeight + height);
                    }
                }
            }
            return new Dimension(0, 0);
        }

        public Dimension preferredLayoutSize(Container c) {
            return minimumLayoutSize(c);
        }

        public void removeLayoutComponent(Component c) { }
    }


    /**
     * This class should be treated as a "protected" inner class.
     * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
     */
    public class PropertyChangeHandler implements PropertyChangeListener {
        /**
         * If the source of the PropertyChangeEvent <code>e equals the
         * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
         * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
         * validateComponent is invoked.
         */
        public void propertyChange(PropertyChangeEvent e) {
            getHandler().propertyChange(e);
        }
    }

    /**
     * Configures any necessary colors/fonts for the specified label
     * used representing the message.
     */
    private void configureMessageLabel(JLabel label) {
        Color color = (Color)DefaultLookup.get(optionPane, this,
                                               "OptionPane.messageForeground");
        if (color != null) {
            label.setForeground(color);
        }
        Font messageFont = (Font)DefaultLookup.get(optionPane, this,
                                                   "OptionPane.messageFont");
        if (messageFont != null) {
            label.setFont(messageFont);
        }
    }

    /**
     * Configures any necessary colors/fonts for the specified button
     * used representing the button portion of the optionpane.
     */
    private void configureButton(JButton button) {
        Font buttonFont = (Font)DefaultLookup.get(optionPane, this,
                                            "OptionPane.buttonFont");
        if (buttonFont != null) {
            button.setFont(buttonFont);
        }
    }

    /**
     * This class should be treated as a "protected" inner class.
     * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
     */
    public class ButtonActionListener implements ActionListener {
        protected int buttonIndex;

        public ButtonActionListener(int buttonIndex) {
            this.buttonIndex = buttonIndex;
        }

        public void actionPerformed(ActionEvent e) {
            if (optionPane != null) {
                int optionType = optionPane.getOptionType();
                Object[] options = optionPane.getOptions();

                /* If the option pane takes input, then store the input value
                 * if custom options were specified, if the option type is
                 * DEFAULT_OPTION, OR if option type is set to a predefined
                 * one and the user chose the affirmative answer.
                 */
                if (inputComponent != null) {
                    if (options != null ||
                        optionType == JOptionPane.DEFAULT_OPTION ||
                        ((optionType == JOptionPane.YES_NO_OPTION ||
                         optionType == JOptionPane.YES_NO_CANCEL_OPTION ||
                         optionType == JOptionPane.OK_CANCEL_OPTION) &&
                         buttonIndex == 0)) {
                        resetInputValue();
                    }
                }
                if (options == null) {
                    if (optionType == JOptionPane.OK_CANCEL_OPTION &&
                        buttonIndex == 1) {
                        optionPane.setValue(Integer.valueOf(2));

                    } else {
                        optionPane.setValue(Integer.valueOf(buttonIndex));
                    }
                } else {
                    optionPane.setValue(options[buttonIndex]);
                }
            }
        }
    }


    private class Handler implements ActionListener, MouseListener,
                                     PropertyChangeListener {
        //
        // ActionListener
        //
        public void actionPerformed(ActionEvent e) {
            optionPane.setInputValue(((JTextField)e.getSource()).getText());
        }


        //
        // MouseListener
        //
        public void mouseClicked(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }

        public void mousePressed(MouseEvent e) {
            if (e.getClickCount() == 2) {
                JList     list = (JList)e.getSource();
                int       index = list.locationToIndex(e.getPoint());

                optionPane.setInputValue(list.getModel().getElementAt(index));
                optionPane.setValue(JOptionPane.OK_OPTION);
            }
        }

        //
        // PropertyChangeListener
        //
        public void propertyChange(PropertyChangeEvent e) {
            if(e.getSource() == optionPane) {
                // Option Pane Auditory Cue Activation
                // only respond to "ancestor" changes
                // the idea being that a JOptionPane gets a JDialog when it is
                // set to appear and loses it's JDialog when it is dismissed.
                if ("ancestor" == e.getPropertyName()) {
                    JOptionPane op = (JOptionPane)e.getSource();
                    boolean isComingUp;

                    // if the old value is null, then the JOptionPane is being
                    // created since it didn't previously have an ancestor.
                    if (e.getOldValue() == null) {
                        isComingUp = true;
                    } else {
                        isComingUp = false;
                    }

                    // figure out what to do based on the message type
                    switch (op.getMessageType()) {
                    case JOptionPane.PLAIN_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                               "OptionPane.informationSound");
                        }
                        break;
                    case JOptionPane.QUESTION_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.questionSound");
                        }
                        break;
                    case JOptionPane.INFORMATION_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.informationSound");
                        }
                        break;
                    case JOptionPane.WARNING_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.warningSound");
                        }
                        break;
                    case JOptionPane.ERROR_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.errorSound");
                        }
                        break;
                    default:
                        System.err.println("Undefined JOptionPane type: " +
                                           op.getMessageType());
                        break;
                    }
                }
                // Visual activity
                String         changeName = e.getPropertyName();

                if(changeName == JOptionPane.OPTIONS_PROPERTY ||
                   changeName == JOptionPane.INITIAL_VALUE_PROPERTY ||
                   changeName == JOptionPane.ICON_PROPERTY ||
                   changeName == JOptionPane.MESSAGE_TYPE_PROPERTY ||
                   changeName == JOptionPane.OPTION_TYPE_PROPERTY ||
                   changeName == JOptionPane.MESSAGE_PROPERTY ||
                   changeName == JOptionPane.SELECTION_VALUES_PROPERTY ||
                   changeName == JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY ||
                   changeName == JOptionPane.WANTS_INPUT_PROPERTY) {
                   uninstallComponents();
                   installComponents();
                   optionPane.validate();
                }
                else if (changeName == "componentOrientation") {
                    ComponentOrientation o = (ComponentOrientation)e.getNewValue();
                    JOptionPane op = (JOptionPane)e.getSource();
                    if (o != e.getOldValue()) {
                        op.applyComponentOrientation(o);
                    }
                }
            }
        }
    }


    //
    // Classes used when optionPane.getWantsInput returns true.
    //

    /**
     * A JTextField that allows you to specify an array of KeyStrokes that
     * that will have their bindings processed regardless of whether or
     * not they are registered on the JTextField. This is used as we really
     * want the ActionListener to be notified so that we can push the
     * change to the JOptionPane, but we also want additional bindings
     * (those of the JRootPane) to be processed as well.
     */
    private static class MultiplexingTextField extends JTextField {
        private KeyStroke[] strokes;

        MultiplexingTextField(int cols) {
            super(cols);
        }

        /**
         * Sets the KeyStrokes that will be additional processed for
         * ancestor bindings.
         */
        void setKeyStrokes(KeyStroke[] strokes) {
            this.strokes = strokes;
        }

        protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
                                            int condition, boolean pressed) {
            boolean processed = super.processKeyBinding(ks, e, condition,
                                                        pressed);

            if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
                for (int counter = strokes.length - 1; counter >= 0;
                         counter--) {
                    if (strokes[counter].equals(ks)) {
                        // Returning false will allow further processing
                        // of the bindings, eg our parent Containers will get a
                        // crack at them.
                        return false;
                    }
                }
            }
            return processed;
        }
    }



    /**
     * Registered in the ActionMap. Sets the value of the option pane
     * to <code>JOptionPane.CLOSED_OPTION.
     */
    private static class Actions extends UIAction {
        private static final String CLOSE = "close";

        Actions(String key) {
            super(key);
        }

        public void actionPerformed(ActionEvent e) {
            if (getName() == CLOSE) {
                JOptionPane optionPane = (JOptionPane)e.getSource();

                optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
            }
        }
    }


    /**
     * This class is used to create the default buttons. This indirection is
     * used so that addButtonComponents can tell which Buttons were created
     * by us vs subclassers or from the JOptionPane itself.
     */
    private static class ButtonFactory {
        private String text;
        private int mnemonic;
        private Icon icon;
        private int minimumWidth = -1;

        ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) {
            this.text = text;
            this.mnemonic = mnemonic;
            this.icon = icon;
            this.minimumWidth = minimumWidth;
        }

        JButton createButton() {
            JButton button;

            if (minimumWidth > 0) {
                button = new ConstrainedButton(text, minimumWidth);
            } else {
                button = new JButton(text);
            }
            if (icon != null) {
                button.setIcon(icon);
            }
            if (mnemonic != 0) {
                button.setMnemonic(mnemonic);
            }
            return button;
        }

        private static class ConstrainedButton extends JButton {
            int minimumWidth;

            ConstrainedButton(String text, int minimumWidth) {
                super(text);
                this.minimumWidth = minimumWidth;
            }

            public Dimension getMinimumSize() {
                Dimension min = super.getMinimumSize();
                min.width = Math.max(min.width, minimumWidth);
                return min;
            }

            public Dimension getPreferredSize() {
                Dimension pref = super.getPreferredSize();
                pref.width = Math.max(pref.width, minimumWidth);
                return pref;
            }
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java BasicOptionPaneUI.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.