001    /* JOptionPane.java
002       Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.awt.AWTEvent;
042    import java.awt.ActiveEvent;
043    import java.awt.Component;
044    import java.awt.Container;
045    import java.awt.EventQueue;
046    import java.awt.Frame;
047    import java.awt.MenuComponent;
048    import java.awt.Toolkit;
049    import java.awt.event.MouseAdapter;
050    import java.awt.event.MouseMotionAdapter;
051    import java.beans.PropertyChangeEvent;
052    import java.beans.PropertyChangeListener;
053    
054    import javax.accessibility.Accessible;
055    import javax.accessibility.AccessibleContext;
056    import javax.accessibility.AccessibleRole;
057    import 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     */
065    public 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    }