001/* JOptionPane.java
002   Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.swing;
040
041import java.awt.AWTEvent;
042import java.awt.ActiveEvent;
043import java.awt.Component;
044import java.awt.Container;
045import java.awt.EventQueue;
046import java.awt.Frame;
047import java.awt.MenuComponent;
048import java.awt.Toolkit;
049import java.awt.event.MouseAdapter;
050import java.awt.event.MouseMotionAdapter;
051import java.beans.PropertyChangeEvent;
052import java.beans.PropertyChangeListener;
053
054import javax.accessibility.Accessible;
055import javax.accessibility.AccessibleContext;
056import javax.accessibility.AccessibleRole;
057import javax.swing.plaf.OptionPaneUI;
058
059/**
060 * This class creates different types of JDialogs and JInternalFrames that can
061 * ask users for input or pass on information. JOptionPane can be used by
062 * calling one of the show static methods or  by creating an instance of
063 * JOptionPane and calling createDialog or createInternalFrame.
064 */
065public class JOptionPane extends JComponent implements Accessible
066{
067  /**
068   * Provides the accessibility features for the <code>JOptionPane</code>
069   * component.
070   */
071  protected class AccessibleJOptionPane extends JComponent.AccessibleJComponent
072  {
073    private static final long serialVersionUID = 686071432213084821L;
074
075    /**
076     * Creates a new <code>AccessibleJOptionPane</code> instance.
077     */
078    protected AccessibleJOptionPane()
079    {
080      // Nothing to do here.
081    }
082
083    /**
084     * Returns the accessible role of this object, which is always
085     * {@link AccessibleRole#OPTION_PANE}.
086     *
087     * @return the accessible role of this object
088     */
089    public AccessibleRole getAccessibleRole()
090    {
091      return AccessibleRole.OPTION_PANE;
092    }
093  }
094
095  private static final long serialVersionUID = 5231143276678566796L;
096
097  /** The value returned when cancel option is selected. */
098  public static final int CANCEL_OPTION = 2;
099
100  /** The value returned when the dialog is closed without a selection. */
101  public static final int CLOSED_OPTION = -1;
102
103  /** An option used in confirmation dialog methods. */
104  public static final int DEFAULT_OPTION = -1;
105
106  /** The value returned when the no option is selected. */
107  public static final int NO_OPTION = 1;
108
109  /** An option used in confirmation dialog methods. */
110  public static final int OK_CANCEL_OPTION = 2;
111
112  /** The value returned when the ok option is selected. */
113  public static final int OK_OPTION = 0;
114
115  /** An option used in confirmation dialog methods. */
116  public static final int YES_NO_CANCEL_OPTION = 1;
117
118  /** An option used in confirmation dialog methods. */
119  public static final int YES_NO_OPTION = 0;
120
121  /** The value returned when the yes option is selected. */
122  public static final int YES_OPTION = 0;
123
124  /** Identifier for the error message type. */
125  public static final int ERROR_MESSAGE = 0;
126
127  /** Identifier for the information message type. */
128  public static final int INFORMATION_MESSAGE = 1;
129
130  /** Identifier for the plain message type. */
131  public static final int PLAIN_MESSAGE = -1;
132
133  /** Identifier for the question message type. */
134  public static final int QUESTION_MESSAGE = 3;
135
136  /** Identifier for the warning message type. */
137  public static final int WARNING_MESSAGE = 2;
138
139  /**
140   * The identifier for the propertyChangeEvent when the icon property
141   * changes.
142   */
143  public static final String ICON_PROPERTY = "icon";
144
145  /**
146   * The identifier for the propertyChangeEvent when the initialSelectionValue
147   * property changes.
148   */
149  public static final String INITIAL_SELECTION_VALUE_PROPERTY = "initialSelectionValue";
150
151  /**
152   * The identifier for the propertyChangeEvent when the initialValue property
153   * changes.
154   */
155  public static final String INITIAL_VALUE_PROPERTY = "initialValue";
156
157  /**
158   * The identifier for the propertyChangeEvent when the inputValue property
159   * changes.
160   */
161  public static final String INPUT_VALUE_PROPERTY = "inputValue";
162
163  /**
164   * The identifier for the propertyChangeEvent when the message property
165   * changes.
166   */
167  public static final String MESSAGE_PROPERTY = "message";
168
169  /**
170   * The identifier for the propertyChangeEvent when the messageType property
171   * changes.
172   */
173  public static final String MESSAGE_TYPE_PROPERTY = "messageType";
174
175  /**
176   * The identifier for the propertyChangeEvent when the optionType property
177   * changes.
178   */
179  public static final String OPTION_TYPE_PROPERTY = "optionType";
180
181  /**
182   * The identifier for the propertyChangeEvent when the options property
183   * changes.
184   */
185  public static final String OPTIONS_PROPERTY = "options";
186
187  /**
188   * The identifier for the propertyChangeEvent when the selectionValues
189   * property changes.
190   */
191  public static final String SELECTION_VALUES_PROPERTY = "selectionValues";
192
193  /**
194   * The identifier for the propertyChangeEvent when the value property
195   * changes.
196   */
197  public static final String VALUE_PROPERTY = "value";
198
199  /**
200   * The identifier for the propertyChangeEvent when the wantsInput property
201   * changes.
202   */
203  public static final String WANTS_INPUT_PROPERTY = "wantsInput";
204
205  /** The value returned when the inputValue is uninitialized. */
206  public static final Object UNINITIALIZED_VALUE = "uninitializedValue";
207
208  /** The icon displayed in the dialog/internal frame. */
209  protected Icon icon;
210
211  /** The initial selected value in the input component. */
212  protected Object initialSelectionValue;
213
214  /** The object that is initially selected for options. */
215  protected Object initialValue;
216
217  /** The value the user inputs. */
218  protected Object inputValue = UNINITIALIZED_VALUE;
219
220  /** The message displayed in the dialog/internal frame. */
221  protected Object message;
222
223  /** The type of message displayed. */
224  protected int messageType = PLAIN_MESSAGE;
225
226  /**
227   * The options (usually buttons) aligned at the bottom for the user to
228   * select.
229   */
230  protected Object[] options;
231
232  /** The type of options to display. */
233  protected int optionType = DEFAULT_OPTION;
234
235  /** The input values the user can select. */
236  protected Object[] selectionValues;
237
238  /** The value returned by selecting an option. */
239  protected Object value = UNINITIALIZED_VALUE;
240
241  /** Whether the Dialog/InternalFrame needs input. */
242  protected boolean wantsInput;
243
244  /** The common frame used when no parent is provided. */
245  private static Frame privFrame = (Frame) SwingUtilities.getOwnerFrame(null);
246
247  /**
248   * Creates a new JOptionPane object using a message of "JOptionPane
249   * message", using the PLAIN_MESSAGE type and DEFAULT_OPTION.
250   */
251  public JOptionPane()
252  {
253    this("JOptionPane message", PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null);
254  }
255
256  /**
257   * Creates a new JOptionPane object using the given message using the
258   * PLAIN_MESSAGE type and DEFAULT_OPTION.
259   *
260   * @param message The message to display.
261   */
262  public JOptionPane(Object message)
263  {
264    this(message, PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null);
265  }
266
267  /**
268   * Creates a new JOptionPane object using the given message and messageType
269   * and DEFAULT_OPTION.
270   *
271   * @param message The message to display.
272   * @param messageType The type of message.
273   */
274  public JOptionPane(Object message, int messageType)
275  {
276    this(message, messageType, DEFAULT_OPTION, null, null, null);
277  }
278
279  /**
280   * Creates a new JOptionPane object using the given message, messageType and
281   * optionType.
282   *
283   * @param message The message to display.
284   * @param messageType The type of message.
285   * @param optionType The type of options.
286   */
287  public JOptionPane(Object message, int messageType, int optionType)
288  {
289    this(message, messageType, optionType, null, null, null);
290  }
291
292  /**
293   * Creates a new JOptionPane object using the given message, messageType,
294   * optionType and icon.
295   *
296   * @param message The message to display.
297   * @param messageType The type of message.
298   * @param optionType The type of options.
299   * @param icon The icon to display.
300   */
301  public JOptionPane(Object message, int messageType, int optionType, Icon icon)
302  {
303    this(message, messageType, optionType, icon, null, null);
304  }
305
306  /**
307   * Creates a new JOptionPane object using the given message, messageType,
308   * optionType, icon and options.
309   *
310   * @param message The message to display.
311   * @param messageType The type of message.
312   * @param optionType The type of options.
313   * @param icon The icon to display.
314   * @param options The options given.
315   */
316  public JOptionPane(Object message, int messageType, int optionType,
317                     Icon icon, Object[] options)
318  {
319    this(message, messageType, optionType, icon, options, null);
320  }
321
322  /**
323   * Creates a new JOptionPane object using the given message, messageType,
324   * optionType, icon, options and initialValue. The initialValue will be
325   * focused initially.
326   *
327   * @param message The message to display.
328   * @param messageType The type of message.
329   * @param optionType The type of options.
330   * @param icon The icon to display.
331   * @param options The options given.
332   * @param initialValue The component to focus on initially.
333   *
334   * @throws IllegalArgumentException If the messageType or optionType are not
335   *         legal values.
336   */
337  public JOptionPane(Object message, int messageType, int optionType,
338                     Icon icon, Object[] options, Object initialValue)
339  {
340    this.message = message;
341    if (! validMessageType(messageType))
342      throw new IllegalArgumentException("Message Type not legal value.");
343    this.messageType = messageType;
344    if (! validOptionType(optionType))
345      throw new IllegalArgumentException("Option Type not legal value.");
346    this.optionType = optionType;
347    this.icon = icon;
348    this.options = options;
349    this.initialValue = initialValue;
350
351    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
352
353    updateUI();
354  }
355
356  /**
357   * This method creates a new JDialog that is either centered around the
358   * parent's frame or centered on the screen (if the parent is null). The
359   * JDialog will not be resizable and will be modal. Once the JDialog is
360   * disposed, the inputValue and value properties will  be set by the
361   * optionPane.
362   *
363   * @param parentComponent The parent of the Dialog.
364   * @param title The title in the bar of the JDialog.
365   *
366   * @return A new JDialog based on the JOptionPane configuration.
367   */
368  public JDialog createDialog(Component parentComponent, String title)
369  {
370    Frame toUse = getFrameForComponent(parentComponent);
371    if (toUse == null)
372      toUse = getRootFrame();
373
374    JDialog dialog = new JDialog(toUse, title);
375    inputValue = UNINITIALIZED_VALUE;
376    value = UNINITIALIZED_VALUE;
377
378    dialog.getContentPane().add(this);
379    dialog.setModal(true);
380    dialog.setResizable(false);
381    dialog.pack();
382    dialog.setLocationRelativeTo(parentComponent);
383
384    addPropertyChangeListener(new ValuePropertyHandler(dialog));
385    return dialog;
386  }
387
388  /**
389   * Handles changes of the value property. Whenever this property changes,
390   * the JOptionPane dialog should be closed.
391   */
392  private static class ValuePropertyHandler
393    implements PropertyChangeListener
394  {
395    /**
396     * The dialog to close.
397     */
398    JDialog dialog;
399
400    /**
401     * Creates a new instance.
402     *
403     * @param d the dialog to be closed
404     */
405    ValuePropertyHandler(JDialog d)
406    {
407      dialog = d;
408    }
409
410    /**
411     * Receives notification when any of the properties change.
412     */
413    public void propertyChange(PropertyChangeEvent p)
414    {
415      String prop = p.getPropertyName();
416      Object val = p.getNewValue();
417      if (prop.equals(VALUE_PROPERTY) && val != null
418          && val != UNINITIALIZED_VALUE)
419        {
420          dialog.setVisible(false);
421        }
422    }
423  }
424
425  /**
426   * This method creates a new JInternalFrame that is in the JLayeredPane
427   * which contains the parentComponent given. If no suitable JLayeredPane
428   * can be found from the parentComponent given, a RuntimeException will be
429   * thrown.
430   *
431   * @param parentComponent The parent to find a JDesktopPane from.
432   * @param title The title of the JInternalFrame.
433   *
434   * @return A new JInternalFrame based on the JOptionPane configuration.
435   *
436   * @throws RuntimeException If no suitable JDesktopPane is found.
437   *
438   * @specnote The specification says that the internal frame is placed
439   *           in the nearest <code>JDesktopPane</code> that is found in
440   *           <code>parent</code>'s ancestors. The behaviour of the JDK
441   *           is that it actually looks up the nearest
442   *           <code>JLayeredPane</code> in <code>parent</code>'s ancestors.
443   *           So do we.
444   */
445  public JInternalFrame createInternalFrame(Component parentComponent,
446                                            String title)
447                                     throws RuntimeException
448  {
449    // Try to find a JDesktopPane.
450    JLayeredPane toUse = getDesktopPaneForComponent(parentComponent);
451    // If we don't have a JDesktopPane, we try to find a JLayeredPane.
452    if (toUse == null)
453      toUse = JLayeredPane.getLayeredPaneAbove(parentComponent);
454    // If this still fails, we throw a RuntimeException.
455    if (toUse == null)
456      throw new RuntimeException
457        ("parentComponent does not have a valid parent");
458
459    JInternalFrame frame = new JInternalFrame(title);
460
461    inputValue = UNINITIALIZED_VALUE;
462    value = UNINITIALIZED_VALUE;
463
464    frame.setContentPane(this);
465    frame.setClosable(true);
466
467    toUse.add(frame);
468    frame.setLayer(JLayeredPane.MODAL_LAYER);
469
470    frame.pack();
471    frame.setVisible(true);
472
473    return frame;
474  }
475
476  /**
477   * Returns the object that provides accessibility features for this
478   * <code>JOptionPane</code> component.
479   *
480   * @return The accessible context (an instance of
481   *     {@link AccessibleJOptionPane}).
482   */
483  public AccessibleContext getAccessibleContext()
484  {
485    if (accessibleContext == null)
486      accessibleContext = new AccessibleJOptionPane();
487    return accessibleContext;
488  }
489
490  /**
491   * This method returns the JDesktopPane for the given parentComponent or
492   * null if none can be found.
493   *
494   * @param parentComponent The component to look in.
495   *
496   * @return The JDesktopPane for the given component or null if none can be
497   *         found.
498   */
499  public static JDesktopPane getDesktopPaneForComponent(Component parentComponent)
500  {
501    return (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class,
502                                                            parentComponent);
503  }
504
505  /**
506   * This method returns the Frame for the given parentComponent or null if
507   * none can be found.
508   *
509   * @param parentComponent The component to look in.
510   *
511   * @return The Frame for the given component or null if none can be found.
512   */
513  public static Frame getFrameForComponent(Component parentComponent)
514  {
515    return (Frame) SwingUtilities.getAncestorOfClass(Frame.class,
516                                                     parentComponent);
517  }
518
519  /**
520   * This method returns the icon displayed.
521   *
522   * @return The icon displayed.
523   */
524  public Icon getIcon()
525  {
526    return icon;
527  }
528
529  /**
530   * This method returns the value initially selected from the list of values
531   * the user can input.
532   *
533   * @return The initial selection value.
534   */
535  public Object getInitialSelectionValue()
536  {
537    return initialSelectionValue;
538  }
539
540  /**
541   * This method returns the value that is focused from the list of options.
542   *
543   * @return The initial value from options.
544   */
545  public Object getInitialValue()
546  {
547    return initialValue;
548  }
549
550  /**
551   * This method returns the value that the user input.
552   *
553   * @return The user's input value.
554   */
555  public Object getInputValue()
556  {
557    if (getValue().equals(new Integer(CANCEL_OPTION)))
558      setInputValue(null);
559    return inputValue;
560  }
561
562  /**
563   * This method returns the maximum characters per line. By default, this is
564   * Integer.MAX_VALUE.
565   *
566   * @return The maximum characters per line.
567   */
568  public int getMaxCharactersPerLineCount()
569  {
570    return Integer.MAX_VALUE;
571  }
572
573  /**
574   * This method returns the message displayed.
575   *
576   * @return The message displayed.
577   */
578  public Object getMessage()
579  {
580    return message;
581  }
582
583  /**
584   * This method returns the message type.
585   *
586   * @return The message type.
587   */
588  public int getMessageType()
589  {
590    return messageType;
591  }
592
593  /**
594   * This method returns the options.
595   *
596   * @return The options.
597   */
598  public Object[] getOptions()
599  {
600    return options;
601  }
602
603  /**
604   * This method returns the option type.
605   *
606   * @return The option type.
607   */
608  public int getOptionType()
609  {
610    return optionType;
611  }
612
613  /**
614   * This method returns the Frame used by JOptionPane dialog's that have no
615   * parent.
616   *
617   * @return The Frame used by dialogs that have no parent.
618   */
619  public static Frame getRootFrame()
620  {
621    return privFrame;
622  }
623
624  /**
625   * This method returns the selection values.
626   *
627   * @return The selection values.
628   */
629  public Object[] getSelectionValues()
630  {
631    return selectionValues;
632  }
633
634  /**
635   * This method returns the UI used by the JOptionPane.
636   *
637   * @return The UI used by the JOptionPane.
638   */
639  public OptionPaneUI getUI()
640  {
641    return (OptionPaneUI) ui;
642  }
643
644  /**
645   * This method returns an identifier to determine which UI class will act as
646   * the UI.
647   *
648   * @return The UI identifier.
649   */
650  public String getUIClassID()
651  {
652    return "OptionPaneUI";
653  }
654
655  /**
656   * This method returns the value that the user selected out of options.
657   *
658   * @return The value that the user selected out of options.
659   */
660  public Object getValue()
661  {
662    return value;
663  }
664
665  /**
666   * This method returns whether this JOptionPane wants input.
667   *
668   * @return Whether this JOptionPane wants input.
669   */
670  public boolean getWantsInput()
671  {
672    return wantsInput;
673  }
674
675  /**
676   * This method returns a String that describes this JOptionPane.
677   *
678   * @return A String that describes this JOptionPane.
679   */
680  protected String paramString()
681  {
682    return "JOptionPane";
683  }
684
685  /**
686   * This method requests focus for the initial value.
687   */
688  public void selectInitialValue()
689  {
690    if (ui != null)
691      ((OptionPaneUI) ui).selectInitialValue(this);
692  }
693
694  /**
695   * This method changes the icon property.
696   *
697   * @param newIcon The new icon to use.
698   */
699  public void setIcon(Icon newIcon)
700  {
701    if (icon != newIcon)
702      {
703        Icon old = icon;
704        icon = newIcon;
705        firePropertyChange(ICON_PROPERTY, old, icon);
706      }
707  }
708
709  /**
710   * This method changes the initial selection property.
711   *
712   * @param newValue The new initial selection.
713   */
714  public void setInitialSelectionValue(Object newValue)
715  {
716    if (initialSelectionValue != newValue)
717      {
718        Object old = initialSelectionValue;
719        initialSelectionValue = newValue;
720        firePropertyChange(INITIAL_SELECTION_VALUE_PROPERTY, old,
721                           initialSelectionValue);
722      }
723  }
724
725  /**
726   * This method changes the initial value property.
727   *
728   * @param newValue The new initial value.
729   */
730  public void setInitialValue(Object newValue)
731  {
732    if (initialValue != newValue)
733      {
734        Object old = initialValue;
735        initialValue = newValue;
736        firePropertyChange(INITIAL_VALUE_PROPERTY, old, initialValue);
737      }
738  }
739
740  /**
741   * This method changes the inputValue property.
742   *
743   * @param newValue The new inputValue.
744   */
745  public void setInputValue(Object newValue)
746  {
747    if (inputValue != newValue)
748      {
749        Object old = inputValue;
750        inputValue = newValue;
751        firePropertyChange(INPUT_VALUE_PROPERTY, old, inputValue);
752      }
753  }
754
755  /**
756   * This method changes the message property.
757   *
758   * @param newMessage The new message.
759   */
760  public void setMessage(Object newMessage)
761  {
762    if (message != newMessage)
763      {
764        Object old = message;
765        message = newMessage;
766        firePropertyChange(MESSAGE_PROPERTY, old, message);
767      }
768  }
769
770  /**
771   * This method changes the messageType property.
772   *
773   * @param newType The new messageType.
774   *
775   * @throws IllegalArgumentException If the messageType is not valid.
776   */
777  public void setMessageType(int newType)
778  {
779    if (! validMessageType(newType))
780      throw new IllegalArgumentException("Message Type not legal value.");
781    if (newType != messageType)
782      {
783        int old = messageType;
784        messageType = newType;
785        firePropertyChange(MESSAGE_TYPE_PROPERTY, old, messageType);
786      }
787  }
788
789  /**
790   * This method changes the options property.
791   *
792   * @param newOptions The new options.
793   */
794  public void setOptions(Object[] newOptions)
795  {
796    if (options != newOptions)
797      {
798        Object[] old = options;
799        options = newOptions;
800        firePropertyChange(OPTIONS_PROPERTY, old, options);
801      }
802  }
803
804  /**
805   * This method changes the optionType property.
806   *
807   * @param newType The new optionType.
808   *
809   * @throws IllegalArgumentException If the optionType is not valid.
810   */
811  public void setOptionType(int newType)
812  {
813    if (! validOptionType(newType))
814      throw new IllegalArgumentException("Option Type not legal value.");
815    if (newType != optionType)
816      {
817        int old = optionType;
818        optionType = newType;
819        firePropertyChange(OPTION_TYPE_PROPERTY, old, optionType);
820      }
821  }
822
823  /**
824   * This method changes the Frame used for JOptionPane dialogs that have no
825   * parent.
826   *
827   * @param newRootFrame The Frame to use for dialogs that have no parent.
828   */
829  public static void setRootFrame(Frame newRootFrame)
830  {
831    privFrame = newRootFrame;
832  }
833
834  /**
835   * This method changes the selectionValues property.
836   *
837   * @param newValues The new selectionValues.
838   */
839  public void setSelectionValues(Object[] newValues)
840  {
841    if (newValues != selectionValues)
842      {
843        if (newValues != null)
844          wantsInput = true;
845        Object[] old = selectionValues;
846        selectionValues = newValues;
847        firePropertyChange(SELECTION_VALUES_PROPERTY, old, selectionValues);
848      }
849  }
850
851  /**
852   * This method sets the UI used with the JOptionPane.
853   *
854   * @param ui The UI used with the JOptionPane.
855   */
856  public void setUI(OptionPaneUI ui)
857  {
858    super.setUI(ui);
859  }
860
861  /**
862   * This method sets the value has been selected out of options.
863   *
864   * @param newValue The value that has been selected out of options.
865   */
866  public void setValue(Object newValue)
867  {
868    if (value != newValue)
869      {
870        Object old = value;
871        value = newValue;
872        firePropertyChange(VALUE_PROPERTY, old, value);
873      }
874  }
875
876  /**
877   * This method changes the wantsInput property.
878   *
879   * @param newValue Whether this JOptionPane requires input.
880   */
881  public void setWantsInput(boolean newValue)
882  {
883    if (wantsInput != newValue)
884      {
885        boolean old = wantsInput;
886        wantsInput = newValue;
887        firePropertyChange(WANTS_INPUT_PROPERTY, old, wantsInput);
888      }
889  }
890
891  /**
892   * This method shows a confirmation dialog with the title "Select an Option"
893   * and displays the given message. The parent frame will be the same as the
894   * parent frame of the given parentComponent. This method returns the
895   * option chosen by the user.
896   *
897   * @param parentComponent The parentComponent to find a frame in.
898   * @param message The message to display.
899   *
900   * @return The option that was selected.
901   */
902  public static int showConfirmDialog(Component parentComponent, Object message)
903  {
904    JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
905    JDialog dialog = pane.createDialog(parentComponent, "Select an Option");
906    dialog.show();
907
908    if (pane.getValue() instanceof Integer)
909      return ((Integer) pane.getValue()).intValue();
910    return -1;
911  }
912
913  /**
914   * This method shows a confirmation dialog with the given message,
915   * optionType and title. The frame that owns the dialog will be the same
916   * frame that holds the given parentComponent. This method returns the
917   * option that was chosen.
918   *
919   * @param parentComponent The component to find a frame in.
920   * @param message The message displayed.
921   * @param title The title of the dialog.
922   * @param optionType The optionType.
923   *
924   * @return The option that was chosen.
925   */
926  public static int showConfirmDialog(Component parentComponent,
927                                      Object message, String title,
928                                      int optionType)
929  {
930    JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType);
931    JDialog dialog = pane.createDialog(parentComponent, title);
932    dialog.show();
933
934    if (pane.getValue() instanceof Integer)
935      return ((Integer) pane.getValue()).intValue();
936    return -1;
937  }
938
939  /**
940   * This method shows a confirmation dialog with the given message, title,
941   * messageType and optionType. The frame owner will be the same frame as
942   * the one that holds the given parentComponent. This method returns the
943   * option selected by the user.
944   *
945   * @param parentComponent The component to find a frame in.
946   * @param message The message displayed.
947   * @param title The title of the dialog.
948   * @param optionType The optionType.
949   * @param messageType The messageType.
950   *
951   * @return The selected option.
952   */
953  public static int showConfirmDialog(Component parentComponent,
954                                      Object message, String title,
955                                      int optionType, int messageType)
956  {
957    JOptionPane pane = new JOptionPane(message, messageType, optionType);
958    JDialog dialog = pane.createDialog(parentComponent, title);
959    dialog.show();
960
961    if (pane.getValue() instanceof Integer)
962      return ((Integer) pane.getValue()).intValue();
963    return -1;
964  }
965
966  /**
967   * This method shows a confirmation dialog with the given message, title,
968   * optionType, messageType and icon. The frame owner will be the same as
969   * the one that holds the given parentComponent. This method returns the
970   * option selected by the user.
971   *
972   * @param parentComponent The component to find a frame in.
973   * @param message The message displayed.
974   * @param title The title of the dialog.
975   * @param optionType The optionType.
976   * @param messageType The messsageType.
977   * @param icon The icon displayed.
978   *
979   * @return The selected option.
980   */
981  public static int showConfirmDialog(Component parentComponent,
982                                      Object message, String title,
983                                      int optionType, int messageType,
984                                      Icon icon)
985  {
986    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon);
987    JDialog dialog = pane.createDialog(parentComponent, title);
988    dialog.show();
989
990    if (pane.getValue() instanceof Integer)
991      return ((Integer) pane.getValue()).intValue();
992    return -1;
993  }
994
995  /**
996   * This method will show a QUESTION_MESSAGE input dialog with the given
997   * message. No selectionValues is set so the Look and Feel will usually
998   * give the user a TextField to fill out. The frame owner will be the same
999   * frame that holds the given parentComponent. This method will return the
1000   * value entered by the user.
1001   *
1002   * @param parentComponent The component to find a frame in.
1003   * @param message The message displayed.
1004   *
1005   * @return The value entered by the user.
1006   */
1007  public static String showInputDialog(Component parentComponent,
1008                                       Object message)
1009  {
1010    JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
1011    pane.setWantsInput(true);
1012    JDialog dialog = pane.createDialog(parentComponent, null);
1013    dialog.show();
1014
1015    return (String) pane.getInputValue();
1016  }
1017
1018  /**
1019   * This method will show a QUESTION_MESSAGE type input dialog with the given
1020   * message and initialSelectionValue. Since there is no selectionValues
1021   * set, the Look and Feel will usually give a TextField to fill out. The
1022   * frame owner will be the same as the one that holds the given
1023   * parentComponent. This method will return the value entered by the user.
1024   *
1025   * @param parentComponent The component to find a frame in.
1026   * @param message The message to display.
1027   * @param initialSelectionValue The initially selected value.
1028   *
1029   * @return The value the user input.
1030   */
1031  public static String showInputDialog(Component parentComponent,
1032                                       Object message,
1033                                       Object initialSelectionValue)
1034  {
1035    JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
1036    pane.setInitialSelectionValue(initialSelectionValue);
1037    pane.setWantsInput(true);
1038    JDialog dialog = pane.createDialog(parentComponent, null);
1039    dialog.show();
1040
1041    return (String) pane.getInputValue();
1042  }
1043
1044  /**
1045   * This method displays a new input dialog with the given message, title and
1046   * messageType. Since no selectionValues value is given, the Look and Feel
1047   * will usually give the user a TextField to input data to. This method
1048   * returns the value the user inputs.
1049   *
1050   * @param parentComponent The component to find a frame in.
1051   * @param message The message to display.
1052   * @param title The title of the dialog.
1053   * @param messageType The messageType.
1054   *
1055   * @return The value the user input.
1056   */
1057  public static String showInputDialog(Component parentComponent,
1058                                       Object message, String title,
1059                                       int messageType)
1060  {
1061    JOptionPane pane = new JOptionPane(message, messageType);
1062    pane.setWantsInput(true);
1063    JDialog dialog = pane.createDialog(parentComponent, title);
1064    dialog.show();
1065
1066    return (String) pane.getInputValue();
1067  }
1068
1069  /**
1070   * This method shows an input dialog with the given message, title,
1071   * messageType, icon, selectionValues, and initialSelectionValue. This
1072   * method returns the value that the user selects.
1073   *
1074   * @param parentComponent The component to find a frame in.
1075   * @param message The message displayed.
1076   * @param title The title of the dialog.
1077   * @param messageType The messageType.
1078   * @param icon The icon displayed.
1079   * @param selectionValues The list of values to select from.
1080   * @param initialSelectionValue The initially selected value.
1081   *
1082   * @return The user selected value.
1083   */
1084  public static Object showInputDialog(Component parentComponent,
1085                                       Object message, String title,
1086                                       int messageType, Icon icon,
1087                                       Object[] selectionValues,
1088                                       Object initialSelectionValue)
1089  {
1090    JOptionPane pane = new JOptionPane(message, messageType);
1091    pane.setWantsInput(true);
1092    pane.setIcon(icon);
1093    pane.setSelectionValues(selectionValues);
1094    pane.setInitialSelectionValue(initialSelectionValue);
1095    JDialog dialog = pane.createDialog(parentComponent, title);
1096    dialog.show();
1097
1098    return pane.getInputValue();
1099  }
1100
1101  /**
1102   * This method shows a QUESTION_MESSAGE type input dialog. Since no
1103   * selectionValues is set, the Look and Feel will usually give the user a
1104   * TextField to input data to. This method returns the value the user
1105   * inputs.
1106   *
1107   * @param message The message to display.
1108   *
1109   * @return The user selected value.
1110   */
1111  public static String showInputDialog(Object message)
1112  {
1113    JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
1114    pane.setWantsInput(true);
1115    JDialog dialog = pane.createDialog(null, null);
1116    dialog.show();
1117
1118    return (String) pane.getInputValue();
1119  }
1120
1121  /**
1122   * This method shows a QUESTION_MESSAGE type input dialog. Since no
1123   * selectionValues is set, the Look and Feel will usually give the user a
1124   * TextField to input data to. The input component will be initialized with
1125   * the initialSelectionValue. This method returns the value the user
1126   * inputs.
1127   *
1128   * @param message The message to display.
1129   * @param initialSelectionValue The initialSelectionValue.
1130   *
1131   * @return The user selected value.
1132   */
1133  public static String showInputDialog(Object message,
1134                                       Object initialSelectionValue)
1135  {
1136    JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
1137    pane.setWantsInput(true);
1138    pane.setInitialSelectionValue(initialSelectionValue);
1139    JDialog dialog = pane.createDialog(null, null);
1140    dialog.show();
1141
1142    return (String) pane.getInputValue();
1143  }
1144
1145  /**
1146   * This method shows an internal confirmation dialog with the given message.
1147   * The internal frame dialog will be placed in the first JDesktopPane
1148   * ancestor of the given parentComponent. This method will return the value
1149   * selected.
1150   *
1151   * @param parentComponent The parent to find a JDesktopPane in.
1152   * @param message The message to display.
1153   *
1154   * @return The value selected.
1155   */
1156  public static int showInternalConfirmDialog(Component parentComponent,
1157                                              Object message)
1158  {
1159    JOptionPane pane = new JOptionPane(message);
1160    JInternalFrame frame = pane.createInternalFrame(parentComponent, null);
1161
1162    startModal(frame);
1163
1164    if (pane.getValue() instanceof Integer)
1165      return ((Integer) pane.getValue()).intValue();
1166    return -1;
1167  }
1168
1169  /**
1170   * This method shows an internal confirmation dialog with the given message,
1171   * optionType and title. The internal frame dialog will be placed in the
1172   * first JDesktopPane ancestor of the given parentComponent.  This method
1173   * will return the selected value.
1174   *
1175   * @param parentComponent The parent to find a JDesktopPane in.
1176   * @param message The message to display.
1177   * @param title The title to display.
1178   * @param optionType The option type.
1179   *
1180   * @return The selected value.
1181   */
1182  public static int showInternalConfirmDialog(Component parentComponent,
1183                                              Object message, String title,
1184                                              int optionType)
1185  {
1186    JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType);
1187    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1188
1189    startModal(frame);
1190
1191    if (pane.getValue() instanceof Integer)
1192      return ((Integer) pane.getValue()).intValue();
1193    return -1;
1194  }
1195
1196  /**
1197   * This method shows an internal confirmation dialog with the given message,
1198   * title, optionTypes and icon for the given message type. The internal
1199   * confirmation dialog will be placed in the first  instance of
1200   * JDesktopPane ancestor of the given parentComponent.
1201   *
1202   * @param parentComponent The component to find a JDesktopPane in.
1203   * @param message The message to display.
1204   * @param title The title of the dialog.
1205   * @param optionType The option type.
1206   * @param messageType The message type.
1207   *
1208   * @return The selected value.
1209   */
1210  public static int showInternalConfirmDialog(Component parentComponent,
1211                                              Object message, String title,
1212                                              int optionType, int messageType)
1213  {
1214    JOptionPane pane = new JOptionPane(message, messageType, optionType);
1215    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1216
1217    startModal(frame);
1218
1219    if (pane.getValue() instanceof Integer)
1220      return ((Integer) pane.getValue()).intValue();
1221    return -1;
1222  }
1223
1224  /**
1225   * This method shows an internal confirmation dialog with the given message,
1226   * title, option type, message type, and icon. The internal frame dialog
1227   * will be placed in the first JDesktopPane ancestor  that is found in the
1228   * given parentComponent. This method returns  the selected value.
1229   *
1230   * @param parentComponent The parent to find a JDesktopPane in.
1231   * @param message The message to display.
1232   * @param title The title to display.
1233   * @param optionType The option type.
1234   * @param messageType The message type.
1235   * @param icon The icon to display.
1236   *
1237   * @return The selected value.
1238   */
1239  public static int showInternalConfirmDialog(Component parentComponent,
1240                                              Object message, String title,
1241                                              int optionType, int messageType,
1242                                              Icon icon)
1243  {
1244    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon);
1245    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1246
1247    startModal(frame);
1248
1249    if (pane.getValue() instanceof Integer)
1250      return ((Integer) pane.getValue()).intValue();
1251    return -1;
1252  }
1253
1254  /**
1255   * This method shows an internal input dialog with the given message. The
1256   * internal frame dialog will be placed in the first JDesktopPane ancestor
1257   * of the given parent component. This method returns the value input by
1258   * the user.
1259   *
1260   * @param parentComponent The parent to find a JDesktopPane in.
1261   * @param message The message to display.
1262   *
1263   * @return The user selected value.
1264   */
1265  public static String showInternalInputDialog(Component parentComponent,
1266                                               Object message)
1267  {
1268    JOptionPane pane = new JOptionPane(message);
1269    pane.setWantsInput(true);
1270    JInternalFrame frame = pane.createInternalFrame(parentComponent, null);
1271
1272    startModal(frame);
1273
1274    return (String) pane.getInputValue();
1275  }
1276
1277  /**
1278   * This method shows an internal input dialog with the given message,  title
1279   * and message type. The internal input dialog will be placed in the first
1280   * JDesktopPane ancestor found in the given parent component. This method
1281   * will return the input value given by the user.
1282   *
1283   * @param parentComponent The component to find a JDesktopPane in.
1284   * @param message The message to display.
1285   * @param title The title to display.
1286   * @param messageType The message type.
1287   *
1288   * @return The user input value.
1289   */
1290  public static String showInternalInputDialog(Component parentComponent,
1291                                               Object message, String title,
1292                                               int messageType)
1293  {
1294    JOptionPane pane = new JOptionPane(message, messageType);
1295    pane.setWantsInput(true);
1296    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1297
1298    startModal(frame);
1299
1300    return (String) pane.getInputValue();
1301  }
1302
1303  /**
1304   * This method shows an internal input dialog with the given message, title
1305   * message type, icon, selection value list and initial selection value.
1306   * The internal frame dialog will be placed in the first JDesktopPane
1307   * ancestor found in the given parent component. This method returns the
1308   * input value from the user.
1309   *
1310   * @param parentComponent The parent to find a JDesktopPane in.
1311   * @param message The message to display.
1312   * @param title The title to display.
1313   * @param messageType The message type.
1314   * @param icon The icon to display.
1315   * @param selectionValues The selection value list.
1316   * @param initialSelectionValue The initial selection value.
1317   *
1318   * @return The user input value.
1319   */
1320  public static Object showInternalInputDialog(Component parentComponent,
1321                                               Object message, String title,
1322                                               int messageType, Icon icon,
1323                                               Object[] selectionValues,
1324                                               Object initialSelectionValue)
1325  {
1326    JOptionPane pane = new JOptionPane(message, messageType);
1327    pane.setWantsInput(true);
1328    pane.setIcon(icon);
1329    pane.setSelectionValues(selectionValues);
1330    pane.setInitialSelectionValue(initialSelectionValue);
1331    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1332
1333    startModal(frame);
1334
1335    return pane.getInputValue();
1336  }
1337
1338  /**
1339   * This method shows an internal message dialog with the given message. The
1340   * internal frame dialog will be placed in the first JDesktopPane ancestor
1341   * found in the given parent component.
1342   *
1343   * @param parentComponent The component to find a JDesktopPane in.
1344   * @param message The message to display.
1345   */
1346  public static void showInternalMessageDialog(Component parentComponent,
1347                                               Object message)
1348  {
1349    JOptionPane pane = new JOptionPane(message);
1350    JInternalFrame frame = pane.createInternalFrame(parentComponent, null);
1351
1352    startModal(frame);
1353  }
1354
1355  /**
1356   * This method shows an internal message dialog with the given message,
1357   * title and message type. The internal message dialog is placed in the
1358   * first JDesktopPane ancestor found in the given parent component.
1359   *
1360   * @param parentComponent The parent component to find a JDesktopPane in.
1361   * @param message The message to display.
1362   * @param title The title to display.
1363   * @param messageType The message type.
1364   */
1365  public static void showInternalMessageDialog(Component parentComponent,
1366                                               Object message, String title,
1367                                               int messageType)
1368  {
1369    JOptionPane pane = new JOptionPane(message, messageType);
1370    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1371
1372    startModal(frame);
1373  }
1374
1375  /**
1376   * This method shows an internal message dialog with the given message,
1377   * title, message type and icon. The internal message dialog is placed in
1378   * the first JDesktopPane ancestor found in the given parent component.
1379   *
1380   * @param parentComponent The component to find a JDesktopPane in.
1381   * @param message The message to display.
1382   * @param title The title to display.
1383   * @param messageType The message type.
1384   * @param icon The icon to display.
1385   */
1386  public static void showInternalMessageDialog(Component parentComponent,
1387                                               Object message, String title,
1388                                               int messageType, Icon icon)
1389  {
1390    JOptionPane pane = new JOptionPane(message, messageType);
1391    pane.setIcon(icon);
1392    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1393
1394    startModal(frame);
1395  }
1396
1397  /**
1398   * This method displays an internal option dialog with the given message,
1399   * title, option type, message type, icon, option list, and initial option
1400   * value. The internal option dialog is placed in the first JDesktopPane
1401   * ancestor found in the parent component. This method returns the option
1402   * selected.
1403   *
1404   * @param parentComponent The parent to find a JDesktopPane in.
1405   * @param message The message displayed.
1406   * @param title The title displayed.
1407   * @param optionType The option type.
1408   * @param messageType The message type.
1409   * @param icon The icon to display.
1410   * @param options The array of options.
1411   * @param initialValue The initial value selected.
1412   *
1413   * @return The option that was selected.
1414   */
1415  public static int showInternalOptionDialog(Component parentComponent,
1416                                             Object message, String title,
1417                                             int optionType, int messageType,
1418                                             Icon icon, Object[] options,
1419                                             Object initialValue)
1420  {
1421    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon,
1422                                       options, initialValue);
1423
1424    JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
1425
1426    startModal(frame);
1427
1428    if (pane.getValue() instanceof Integer)
1429      return ((Integer) pane.getValue()).intValue();
1430    return -1;
1431  }
1432
1433  /**
1434   * This method shows an INFORMATION_MESSAGE type message dialog.
1435   *
1436   * @param parentComponent The component to find a frame in.
1437   * @param message The message displayed.
1438   */
1439  public static void showMessageDialog(Component parentComponent,
1440                                       Object message)
1441  {
1442    JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE);
1443    JDialog dialog = pane.createDialog(parentComponent, null);
1444    dialog.show();
1445  }
1446
1447  /**
1448   * This method shows a message dialog with the given message, title and
1449   * messageType.
1450   *
1451   * @param parentComponent The component to find a frame in.
1452   * @param message The message displayed.
1453   * @param title The title of the dialog.
1454   * @param messageType The messageType.
1455   */
1456  public static void showMessageDialog(Component parentComponent,
1457                                       Object message, String title,
1458                                       int messageType)
1459  {
1460    JOptionPane pane = new JOptionPane(message, messageType);
1461    JDialog dialog = pane.createDialog(parentComponent, title);
1462    dialog.show();
1463  }
1464
1465  /**
1466   * This method shows a message dialog with the given message, title,
1467   * messageType and icon.
1468   *
1469   * @param parentComponent The component to find a frame in.
1470   * @param message The message displayed.
1471   * @param title The title of the dialog.
1472   * @param messageType The messageType.
1473   * @param icon The icon displayed.
1474   */
1475  public static void showMessageDialog(Component parentComponent,
1476                                       Object message, String title,
1477                                       int messageType, Icon icon)
1478  {
1479    JOptionPane pane = new JOptionPane(message, messageType);
1480    pane.setIcon(icon);
1481    JDialog dialog = pane.createDialog(parentComponent, title);
1482    dialog.show();
1483  }
1484
1485  /**
1486   * This method shows an option dialog with the given message, title,
1487   * optionType, messageType, icon, options and initialValue. This method
1488   * returns the option that was selected.
1489   *
1490   * @param parentComponent The component to find a frame in.
1491   * @param message The message displayed.
1492   * @param title The title of the dialog.
1493   * @param optionType The optionType.
1494   * @param messageType The messageType.
1495   * @param icon The icon displayed.
1496   * @param options The options to choose from.
1497   * @param initialValue The initial value.
1498   *
1499   * @return The selected option.
1500   */
1501  public static int showOptionDialog(Component parentComponent,
1502                                     Object message, String title,
1503                                     int optionType, int messageType,
1504                                     Icon icon, Object[] options,
1505                                     Object initialValue)
1506  {
1507    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon,
1508                                       options, initialValue);
1509
1510    JDialog dialog = pane.createDialog(parentComponent, title);
1511    dialog.show();
1512
1513    if (pane.getValue() instanceof Integer)
1514      return ((Integer) pane.getValue()).intValue();
1515    return -1;
1516  }
1517
1518  /**
1519   * This method resets the UI to the Look and Feel default.
1520   */
1521  public void updateUI()
1522  {
1523    setUI((OptionPaneUI) UIManager.getUI(this));
1524  }
1525
1526  /**
1527   * This method returns true if the key is a valid messageType.
1528   *
1529   * @param key The key to check.
1530   *
1531   * @return True if key is valid.
1532   */
1533  private boolean validMessageType(int key)
1534  {
1535    switch (key)
1536      {
1537      case ERROR_MESSAGE:
1538      case INFORMATION_MESSAGE:
1539      case PLAIN_MESSAGE:
1540      case QUESTION_MESSAGE:
1541      case WARNING_MESSAGE:
1542        return true;
1543      }
1544    return false;
1545  }
1546
1547  /**
1548   * This method returns true if the key is a valid optionType.
1549   *
1550   * @param key The key to check.
1551   *
1552   * @return True if key is valid.
1553   */
1554  private boolean validOptionType(int key)
1555  {
1556    switch (key)
1557      {
1558      case DEFAULT_OPTION:
1559      case OK_CANCEL_OPTION:
1560      case YES_NO_CANCEL_OPTION:
1561      case YES_NO_OPTION:
1562        return true;
1563      }
1564    return false;
1565  }
1566
1567  /**
1568   * This helper method makes the JInternalFrame wait until it is notified by
1569   * an InternalFrameClosing event. This method also adds the given
1570   * JOptionPane to the JInternalFrame and sizes it according to the
1571   * JInternalFrame's preferred size.
1572   *
1573   * @param f The JInternalFrame to make modal.
1574   */
1575  private static void startModal(JInternalFrame f)
1576  {
1577    // We need to add an additional glasspane-like component directly
1578    // below the frame, which intercepts all mouse events that are not
1579    // directed at the frame itself.
1580    JPanel modalInterceptor = new JPanel();
1581    modalInterceptor.setOpaque(false);
1582    JLayeredPane lp = JLayeredPane.getLayeredPaneAbove(f);
1583    lp.setLayer(modalInterceptor, JLayeredPane.MODAL_LAYER.intValue());
1584    modalInterceptor.setBounds(0, 0, lp.getWidth(), lp.getHeight());
1585    modalInterceptor.addMouseListener(new MouseAdapter(){});
1586    modalInterceptor.addMouseMotionListener(new MouseMotionAdapter(){});
1587    lp.add(modalInterceptor);
1588    f.toFront();
1589
1590    // We need to explicitly dispatch events when we are blocking the event
1591    // dispatch thread.
1592    EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
1593    try
1594      {
1595        while (! f.isClosed())
1596          {
1597            if (EventQueue.isDispatchThread())
1598              {
1599                // The getNextEventMethod() issues wait() when no
1600                // event is available, so we don't need do explicitly wait().
1601                AWTEvent ev = queue.getNextEvent();
1602                // This mimics EventQueue.dispatchEvent(). We can't use
1603                // EventQueue.dispatchEvent() directly, because it is
1604                // protected, unfortunately.
1605                if (ev instanceof ActiveEvent)
1606                  ((ActiveEvent) ev).dispatch();
1607                else if (ev.getSource() instanceof Component)
1608                  ((Component) ev.getSource()).dispatchEvent(ev);
1609                else if (ev.getSource() instanceof MenuComponent)
1610                  ((MenuComponent) ev.getSource()).dispatchEvent(ev);
1611                // Other events are ignored as per spec in
1612                // EventQueue.dispatchEvent
1613              }
1614            else
1615              {
1616                // Give other threads a chance to become active.
1617                Thread.yield();
1618              }
1619          }
1620      }
1621    catch (InterruptedException ex)
1622      {
1623        // If we get interrupted, then leave the modal state.
1624      }
1625    finally
1626      {
1627        // Clean up the modal interceptor.
1628        lp.remove(modalInterceptor);
1629
1630        // Remove the internal frame from its parent, so it is no longer
1631        // lurking around and clogging memory.
1632        Container parent = f.getParent();
1633        if (parent != null)
1634          parent.remove(f);
1635      }
1636  }
1637}