/** * Distribution License: * BibleDesktop is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License, version 2 or later * as published by the Free Software Foundation. This program 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 for more details. * * The License is available on the internet at: * http://www.gnu.org/copyleft/gpl.html * or by writing to: * Free Software Foundation, Inc. * 59 Temple Place - Suite 330 * Boston, MA 02111-1307, USA * * © CrossWire Bible Society, 2008 - 2016 */ package org.crosswire.common.swing; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dialog; import java.awt.Frame; import java.awt.HeadlessException; import java.awt.Window; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.Action; import javax.swing.Icon; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JRootPane; import javax.swing.UIManager; import org.crosswire.bibledesktop.BDMsg; /** * CWOptionPane is just like JOptionPane, but internationalize the button text * for some languages that Java does not handle, for which JSword has * translations. * * @see gnu.gpl.License The GNU General Public License for details. * @author DM Smith */ public class CWOptionPane extends JOptionPane { /** * Creates a CWOptionPane with a test message. */ public CWOptionPane() { this("CWOptionPane message", PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); } /** * Creates a instance of CWOptionPane to display a message * using the plain-message message type and the default options delivered by * the UI. * * @param message * the Object to display */ public CWOptionPane(Object message) { this(message, PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); } /** * Creates an instance of CWOptionPane to display a message * with the specified message type and the default options, * * @param message * the Object to display * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE */ public CWOptionPane(Object message, int messageType) { this(message, messageType, DEFAULT_OPTION, null, null, null); } /** * Creates an instance of CWOptionPane to display a message * with the specified message type and options. * * @param message * the Object to display * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param optionType * the options to display in the pane: * DEFAULT_OPTION, YES_NO_OPTION, * YES_NO_CANCEL_OPTION, * OK_CANCEL_OPTION */ public CWOptionPane(Object message, int messageType, int optionType) { this(message, messageType, optionType, null, null, null); } /** * Creates an instance of CWOptionPane to display a message * with the specified message type, options, and icon. * * @param message * the Object to display * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param optionType * the options to display in the pane: * DEFAULT_OPTION, YES_NO_OPTION, * YES_NO_CANCEL_OPTION, * OK_CANCEL_OPTION * @param icon * the Icon image to display */ public CWOptionPane(Object message, int messageType, int optionType, Icon icon) { this(message, messageType, optionType, icon, null, null); } /** * Creates an instance of CWOptionPane to display a message * with the specified message type, icon, and options. None of the options * is initially selected. *

* The options objects should contain either instances of * Components, (which are added directly) or * Strings (which are wrapped in a JButton). If * you provide Components, you must ensure that when the * Component is clicked it messages setValue in * the created CWOptionPane. * * @param message * the Object to display * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param optionType * the options to display in the pane: * DEFAULT_OPTION, YES_NO_OPTION, * YES_NO_CANCEL_OPTION, * OK_CANCEL_OPTION * @param icon * the Icon image to display * @param options * the choices the user can select */ public CWOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options) { this(message, messageType, optionType, icon, options, null); GuiUtil.applyDefaultOrientation(this); } /** * Creates an instance of CWOptionPane to display a message * with the specified message type, icon, and options, with the * initially-selected option specified. * * @param message * the Object to display * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param optionType * the options to display in the pane: * DEFAULT_OPTION, YES_NO_OPTION, * YES_NO_CANCEL_OPTION, * OK_CANCEL_OPTION * @param icon * the Icon image to display * @param options * the choices the user can select * @param initialValue * the choice that is initially selected; if null, * then nothing will be initially selected; only meaningful if * options is used */ public CWOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options, Object initialValue) { super(message, messageType, optionType, icon, CWOptionPane.fixOptions(options, optionType, messageType), initialValue); } /** * Shows a question-message dialog requesting input from the user. The * dialog uses the default frame, which usually means it is centered on the * screen. * * @param message * the Object to display * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static String showInputDialog(Object message) throws HeadlessException { return showInputDialog(null, message); } /** * Shows a question-message dialog requesting input from the user, with the * input value initialized to initialSelectionValue. The dialog * uses the default frame, which usually means it is centered on the screen. * * @param message * the Object to display * @param initialSelectionValue * the value used to initialize the input field */ public static String showInputDialog(Object message, Object initialSelectionValue) { return showInputDialog(null, message, initialSelectionValue); } /** * Shows a question-message dialog requesting input from the user parented * to parentComponent. The dialog is displayed on top of the * Component's frame, and is usually positioned below the * Component. * * @param parentComponent * the parent Component for the dialog * @param message * the Object to display * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static String showInputDialog(Component parentComponent, Object message) throws HeadlessException { return showInputDialog(parentComponent, message, "?", QUESTION_MESSAGE); } /** * Shows a question-message dialog requesting input from the user and * parented to parentComponent. The input value will be * initialized to initialSelectionValue. The dialog is * displayed on top of the Component's frame, and is usually * positioned below the Component. * * @param parentComponent * the parent Component for the dialog * @param message * the Object to display * @param initialSelectionValue * the value used to initialize the input field */ public static String showInputDialog(Component parentComponent, Object message, Object initialSelectionValue) { return (String) showInputDialog(parentComponent, message, "?", QUESTION_MESSAGE, null, null, initialSelectionValue); } /** * Shows a dialog requesting input from the user parented to * parentComponent with the dialog having the title * title and message type messageType. * * @param parentComponent * the parent Component for the dialog * @param message * the Object to display * @param title * the String to display in the dialog title bar * @param messageType * the type of message that is to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static String showInputDialog(Component parentComponent, Object message, String title, int messageType) throws HeadlessException { return (String) showInputDialog(parentComponent, message, title, messageType, null, null, null); } /** * Prompts the user for input in a blocking dialog where the initial * selection, possible selections, and all other options can be specified. * The user will able to choose from selectionValues, where * null implies the user can input whatever they wish, usually * by means of a JTextField. initialSelectionValue * is the initial value to prompt the user with. It is up to the UI to * decide how best to represent the selectionValues, but * usually a JComboBox, JList, or * JTextField will be used. * * @param parentComponent * the parent Component for the dialog * @param message * the Object to display * @param title * the String to display in the dialog title bar * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param icon * the Icon image to display * @param selectionValues * an array of Objects that gives the possible * selections * @param initialSelectionValue * the value used to initialize the input field * @return user's input, or null meaning the user canceled the * input * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) throws HeadlessException { CWOptionPane pane = new CWOptionPane(message, messageType, OK_CANCEL_OPTION, icon, null, null); pane.setWantsInput(true); pane.setSelectionValues(selectionValues); pane.setInitialSelectionValue(initialSelectionValue); GuiUtil.applyDefaultOrientation(pane); int style = styleFromMessageType(messageType); JDialog dialog = pane.createDialog(parentComponent, title, style); pane.selectInitialValue(); dialog.setVisible(true); dialog.dispose(); Object value = pane.getInputValue(); if (value == UNINITIALIZED_VALUE) { return null; } return value; } /** * Brings up an information-message dialog titled "Message". * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException { showOptionDialog(parentComponent, message, "?", DEFAULT_OPTION, INFORMATION_MESSAGE, null, null, null); } /** * Brings up a dialog that displays a message using a default icon * determined by the messageType parameter. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @param title * the title string for the dialog * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) throws HeadlessException { showOptionDialog(parentComponent, message, title, DEFAULT_OPTION, messageType, null, null, null); } /** * Brings up a dialog displaying a message, specifying all parameters. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @param title * the title string for the dialog * @param messageType * the type of message to be displayed: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param icon * an icon to display in the dialog that helps the user identify * the kind of message that is being displayed * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) throws HeadlessException { showOptionDialog(parentComponent, message, title, DEFAULT_OPTION, messageType, icon, null, null); } /** * Brings up a dialog with the options Yes, No and * Cancel; with the title, Select an Option. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @return an integer indicating the option selected by the user * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static int showConfirmDialog(Component parentComponent, Object message) throws HeadlessException { return showOptionDialog(parentComponent, message, "?", YES_NO_CANCEL_OPTION, QUESTION_MESSAGE, null, null, null); } /** * Brings up a dialog where the number of choices is determined by the * optionType parameter. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @param title * the title string for the dialog * @param optionType * an int designating the options available on the dialog: * YES_NO_OPTION, or * YES_NO_CANCEL_OPTION * @return an int indicating the option selected by the user * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) throws HeadlessException { return showOptionDialog(parentComponent, message, title, optionType, QUESTION_MESSAGE, null, null, null); } /** * Brings up a dialog where the number of choices is determined by the * optionType parameter, where the messageType * parameter determines the icon to display. The messageType * parameter is primarily used to supply a default icon from the Look and * Feel. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used. * @param message * the Object to display * @param title * the title string for the dialog * @param optionType * an integer designating the options available on the dialog: * YES_NO_OPTION, or * YES_NO_CANCEL_OPTION * @param messageType * an integer designating the kind of message this is; primarily * used to determine the icon from the pluggable Look and Feel: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @return an integer indicating the option selected by the user * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) throws HeadlessException { return showOptionDialog(parentComponent, message, title, optionType, messageType, null, null, null); } /** * Brings up a dialog with a specified icon, where the number of choices is * determined by the optionType parameter. The * messageType parameter is primarily used to supply a default * icon from the look and feel. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @param title * the title string for the dialog * @param optionType * an int designating the options available on the dialog: * YES_NO_OPTION, or * YES_NO_CANCEL_OPTION * @param messageType * an int designating the kind of message this is, primarily used * to determine the icon from the pluggable Look and Feel: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param icon * the icon to display in the dialog * @return an int indicating the option selected by the user * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon) throws HeadlessException { return showOptionDialog(parentComponent, message, title, optionType, messageType, icon, null, null); } /** * Brings up a dialog with a specified icon, where the initial choice is * determined by the initialValue parameter and the number of * choices is determined by the optionType parameter. *

* If optionType is YES_NO_OPTION, or * YES_NO_CANCEL_OPTION and the options parameter * is null, then the options are supplied by the look and feel. *

* The messageType parameter is primarily used to supply a * default icon from the look and feel. * * @param parentComponent * determines the Frame in which the dialog is * displayed; if null, or if the * parentComponent has no Frame, a * default Frame is used * @param message * the Object to display * @param title * the title string for the dialog * @param optionType * an integer designating the options available on the dialog: * YES_NO_OPTION, or * YES_NO_CANCEL_OPTION * @param messageType * an integer designating the kind of message this is, primarily * used to determine the icon from the pluggable Look and Feel: * ERROR_MESSAGE, INFORMATION_MESSAGE, * WARNING_MESSAGE, QUESTION_MESSAGE, * or PLAIN_MESSAGE * @param icon * the icon to display in the dialog * @param options * an array of objects indicating the possible choices the user * can make; if the objects are components, they are rendered * properly; non-String objects are rendered using * their toString methods; if this parameter is * null, the options are determined by the Look and * Feel * @param initialValue * the object that represents the default selection for the * dialog; only meaningful if options is used; can * be null * @return an integer indicating the option chosen by the user, or * CLOSED_OPTION if the user closed the dialog * @exception HeadlessException * if GraphicsEnvironment.isHeadless returns * true * @see java.awt.GraphicsEnvironment#isHeadless */ public static int showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) throws HeadlessException { CWOptionPane pane = new CWOptionPane(message, messageType, optionType, icon, options, initialValue); pane.setInitialValue(initialValue); GuiUtil.applyDefaultOrientation(pane); int style = styleFromMessageType(messageType); JDialog dialog = pane.createDialog(parentComponent, title, style); pane.selectInitialValue(); dialog.setVisible(true); dialog.dispose(); Object selectedValue = pane.getValue(); if (selectedValue == null) { return CLOSED_OPTION; } Object[] opts = pane.getOptions(); if (opts == null) { if (selectedValue instanceof Integer) { return ((Integer) selectedValue).intValue(); } return CLOSED_OPTION; } if (getActionName("Yes").equals(selectedValue)) { return YES_OPTION; } if (getActionName("No").equals(selectedValue)) { return NO_OPTION; } if (getActionName("OK").equals(selectedValue)) { return OK_OPTION; } if (getActionName("Cancel").equals(selectedValue)) { return CANCEL_OPTION; } int maxCounter = opts.length; for (int counter = 0; counter < maxCounter; counter++) { if (opts[counter].equals(selectedValue)) { return counter; } } return CLOSED_OPTION; } private JDialog createDialog(Component parentComponent, String title, int style) throws HeadlessException { final JDialog dialog; Window window = GuiUtil.getWindow(parentComponent); if (window instanceof Frame) { dialog = new JDialog((Frame) window, title, true); } else { dialog = new JDialog((Dialog) window, title, true); } Container contentPane = dialog.getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(this, BorderLayout.CENTER); dialog.setResizable(false); if (JDialog.isDefaultLookAndFeelDecorated()) { boolean supportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations(); if (supportsWindowDecorations) { dialog.setUndecorated(true); getRootPane().setWindowDecorationStyle(style); } } dialog.pack(); dialog.setLocationRelativeTo(parentComponent); dialog.addWindowListener(new WindowAdapter() { private boolean gotFocus; @Override public void windowClosing(WindowEvent we) { setValue(null); } @Override public void windowGainedFocus(WindowEvent we) { // Once window gets focus, set initial focus if (!gotFocus) { selectInitialValue(); gotFocus = true; } } }); dialog.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent ce) { // reset value to ensure closing works properly setValue(JOptionPane.UNINITIALIZED_VALUE); } }); addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { // Let the defaultCloseOperation handle the closing // if the user closed the window without selecting a button // (newValue = null in that case). Otherwise, close the dialog. if (dialog.isVisible() && event.getSource() == CWOptionPane.this && event.getPropertyName().equals(VALUE_PROPERTY) && event.getNewValue() != null && event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) { dialog.setVisible(false); } } }); GuiUtil.applyDefaultOrientation(dialog); return dialog; } private static int styleFromMessageType(int messageType) { switch (messageType) { case ERROR_MESSAGE: return JRootPane.ERROR_DIALOG; case QUESTION_MESSAGE: return JRootPane.QUESTION_DIALOG; case WARNING_MESSAGE: return JRootPane.WARNING_DIALOG; case INFORMATION_MESSAGE: return JRootPane.INFORMATION_DIALOG; case PLAIN_MESSAGE: default: return JRootPane.PLAIN_DIALOG; } } private static String getActionName(String key) { return actions.findAction(key).getValue(Action.NAME).toString(); } private static Object[] fixOptions(Object[] options, int optionType, int messageType) { Object[] opts = options; if (options == null) { if (optionType == YES_NO_OPTION) { opts = new Object[] { getActionName("Yes"), getActionName("No") }; } else if (optionType == OK_CANCEL_OPTION) { opts = new Object[] { getActionName("OK"), getActionName("Cancel") }; } else if (optionType == YES_NO_CANCEL_OPTION && messageType != INFORMATION_MESSAGE) { opts = new Object[] { getActionName("Yes"), getActionName("No"), getActionName("Cancel") }; } else { opts = new Object[] { getActionName("OK"), }; } } return opts; } /** * The actions for this dialog. */ private static ActionFactory actions = new ActionFactory(null); static { // TRANSLATOR: This is the text on a "Yes" button. actions.addAction("Yes", BDMsg.gettext("Yes")); // TRANSLATOR: This is the text on a "No" button. actions.addAction("No", BDMsg.gettext("No")); // TRANSLATOR: This is the text on an "OK" button. actions.addAction("OK", BDMsg.gettext("OK")); // TRANSLATOR: This is the text on a "Cancel" button. actions.addAction("Cancel", BDMsg.gettext("Cancel")); } /** * Serialization ID */ private static final long serialVersionUID = -1870422750863765033L; }