package com.onaro.util.jfc; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.UIManager; import org.apache.commons.lang3.StringUtils; import com.onaro.sanscreen.client.MainDirector; /** * An extension of {@link JOptionPane} allowing access to the buttons and reusing the resources of * the {@link JDialog} that is used by the option-pane.

* This class provides access to the {@link JButton} used by the option pane (that are otherwise * inacssible) through the {@link OptionPane#getOptionButtonByValue(int)} method. In addition, it is * possible to setup a {@link OptionPane.OptionPaneButtonFilter} that is consulted whenever a button * is pressed and allwos to veto the action.

* Usage:

    *
  1. Use a single instance for each type of window. *
  2. To show the window, first call to {@link OptionPane#prepare(java.awt.Component, java.awt.Component)} * which, initializes the option-pane and the buttons. *
  3. Next, call to {@link OptionPane#show()}, this way, you may access the buttons after they were initilized * and before the window is displayed. *
  4. Optionally, you can use {@link OptionPane#show(java.awt.Component, java.awt.Component)} instead * of the previous two methods. *
  5. Use {@link OptionPane#getSelectedOption()} to find out the option that the user had selected. *
* Note: The {@link JOptionPane} is used because it deals with the texts of the buttons as well as * the layout of the window. */ public class OptionPane implements PropertyChangeListener{ /** * Window title. */ private String title; /** * The option pane itself, is created once and only its message is being changed. * * @see JOptionPane#setMessage(Object) */ private JOptionPane optionPane; /** * The window displaying the option-pane, is created once, and is displayed and hide when needed. */ private JDialog dialog; /** * The type of options that the user may choose from. * * @see JOptionPane#optionType */ private int options; /** * Map to keep track of Option buttons by JOptionPane constant values */ private Map optionButtonsByValueMap; /** * The icon to display in the option pane (defaults to null) */ private Icon icon; /** * Optionally, allow to override user selection of option buttons. */ private OptionPaneButtonFilter buttonFilter; private int messageType = JOptionPane.PLAIN_MESSAGE; /** * Initilizes a simple option pane. * * @param title window title * @param options the type of options that the user may choose from * @see JOptionPane#optionType */ public OptionPane(String title, int options) { this.title = title; this.options = options; } /** * Initilizes an option pane. * * @param title window title * @param options the type of options that the user may choose from * @param messageType tells if its a plain, warning, error, question dialog * @see JOptionPane#optionType * @see JOptionPane#messageType */ public OptionPane(String title, int options, int messageType) { this.title = title; this.options = options; this.messageType = messageType; } /** * Initilizes an option pane using a filter that can override user selection of option buttons. * * @param title window title * @param options the type of options that the user may choose from * @param buttonFilter a filter that is consulted whenever a user presses a button to determine * if the selection will be accepted or not * @see JOptionPane#optionType */ public OptionPane(String title, int options, OptionPaneButtonFilter buttonFilter) { this.title = title; this.options = options; this.buttonFilter = buttonFilter; } /** * Set the icon shown in the option pane dialog * @param icon icon to show */ public void setIcon(Icon icon) { this.icon = icon; } /** * Prepare for displaying the window. On the first time, creates the dialog and option-pane. * * @param parent the parent window is used by the modal behavior of the option-pane * @param component the message to display in the window */ public void prepare(Component parent, Component component) { prepare(parent,component,true); } /** * Prepare for displaying the window. On the first time, creates the dialog and option-pane. * * @param parent the parent window is used by the modal behavior of the option-pane * @param component the message to display in the window * @param resizable determine if the dialog will be resizable or not */ public void prepare(Component parent, Component component,boolean resizable) { if (optionPane == null) { optionPane = new JOptionPane(component, messageType, options, icon, null, null); setOptionPaneButtons(optionPane, options); dialog = optionPane.createDialog(parent, title); dialog.setResizable(resizable); } else { optionPane.setMessage(component); } String name = component != null ? component.getName() + "." : StringUtils.EMPTY; //$NON-NLS-1$ optionPane.setName(name + "OptionPane"); //$NON-NLS-1$ dialog.setName(name + "OptionPane.dialog"); //$NON-NLS-1$ } /** * Get the size of the Option dialog * @return the size of the dialog as a {@link Dimension} */ public Dimension getSize() { return dialog.getSize(); } /** * Set the size of the Option Dialog * @param size for the dialog as a {@link Dimension} */ public void setSize (Dimension size) { dialog.setSize (size); } /** * Prepare for displaying the window and shows it. * * @param parent the parent window is used by the modal behavior of the option-pane * @param component the message to display in the window */ public void show(Component parent, Component component) { prepare(parent, component); show(); } /** * Shows the window. */ public void show() { dialog.setVisible(true); optionPane.setMessage(null); } /** * Gets the option that the user selected. * * @return the option that the user selected is the constant value of the button * from the JOptionPane class, e.g. JOptionPane.OK_OPTION * @see JOptionPane#optionType */ public int getSelectedOption() { int selectedOption = JOptionPane.CLOSED_OPTION; Object selectedValue = optionPane.getValue(); if (selectedValue != null && selectedValue instanceof Integer) { selectedOption = ((Integer) selectedValue).intValue(); } return selectedOption; } /** * Get the button with the given value constant. * * @param value the JOptionPane constant of the button, e.g. JOptionPane.OK_OPTION * @return the button */ public JButton getOptionButtonByValue(int value) { return optionButtonsByValueMap.get(value); } /** * Get the button at the requested index. * * @param index the index of the button * @return the button */ public JButton getOptionButtonByIndex(int index) { return (JButton) optionPane.getOptions()[index]; } public interface OptionPaneButtonFilter { /** * Whenever a button is pressed, this method is consulted, letting the filter veto * the selection. * * @param buttonIndex the index of the pressed button * @param optionPane the option-pane itself * @return true if the selection is accepted */ public boolean canSelectButton(int buttonIndex, JOptionPane optionPane); } private void setOptionPaneButtons(JOptionPane optionPane, int optionType) { optionPane.setOptionType(optionType); if (optionButtonsByValueMap == null) { optionButtonsByValueMap = new HashMap(); } else { optionButtonsByValueMap.clear(); } JButton buttons[] = null; Object[] buttonFactory = getButtons(); if (buttonFactory != null) { buttons = new JButton[buttonFactory.length]; for (int i = 0; i < buttonFactory.length; i++) { ButtonFactory factory = (ButtonFactory)buttonFactory[i]; buttons[i] = factory.createButton(); buttons[i].addActionListener(new OptionButtonListener(factory.getValue(), optionPane, buttonFilter)); optionButtonsByValueMap.put(factory.getValue(), buttons[i]); } } if (buttons != null) { optionPane.setOptions(buttons); optionPane.setInitialValue(buttons[0]); } } private static class ButtonFactory { private String text; private int mnemonic; private Icon icon; private int value; ButtonFactory(String text, int mnemonic, Icon icon, int value) { this.text = text; this.mnemonic = mnemonic; this.icon = icon; this.value = value; } JButton createButton() { JButton button = new JButton(text); button.setName(text); if (icon != null) { button.setIcon(icon); } if (mnemonic != 0) { button.setMnemonic(mnemonic); } return button; } public int getValue() { return value; } } 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; } protected Object[] getButtons() { if (optionPane != null) { Object[] suppliedOptions = optionPane.getOptions(); if (suppliedOptions == null) { Object[] defaultOptions; int type = optionPane.getOptionType(); Locale l = optionPane.getLocale(); if (type == JOptionPane.YES_NO_OPTION) { defaultOptions = new ButtonFactory[2]; defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.yesButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.yesButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.yesIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.YES_OPTION); defaultOptions[1] = new ButtonFactory(UIManager.getString("OptionPane.noButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.noButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.noIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.NO_OPTION); } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) { defaultOptions = new ButtonFactory[3]; defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.yesButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.yesButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.yesIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.YES_OPTION); defaultOptions[1] = new ButtonFactory(UIManager.getString("OptionPane.noButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.noButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.noIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.NO_OPTION); defaultOptions[2] = new ButtonFactory(UIManager.getString("OptionPane.cancelButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.cancelButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.cancelIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.CANCEL_OPTION); } else if (type == JOptionPane.OK_CANCEL_OPTION) { defaultOptions = new ButtonFactory[2]; defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.okButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.okButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.okIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.OK_OPTION); defaultOptions[1] = new ButtonFactory(UIManager.getString("OptionPane.cancelButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.cancelButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.cancelIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.CANCEL_OPTION); } else { defaultOptions = new ButtonFactory[1]; defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.okButtonText", l), //$NON-NLS-1$ getMnemonic("OptionPane.okButtonMnemonic", l), //$NON-NLS-1$ UIManager.getIcon("OptionPane.okIcon",optionPane.getLocale()), //$NON-NLS-1$ JOptionPane.OK_OPTION); } return defaultOptions; } return suppliedOptions; } return null; } private static class OptionButtonListener implements ActionListener { int buttonValue; JOptionPane optionPane; OptionPane.OptionPaneButtonFilter buttonFilter; public OptionButtonListener(int buttonValue, JOptionPane optionPane, OptionPane.OptionPaneButtonFilter buttonFilter) { this.buttonValue = buttonValue; this.optionPane = optionPane; this.buttonFilter = buttonFilter; } public void actionPerformed(ActionEvent e) { if (buttonFilter == null || buttonFilter.canSelectButton(buttonValue, optionPane)) { optionPane.setValue(Integer.valueOf(buttonValue)); } } } /** * Shows a panel in a "OK" "Cancel" dialog. * * @param parent the component that invoked the dialog. the dialog will be positioned relatively to the parent. *

may be null * @param component the component to display in the dialog * @param title optional title for the dialog * @return true if the OK was pressed. false otherwise */ public static boolean showDialog(Component parent, JComponent component, String title) { return showDialog(parent, component, title, null); } public static boolean showDialog(Component parent, JComponent component, String title, boolean resizable) { return showDialog(parent, component, title, null, resizable); } public static boolean showDialog(Component parent, JComponent component, String title, OptionPaneButtonEnabler enabler) { return showDialog(parent, component, title, enabler, false); } public static boolean showDialog(Component parent, JComponent component, String title, OptionPaneButtonEnabler enabler, boolean resizable) { if(parent == null) parent = MainDirector.getFrameDirector().getAppFrame(); OptionPane pane = new OptionPane(title,JOptionPane.OK_CANCEL_OPTION); pane.prepare(parent, component, resizable); //this will link between the button and the field. if(enabler != null){ enabler.setButton(pane.getOptionButtonByValue(JOptionPane.OK_OPTION)); } pane.show(); return pane.getSelectedOption() == JOptionPane.OK_OPTION; } public void propertyChange(PropertyChangeEvent evt) { dialog.setVisible(false); } }