OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / JOptionPane.java
1 /* JOptionPane.java
2    Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing;
40
41 import java.awt.AWTEvent;
42 import java.awt.ActiveEvent;
43 import java.awt.Component;
44 import java.awt.Container;
45 import java.awt.EventQueue;
46 import java.awt.Frame;
47 import java.awt.MenuComponent;
48 import java.awt.Toolkit;
49 import java.awt.event.MouseAdapter;
50 import java.awt.event.MouseMotionAdapter;
51 import java.beans.PropertyChangeEvent;
52 import java.beans.PropertyChangeListener;
53
54 import javax.accessibility.Accessible;
55 import javax.accessibility.AccessibleContext;
56 import javax.accessibility.AccessibleRole;
57 import javax.swing.plaf.OptionPaneUI;
58
59 /**
60  * This class creates different types of JDialogs and JInternalFrames that can
61  * ask users for input or pass on information. JOptionPane can be used by
62  * calling one of the show static methods or  by creating an instance of
63  * JOptionPane and calling createDialog or createInternalFrame.
64  */
65 public class JOptionPane extends JComponent implements Accessible
66 {
67   /**
68    * Provides the accessibility features for the <code>JOptionPane</code>
69    * component.
70    */
71   protected class AccessibleJOptionPane extends JComponent.AccessibleJComponent
72   {
73     private static final long serialVersionUID = 686071432213084821L;
74     
75     /**
76      * Creates a new <code>AccessibleJOptionPane</code> instance.
77      */
78     protected AccessibleJOptionPane()
79     {
80       // Nothing to do here.
81     }
82
83     /**
84      * Returns the accessible role of this object, which is always
85      * {@link AccessibleRole#OPTION_PANE}.
86      *
87      * @return the accessible role of this object
88      */
89     public AccessibleRole getAccessibleRole()
90     {
91       return AccessibleRole.OPTION_PANE;
92     }
93   }
94
95   private static final long serialVersionUID = 5231143276678566796L;
96
97   /** The value returned when cancel option is selected. */
98   public static final int CANCEL_OPTION = 2;
99
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 }