All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.globalmentor.swing.BasicOptionPane Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 1996-2009 GlobalMentor, Inc. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.globalmentor.swing;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;

import com.globalmentor.awt.*;
import com.globalmentor.model.Verifiable;
import com.globalmentor.util.*;

/**
 * An option pane that knows how to verify its contents before closing the dialog.
 * 

* This class offers several improvements over {@link JOptionPane}: *

*
    *
  • If the message object implements {@link DefaultFocusable}, the initial focus component is given the focus when the pane is displayed.
  • *
  • If the message object implements {@link Verifiable}, the input is verified before the pane is allowed to close.
  • *
  • If {@link #setValue(Object)} is called with an explicit {@link Integer} value, that value will be returned even if options are present.
  • *
* @author Garret Wilson * @see BasicDialog * @see DefaultFocusable * @see Verifiable */ public class BasicOptionPane extends JOptionPane { /** * Creates a BasicOptionPane with a test message. */ public BasicOptionPane() { super(); } /** * Creates a instance of BasicOptionPane 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 BasicOptionPane(Object message) { super(message); } /** * Creates an instance of BasicOptionPane 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 BasicOptionPane(Object message, int messageType) { super(message, messageType); } /** * Creates an instance of BasicOptionPane 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 BasicOptionPane(Object message, int messageType, int optionType) { super(message, messageType, optionType); } /** * Creates an instance of BasicOptionPane 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 BasicOptionPane(Object message, int messageType, int optionType, Icon icon) { super(message, messageType, optionType, icon); } /** * Creates an instance of BasicOptionPane 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 BasicOptionPane. * * @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; only meaningful if the * options parameter is null * @param icon the Icon image to display * @param options the choices the user can select */ public BasicOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options) { super(message, messageType, optionType, icon, options); } /** * Creates an instance of BasicOptionPane 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; only meaningful if the * options parameter is null * @param icon the Icon image to display * @param options the choices the user can select * @param initialValue the choice that is initially selected */ public BasicOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options, Object initialValue) { super(message, messageType, optionType, icon, options, initialValue); } //TODO add other methods here /** * 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 * @throws HeadlessException if GraphicsEnvironment.isHeadless returns true * @see java.awt.GraphicsEnvironment#isHeadless */ public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException { //TODO fix UIManager.getString("OptionPane.messageDialogTitle", parentComponent) showMessageDialog(parentComponent, message, "Message", INFORMATION_MESSAGE); } /** * 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 * @throws 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 { showMessageDialog(parentComponent, message, title, messageType, 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 * @throws 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 modal 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 */ public static int showConfirmDialog(Component parentComponent, Object message) { return showConfirmDialog(parentComponent, message, UIManager.getString("OptionPane.titleText"), YES_NO_CANCEL_OPTION); } /** * Brings up a modal 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 */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) { //TODO del Log.trace("show confirm dialog 1"); //TODO del return showConfirmDialog(parentComponent, message, title, optionType, QUESTION_MESSAGE); } /** * Brings up a modal 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 */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) { //TODO del Log.trace("show confirm dialog 2"); //TODO del return showConfirmDialog(parentComponent, message, title, optionType, messageType, null); } /** * Brings up a modal 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 */ public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon) { //TODO del Log.trace("show confirm dialog 3"); //TODO del return showOptionDialog(parentComponent, message, title, optionType, messageType, icon, null, null); } /** * Brings up a modal dialog with a specified icon, where the initial choice is dermined 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 * @return an integer indicating the option chosen by the user, or CLOSED_OPTION if the user closed the Dialog */ /*TODO del when new JDK1.4 version works public static int showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) { //TODO del Log.trace("inside custom showOptionDialog()"); //TODO del JOptionPane pane = new OptionPane(message, messageType, optionType, icon, options, initialValue); pane.setInitialValue(initialValue); JDialog dialog = pane.createDialog(parentComponent, title); pane.selectInitialValue(); dialog.show(); Object selectedValue = pane.getValue(); if(selectedValue == null) return CLOSED_OPTION; if(options == null) { if(selectedValue instanceof Integer) return ((Integer)selectedValue).intValue(); return CLOSED_OPTION; } for(int counter = 0, maxCounter = options.length; counter < maxCounter; counter++) { if(options[counter].equals(selectedValue)) return counter; } return CLOSED_OPTION; } */ /** * 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 * @throws 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 { JOptionPane pane = new BasicOptionPane(message, messageType, optionType, icon, options, initialValue); pane.setInitialValue(initialValue); pane.setComponentOrientation(((parentComponent == null) ? getRootFrame() : parentComponent).getComponentOrientation()); JDialog dialog = pane.createDialog(parentComponent, title); pane.selectInitialValue(); dialog.show(); dialog.dispose(); Object selectedValue = pane.getValue(); if(selectedValue == null) return CLOSED_OPTION; if(options != null) { for(int counter = 0, maxCounter = options.length; counter < maxCounter; counter++) { if(options[counter].equals(selectedValue)) return counter; } } if(selectedValue instanceof Integer) //if the selected value is an integer, always return it, even if there are options present (newswing) return ((Integer)selectedValue).intValue(); return CLOSED_OPTION; } /** * Creates and returns a new JDialog wrapping this centered on the parentComponent in the parentComponent * 's frame. title is the title of the returned dialog. The returned JDialog will be set up such that once it is closed, or the user * clicks on the OK button, the dialog will be disposed and closed. *

* This version first verifies the content pane, if it is Verifiable, and only closes the dialog if the object verifies correctly or is not * Verifiable. *

* @param parentComponent determines the frame in which the dialog is displayed; if the parentComponent has no Frame, a default * Frame is used * @param title the title string for the dialog * @return a new JDialog containing this instance */ public JDialog createDialog(Component parentComponent, String title) { //TODO del final JDialog dialog=super.createDialog(parentComponent, title); //create the default dialog final JDialog dialog; Window window = getWindowForComponent(parentComponent); if(window instanceof Frame) { dialog = new BasicDialog((Frame)window, title, true); } else { dialog = new BasicDialog((Dialog)window, title, true); } final Container contentPane = dialog.getContentPane(); //see if the message is verifiable final Verifiable verifiableMessage = message instanceof Verifiable ? (Verifiable)message : null; //TODO newswing contentPane.setLayout(new BorderLayout()); contentPane.add(this, BorderLayout.CENTER); dialog.pack(); dialog.setLocationRelativeTo(parentComponent); dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); //don't automatically close the dialog TODO newswing dialog.addWindowListener(new WindowAdapter() { boolean gotFocus = false; public void windowClosing(WindowEvent we) { setValue(null); } public void windowActivated(WindowEvent we) { // Once window gets focus, set initial focus if(!gotFocus) { selectInitialValue(); gotFocus = true; } } }); addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if(dialog.isVisible() && event.getSource() == BasicOptionPane.this && (event.getPropertyName().equals(VALUE_PROPERTY) || event.getPropertyName().equals(INPUT_VALUE_PROPERTY))) { //if the user is pressing "OK", try to verify the message if(event.getNewValue() instanceof Integer && ((Integer)event.getNewValue()).intValue() == OK_OPTION) { //if the user is pressing "OK" //TODO del if(OptionPane.this.getValue().equals(new ) if(verifiableMessage != null) { //if the message is verifiable TODO newswing if(!verifiableMessage.verify()) { //verify the content pane; if it doesn't verify value = null; //change the value back to nothing so that pressing the button again will bring us back here (but don't call setValue(null), because that will close the dialog) return; //cancel the closing process } } } dialog.setVisible(false); dialog.dispose(); } } }); return dialog; } /** * Requests that the initial value be selected, which will set focus to the initial value. *

* This version first checks to see if the message implements DefaultFocusable, and if so the message is asked which component should get the * focus. Otherwise, the default initial value is selected. *

* @see #getMessage * @see DefaultFocusable */ public void selectInitialValue() { final Object message = getMessage(); //get the message object used in the pane /*TODO fix; this might be useful in the future if(message instanceof Container) { final FocusTraversalPolicy focusTraversalPolicy=((Container)message).getFocusTraversalPolicy(); if(focusTraversalPolicy!=null) { final Component defaultComponent=focusTraversalPolicy.getDefaultComponent((Container)message); if(defaultComponent!=null) defaultComponent.requestFocusInWindow(); //TODO testing } //TODO fix else //TODO fix super.selectInitialValue(); //do the default initial value selection } */ //if the message object knows how to request the default focus, let it do so if it can; if it can't if(!(message instanceof DefaultFocusable) || !((DefaultFocusable)message).requestDefaultFocusComponentFocus()) { super.selectInitialValue(); //do the default initial value selection } /*TODO del when works //if the message object knows which component should get the default focus if(message instanceof DefaultFocusable && ((DefaultFocusable)message).getDefaultFocusComponent()!=null) ((DefaultFocusable)message).getDefaultFocusComponent().requestFocusInWindow(); //request focus for the default component else //if the message object doesn't know what to focus super.selectInitialValue(); //do the default initial value selection */ } /** * Returns the specified component's toplevel Frame or Dialog. * * @param parentComponent the Component to check for a Frame or Dialog * @return the Frame or Dialog that contains the component, or the default frame if the component is null, or does not * have a valid Frame or Dialog parent */ static Window getWindowForComponent(Component parentComponent) { if(parentComponent == null) return getRootFrame(); if(parentComponent instanceof Frame || parentComponent instanceof Dialog) return (Window)parentComponent; return getWindowForComponent(parentComponent.getParent()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy