001    /* JInternalFrame.java --
002       Copyright (C) 2002, 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.BorderLayout;
042    import java.awt.Component;
043    import java.awt.Container;
044    import java.awt.Graphics;
045    import java.awt.IllegalComponentStateException;
046    import java.awt.KeyboardFocusManager;
047    import java.awt.LayoutManager;
048    import java.awt.Rectangle;
049    import java.beans.PropertyChangeEvent;
050    import java.beans.PropertyVetoException;
051    
052    import javax.accessibility.Accessible;
053    import javax.accessibility.AccessibleContext;
054    import javax.accessibility.AccessibleRole;
055    import javax.accessibility.AccessibleValue;
056    import javax.swing.event.InternalFrameEvent;
057    import javax.swing.event.InternalFrameListener;
058    import javax.swing.plaf.DesktopIconUI;
059    import javax.swing.plaf.InternalFrameUI;
060    
061    /**
062     * This class implements a Swing widget that looks and acts like a native
063     * frame. The frame can be dragged, resized, closed, etc. Typically,
064     * JInternalFrames are placed in JDesktopPanes. The actions that the
065     * JInternalFrame performs (maximizing, minimizing, etc.) are performed by a
066     * DesktopManager. As with regular frames, components are added by calling
067     * frame.getContentPane().add.
068     */
069    public class JInternalFrame extends JComponent implements Accessible,
070                                                              WindowConstants,
071                                                              RootPaneContainer
072    {
073    
074      private static final long serialVersionUID = -5425177187760785402L;
075    
076      /**
077       * Provides the accessibility features for the <code>JInternalFrame</code>
078       * component.
079       */
080      protected class AccessibleJInternalFrame extends AccessibleJComponent
081        implements AccessibleValue
082      {
083        private static final long serialVersionUID = 5931936924175476797L;
084    
085        /**
086         * Creates a new <code>AccessibleJInternalFrame</code> instance.
087         */
088        protected AccessibleJInternalFrame()
089        {
090          super();
091        }
092    
093        /**
094         * Returns the frame title.
095         *
096         * @return The frame title.
097         */
098        public String getAccessibleName()
099        {
100          return getTitle();
101        }
102    
103        /**
104         * Returns the accessible role for the <code>JInternalFrame</code>
105         * component.
106         *
107         * @return {@link AccessibleRole#INTERNAL_FRAME}.
108         */
109        public AccessibleRole getAccessibleRole()
110        {
111          return AccessibleRole.INTERNAL_FRAME;
112        }
113    
114        /**
115         * Returns an object that provides access to the current, minimum and
116         * maximum values for the {@link JInternalFrame}.  Since this class
117         * implements {@link AccessibleValue}, it returns itself.
118         *
119         * @return The accessible value.
120         */
121        public AccessibleValue getAccessibleValue()
122        {
123          return this;
124        }
125    
126        /**
127         * Returns the current layer for the {@link JInternalFrame} component,
128         * as an {@link Integer}.
129         *
130         * @return The layer for the {@link JInternalFrame} component.
131         */
132        public Number getCurrentAccessibleValue()
133        {
134          return new Integer(getLayer());
135        }
136    
137        /**
138         * Returns the maximum permitted accessible value.
139         *
140         * @return <code>Integer(Integer.MAX_VALUE)</code>.
141         */
142        public Number getMaximumAccessibleValue()
143        {
144          return new Integer(Integer.MAX_VALUE);
145        }
146    
147        /**
148         * Returns the minimum permitted accessible value.
149         *
150         * @return <code>Integer(Integer.MIN_VALUE)</code>.
151         */
152        public Number getMinimumAccessibleValue()
153        {
154          return new Integer(Integer.MIN_VALUE);
155        }
156    
157        /**
158         * Sets the layer for the internal frame.
159         *
160         * @param n  the layer (see the constants defined in {@link JLayeredPane}).
161         *
162         * @return <code>true</code> if the value is set, and <code>false</code>
163         *         if it was not set.
164         */
165        public boolean setCurrentAccessibleValue(Number n)
166        {
167          if (n == null)
168            return false;
169          setLayer(n.intValue());
170          return true;
171        }
172      }
173    
174      /**
175       * This class represents the JInternalFrame while it is iconified.
176       */
177      public static class JDesktopIcon extends JComponent implements Accessible
178      {
179        /**
180         * Provides the accessibility features for the <code>JDesktopIcon</code>
181         * component.
182         */
183        protected class AccessibleJDesktopIcon extends AccessibleJComponent
184          implements AccessibleValue
185        {
186          private static final long serialVersionUID = 5035560458941637802L;
187    
188          /**
189           * Creates a new <code>AccessibleJDesktopIcon</code> instance.
190           */
191          protected AccessibleJDesktopIcon()
192          {
193            super();
194          }
195    
196          /**
197           * Returns the accessible role for the <code>JDesktopIcon</code>
198           * component.
199           *
200           * @return {@link AccessibleRole#DESKTOP_ICON}.
201           */
202          public AccessibleRole getAccessibleRole()
203          {
204            return AccessibleRole.DESKTOP_ICON;
205          }
206    
207          /**
208           * Returns an object that provides access to the current, minimum and
209           * maximum values for the {@link JDesktopIcon}.  Since this class
210           * implements {@link AccessibleValue}, it returns itself.
211           *
212           * @return The accessible value.
213           */
214          public AccessibleValue getAccessibleValue()
215          {
216            return this;
217          }
218    
219          /**
220           * Returns the current layer for the {@link JInternalFrame} component
221           * represented by this <code>JDesktopIcon</code>, as an {@link Integer}.
222           *
223           * @return The layer.
224           */
225          public Number getCurrentAccessibleValue()
226          {
227            return new Integer(frame.getLayer());
228          }
229    
230          /**
231           * Returns the maximum permitted accessible value.
232           *
233           * @return <code>Integer(Integer.MAX_VALUE)</code>.
234           */
235          public Number getMaximumAccessibleValue()
236          {
237            return new Integer(Integer.MAX_VALUE);
238          }
239    
240          /**
241           * Returns the minimum permitted accessible value.
242           *
243           * @return <code>Integer(Integer.MIN_VALUE)</code>.
244           */
245          public Number getMinimumAccessibleValue()
246          {
247            return new Integer(Integer.MIN_VALUE);
248          }
249    
250          /**
251           * Sets the layer for the internal frame represented by this
252           * <code>JDesktopIcon</code> component.
253           *
254           * @param n  the layer (see the constants defined in
255           *           {@link JLayeredPane}).
256           *
257           * @return <code>true</code> if the value is set, and <code>false</code>
258           *         if it was not set.
259           */
260          public boolean setCurrentAccessibleValue(Number n)
261          {
262            if (n == null)
263              return false;
264            frame.setLayer(n.intValue());
265            return true;
266          }
267        }
268    
269        private static final long serialVersionUID = 4672973344731387687L;
270    
271        /** The JInternalFrame this DesktopIcon represents. */
272        JInternalFrame frame;
273    
274        /**
275         * Creates a new JDesktopIcon object for representing the given frame.
276         *
277         * @param f The JInternalFrame to represent.
278         */
279        public JDesktopIcon(JInternalFrame f)
280        {
281          frame = f;
282          updateUI();
283        }
284    
285      /**
286       * Returns the object that provides accessibility features for this
287       * <code>JDesktopIcon</code> component.
288       *
289       * @return The accessible context (an instance of
290       *         {@link AccessibleJDesktopIcon}).
291       */
292        public AccessibleContext getAccessibleContext()
293        {
294          if (accessibleContext == null)
295            accessibleContext = new AccessibleJDesktopIcon();
296          return accessibleContext;
297        }
298    
299        /**
300         * This method returns the JDesktopPane this JDesktopIcon is in.
301         *
302         * @return The JDesktopPane this JDesktopIcon is in.
303         */
304        public JDesktopPane getDesktopPane()
305        {
306          JDesktopPane p = (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class,
307                                                                            this);
308          return p;
309        }
310    
311        /**
312         * This method returns the JInternalFrame this JDesktopIcon represents.
313         *
314         * @return The JInternalFrame this JDesktopIcon represents.
315         */
316        public JInternalFrame getInternalFrame()
317        {
318          return frame;
319        }
320    
321        /**
322         * This method returns the UI that is responsible for the JDesktopIcon.
323         *
324         * @return The UI that is responsible for the JDesktopIcon.
325         */
326        public DesktopIconUI getUI()
327        {
328          return (DesktopIconUI) ui;
329        }
330    
331        /**
332         * This method returns the String identifier that is used to determine
333         * which class is used for JDesktopIcon's UI.
334         *
335         * @return A String identifier for the UI class.
336         */
337        public String getUIClassID()
338        {
339          return "DesktopIconUI";
340        }
341    
342        /**
343         * This method sets the JInternalFrame that this JDesktopIcon represents.
344         *
345         * @param f The JInternalFrame that this JDesktopIcon represents.
346         */
347        public void setInternalFrame(JInternalFrame f)
348        {
349          frame = f;
350        }
351    
352        /**
353         * This method sets the UI used for this JDesktopIcon.
354         *
355         * @param ui The UI to use.
356         */
357        public void setUI(DesktopIconUI ui)
358        {
359          super.setUI(ui);
360        }
361    
362        /**
363         * This method restores the UI property to the defaults.
364         */
365        public void updateUI()
366        {
367          setUI((DesktopIconUI) UIManager.getUI(this));
368        }
369      }
370    
371      /**
372       * The property fired in a PropertyChangeEvent when the contentPane property
373       * changes.
374       */
375      public static final String CONTENT_PANE_PROPERTY = "contentPane";
376    
377      /**
378       * The property fired in a PropertyChangeEvent when the frameIcon property
379       * changes.
380       */
381      public static final String FRAME_ICON_PROPERTY = "frameIcon";
382    
383      /**
384       * The property fired in a PropertyChangeEvent when the glassPane property
385       * changes.
386       */
387      public static final String GLASS_PANE_PROPERTY = "glassPane";
388    
389      /**
390       * The property fired in a PropertyChangeEvent when the closed property
391       * changes.
392       */
393      public static final String IS_CLOSED_PROPERTY = "closed";
394    
395      /**
396       * The property fired in a PropertyChangeEvent when the icon property
397       * changes.
398       */
399      public static final String IS_ICON_PROPERTY = "icon";
400    
401      /**
402       * The property fired in a PropertyChangeEvent when the maximum property
403       * changes.
404       */
405      public static final String IS_MAXIMUM_PROPERTY = "maximum";
406    
407      /**
408       * The property fired in a PropertyChangeEvent when the selected property
409       * changes.
410       */
411      public static final String IS_SELECTED_PROPERTY = "selected";
412    
413      /**
414       * The property fired in a PropertyChangeEvent when the layeredPane property
415       * changes.
416       */
417      public static final String LAYERED_PANE_PROPERTY = "layeredPane";
418    
419      /**
420       * The property fired in a PropertyChangeEvent when the jMenuBar property
421       * changes.
422       */
423      public static final String MENU_BAR_PROPERTY = "JMenuBar";
424    
425      /**
426       * The property fired in a PropertyChangeEvent when the rootPane property
427       * changes.
428       */
429      public static final String ROOT_PANE_PROPERTY = "rootPane";
430    
431      /**
432       * The property fired in a PropertyChangeEvent when the title property
433       * changes.
434       */
435      public static final String TITLE_PROPERTY = "title";
436    
437      /** Whether the JInternalFrame is closable. */
438      protected boolean closable;
439    
440      /** Whether the JInternalFrame can be iconified. */
441      protected boolean iconable;
442    
443      /** Whether the JInternalFrame is closed. */
444      protected boolean isClosed;
445    
446      /** Whether the JInternalFrame has been iconified. */
447      protected boolean isIcon;
448    
449      /** Whether the JInternalFrame has been maximized. */
450      protected boolean isMaximum;
451    
452      /** Whether the JInternalFrame is the active frame. */
453      protected boolean isSelected;
454    
455      /** Whether the JInternalFrame can be maximized. */
456      protected boolean maximizable;
457    
458      /**
459       * Whether the JInternalFrame has rootPaneChecking enabled.
460       *
461       * @specnote Should be false to comply with J2SE 5.0
462       */
463      protected boolean rootPaneCheckingEnabled = false;
464    
465      /** Whether the JInternalFrame is resizable. */
466      protected boolean resizable;
467    
468      /**
469       * The JDesktopIcon that represents the JInternalFrame while it is
470       * iconified.
471       */
472      protected JDesktopIcon desktopIcon;
473    
474      /** The icon used in the JMenuBar in the TitlePane. */
475      protected Icon frameIcon;
476    
477      /** The rootPane of the JInternalFrame. */
478      protected JRootPane rootPane;
479    
480      /** The title on the TitlePane of the JInternalFrame. */
481      protected String title;
482    
483      /** The bounds of the JInternalFrame before it was maximized. */
484      private transient Rectangle storedBounds;
485    
486      /** The Component that receives focus by default. */
487      private transient Component defaultFocus;
488    
489      /** The default close action taken, */
490      private transient int defaultCloseOperation = DISPOSE_ON_CLOSE;
491    
492      /** Whether the JInternalFrame has become visible for the very first time. */
493      private transient boolean isFirstTimeVisible = true;
494    
495      /** DOCUMENT ME! */
496      private transient boolean wasIcon = false;
497    
498      /**
499       * Creates a new JInternalFrame object that has an empty string for its
500       * title, and is non-resizable, non-maximizable, non-iconifiable, and
501       * non-closable.
502       */
503      public JInternalFrame()
504      {
505        this("", false, false, false, false);
506      }
507    
508      /**
509       * Creates a new JInternalFrame object with the given title and is
510       * non-resizable, non-maximizable, non-iconifiable, and non-closable.
511       *
512       * @param title The title displayed in the JInternalFrame.
513       */
514      public JInternalFrame(String title)
515      {
516        this(title, false, false, false, false);
517      }
518    
519      /**
520       * Creates a new JInternalFrame object with the given title and resizable
521       * properties. The JInternalFrame is non-maximizable, non-iconifiable, and
522       * non-closable.
523       *
524       * @param title The title displayed in the JInternalFrame.
525       * @param resizable Whether the JInternalFrame is resizable.
526       */
527      public JInternalFrame(String title, boolean resizable)
528      {
529        this(title, resizable, false, false, false);
530      }
531    
532      /**
533       * Creates a new JInternalFrame object with the given title, resizable, and
534       * closable properties. The JInternalFrame is non-maximizable and
535       * non-iconifiable.
536       *
537       * @param title The title displayed in the JInternalFrame.
538       * @param resizable Whether the JInternalFrame is resizable.
539       * @param closable Whether the JInternalFrame is closable.
540       */
541      public JInternalFrame(String title, boolean resizable, boolean closable)
542      {
543        this(title, resizable, closable, false, false);
544      }
545    
546      /**
547       * Creates a new JInternalFrame object with the given title, resizable,
548       * closable and maximizable properties. The JInternalFrame is
549       * non-iconifiable.
550       *
551       * @param title The title displayed in the JInternalFrame.
552       * @param resizable Whether the JInternalFrame is resizable.
553       * @param closable Whether the JInternalFrame is closable.
554       * @param maximizable Whether the JInternalFrame is maximizable.
555       */
556      public JInternalFrame(String title, boolean resizable, boolean closable,
557                            boolean maximizable)
558      {
559        this(title, resizable, closable, maximizable, false);
560      }
561    
562      /**
563       * Creates a new JInternalFrame object with the given title, resizable,
564       * closable, maximizable and iconifiable properties.
565       *
566       * @param title The title displayed in the JInternalFrame.
567       * @param resizable Whether the JInternalFrame is resizable.
568       * @param closable Whether the JInternalFrame is closable.
569       * @param maximizable Whether the JInternalFrame is maximizable.
570       * @param iconifiable Whether the JInternalFrame is iconifiable.
571       */
572      public JInternalFrame(String title, boolean resizable, boolean closable,
573                            boolean maximizable, boolean iconifiable)
574      {
575        this.title = title;
576        this.resizable = resizable;
577        this.closable = closable;
578        this.maximizable = maximizable;
579        this.iconable = iconifiable;
580        isMaximum = false;
581        setRootPane(createRootPane());
582        // JInternalFrames are invisible and opaque by default.
583        setVisible(false);
584        setOpaque(true);
585        desktopIcon = new JDesktopIcon(this);
586        updateUI();
587        setRootPaneCheckingEnabled(true); // Done the init stage, now adds go to content pane.
588      }
589    
590      /**
591       * This method adds Components to this Container. For JInternalFrames,
592       * instead of calling add directly on the JInternalFrame, it should be
593       * called with JInternalFrame.getContentPane().add. If root pane checking
594       * is enabled, calling this method will cause an exception to be thrown.
595       *
596       * @param comp The Component to add.
597       * @param constraints The constraints on the Component added.
598       * @param index The position to place the Component.
599       *
600       * @throws Error DOCUMENT ME!
601       */
602      protected void addImpl(Component comp, Object constraints, int index)
603      {
604        // If we're in the initialization stage use super.add. Here we add the
605        // rootPane as well as the title bar and other stuff.
606        // Otherwise pass the add onto the content pane.
607        if (isRootPaneCheckingEnabled())
608          getContentPane().add(comp, constraints, index);
609        else
610          super.addImpl(comp,constraints, index);
611      }
612    
613      /**
614       * This method adds an InternalFrameListener to this JInternalFrame.
615       *
616       * @param l The listener to add.
617       */
618      public void addInternalFrameListener(InternalFrameListener l)
619      {
620        listenerList.add(InternalFrameListener.class, l);
621      }
622    
623      /**
624       * This method is used to create a root pane for the JInternalFrame. This
625       * method is called by the constructors.
626       *
627       * @return A root pane for the JInternalFrame to use.
628       */
629      protected JRootPane createRootPane()
630      {
631        return new JRootPane();
632      }
633    
634      /**
635       * This method makes this JInternalFrame invisible, unselected and closed.
636       * If this JInternalFrame is not closed already, it will fire an
637       * INTERNAL_FRAME_CLoSED event. This method is similar to setClosed but it
638       * doesn't give vetoable listeners a chance to veto and it will not fire an
639       * INTERNAL_FRAME_CLOSING event.
640       */
641      public void dispose()
642      {
643        if (isVisible())
644          setVisible(false);
645        if (isSelected())
646          {
647            try
648              {
649                setSelected(false);
650              }
651            catch (PropertyVetoException e)
652              {
653                // Do nothing if they don't want to be unselected.
654              }
655          }
656        if (! isClosed)
657          {
658            firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE);
659            isClosed = true;
660          }
661        fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
662      }
663    
664      /**
665       * This method is used for closing this JInternalFrame. It fires an
666       * INTERNAL_FRAME_CLOSING event and then performs the action specified by
667       * the default close operation.
668       */
669      public void doDefaultCloseAction()
670      {
671        fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
672        switch (getDefaultCloseOperation())
673          {
674          case HIDE_ON_CLOSE:
675                setVisible(false);
676                break;
677          case DISPOSE_ON_CLOSE:
678                dispose();
679                break;
680          }
681      }
682    
683      /**
684       * This method fires an InternalFrameEvent to the listeners.
685       *
686       * @param id The type of event being fired. See InternalFrameEvent.
687       */
688      protected void fireInternalFrameEvent(int id)
689      {
690        Object[] ifListeners = listenerList.getListenerList();
691        InternalFrameEvent evt = new InternalFrameEvent(this, id);
692        switch (id)
693          {
694          case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
695            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
696              {
697                if (ifListeners[i] == InternalFrameListener.class)
698                  ((InternalFrameListener) ifListeners[i + 1])
699                  .internalFrameClosing(evt);
700              }
701            break;
702          case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
703            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
704              {
705                if (ifListeners[i] == InternalFrameListener.class)
706                  ((InternalFrameListener) ifListeners[i + 1])
707                  .internalFrameActivated(evt);
708              }
709            break;
710          case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
711            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
712              {
713                if (ifListeners[i] == InternalFrameListener.class)
714                  ((InternalFrameListener) ifListeners[i + 1]).internalFrameClosed(evt);
715              }
716            break;
717          case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
718            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
719              {
720                if (ifListeners[i] == InternalFrameListener.class)
721                  ((InternalFrameListener) ifListeners[i + 1])
722                  .internalFrameDeactivated(evt);
723              }
724            break;
725          case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
726            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
727              {
728                if (ifListeners[i] == InternalFrameListener.class)
729                  ((InternalFrameListener) ifListeners[i + 1])
730                  .internalFrameDeiconified(evt);
731              }
732            break;
733          case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
734            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
735              {
736                if (ifListeners[i] == InternalFrameListener.class)
737                  ((InternalFrameListener) ifListeners[i + 1])
738                  .internalFrameIconified(evt);
739              }
740            break;
741          case InternalFrameEvent.INTERNAL_FRAME_OPENED:
742            for (int i = ifListeners.length - 2; i >= 0; i -= 2)
743              {
744                if (ifListeners[i] == InternalFrameListener.class)
745                  ((InternalFrameListener) ifListeners[i + 1]).internalFrameOpened(evt);
746              }
747            break;
748          }
749      }
750    
751      /**
752       * Returns the object that provides accessibility features for this
753       * <code>JInternalFrame</code> component.
754       *
755       * @return The accessible context (an instance of
756       *     {@link AccessibleJInternalFrame}).
757       */
758      public AccessibleContext getAccessibleContext()
759      {
760        if (accessibleContext == null)
761          accessibleContext = new AccessibleJInternalFrame();
762        return accessibleContext;
763      }
764    
765      /**
766       * This method returns the Content Pane for this JInternalFrame.
767       *
768       * @return The Content Pane for this JInternalFrame.
769       */
770      public Container getContentPane()
771      {
772        return getRootPane().getContentPane();
773      }
774    
775      /**
776       * Returns a code for the default action taken when this
777       * <code>JInternalFrame</code> is closed.
778       *
779       * @return The action code (usually one of
780       *     {@link WindowConstants#DO_NOTHING_ON_CLOSE},
781       *     {@link WindowConstants#HIDE_ON_CLOSE}, or
782       *     {@link WindowConstants#DISPOSE_ON_CLOSE}).
783       *
784       * @see #setDefaultCloseOperation(int)
785       * @see #doDefaultCloseAction()
786       */
787      public int getDefaultCloseOperation()
788      {
789        return defaultCloseOperation;
790      }
791    
792      /**
793       * Returns the <code>JDesktopIcon</code> that represents this
794       * <code>JInternalFrame</code> while it is iconified.
795       *
796       * @return The desktop icon component.
797       */
798      public JDesktopIcon getDesktopIcon()
799      {
800        return desktopIcon;
801      }
802    
803      /**
804       * This method searches this JInternalFrame ancestors for an instance of
805       * JDesktopPane. If one is found, it is returned. If none is found, then it
806       * will search the JDesktopIcon for a JDesktopPane.
807       *
808       * @return The JDesktopPane that this JInternalFrame belongs to.
809       */
810      public JDesktopPane getDesktopPane()
811      {
812        JDesktopPane value = (JDesktopPane) SwingUtilities.getAncestorOfClass(JDesktopPane.class,
813                                                                              this);
814        if (value == null && desktopIcon != null)
815          value = desktopIcon.getDesktopPane();
816        return value;
817      }
818    
819      /**
820       * This method returns null because this must always be the root of a focus
821       * traversal.
822       *
823       * @return always null
824       *
825       * @since 1.4
826       */
827      public final Container getFocusCycleRootAncestor()
828      {
829        // as defined.
830        return null;
831      }
832    
833      /**
834       * This method returns the child Component that will receive focus if this
835       * JInternalFrame is selected.
836       *
837       * @return The child Component that will receive focus.
838       */
839      public Component getFocusOwner()
840      {
841        if (isSelected())
842          {
843            Component focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
844            if (SwingUtilities.isDescendingFrom(focus, this))
845              {
846                defaultFocus = focus;
847                return focus;
848              }
849          }
850        return null;
851      }
852    
853      /**
854       * This method returns the Frame Icon (the icon used in the JInternalFrame
855       * TitlePane and iconified frame).
856       *
857       * @return The Frame Icon.
858       */
859      public Icon getFrameIcon()
860      {
861        return frameIcon;
862      }
863    
864      /**
865       * This method returns the Glass Pane used with this JInternalFrame.
866       *
867       * @return The Glass Pane used with this JInternalFrame.
868       */
869      public Component getGlassPane()
870      {
871        return getRootPane().getGlassPane();
872      }
873    
874      /**
875       * This method returns an array of InternalFrameListeners that are listening
876       * to this JInternalFrame.
877       *
878       * @return An array of InternalFrameListeners that are listening to this
879       *         JInternalFrame.
880       */
881      public InternalFrameListener[] getInternalFrameListeners()
882      {
883        return (InternalFrameListener[]) listenerList.getListeners(InternalFrameListener.class);
884      }
885    
886      /**
887       * This method returns the JMenuBar for this JInternalFrame.
888       *
889       * @return The JMenuBar for this JInternalFrame.
890       */
891      public JMenuBar getJMenuBar()
892      {
893        return getRootPane().getJMenuBar();
894      }
895    
896      /**
897       * This method returns the layer that this JInternalFrame resides in.
898       *
899       * @return The layer that this JInternalFrame resides in.
900       */
901      public int getLayer()
902      {
903        return JLayeredPane.getLayer(this);
904      }
905    
906      /**
907       * This method returns the LayeredPane for this JInternalFrame.
908       *
909       * @return The LayeredPane for this JInternalFrame.
910       */
911      public JLayeredPane getLayeredPane()
912      {
913        return getRootPane().getLayeredPane();
914      }
915    
916      /**
917       * This method is deprecated. This method returns the JMenuBar for this
918       * JInternalFrame.
919       *
920       * @return The JMenuBar for this JInternalFrame.
921       *
922       * @deprecated 1.0.3
923       */
924      public JMenuBar getMenuBar()
925      {
926        return getJMenuBar();
927      }
928    
929      /**
930       * This method returns the child Component that will receive focus when the
931       * JInternalFrame is selected. If the JInternalFrame is selected, this
932       * method returns getFocusOwner(). Otherwise, it will return the child
933       * Component that most recently requested focus. If that is null, then the
934       * initial focus Component is returned. If that is null, then the default
935       * focus component is returned.
936       *
937       * @return The most recent focus owner.
938       */
939      public Component getMostRecentFocusOwner()
940      {
941        if (isSelected())
942          return getFocusOwner();
943        else
944          return defaultFocus;
945      }
946    
947      /**
948       * This method returns the bounds of the JInternalFrame if it is not
949       * maximized. If it is maximized, it returns the bounds of the
950       * JInternalFrame before it was maximized (the bounds that it will be
951       * restored to).
952       *
953       * @return A Rectangle that contains this JInternalFrame's normal bounds (or
954       *         just its bounds if it is not maximized).
955       */
956      public Rectangle getNormalBounds()
957      {
958        if (storedBounds == null)
959          return getBounds();
960        else
961          return storedBounds;
962      }
963    
964      /**
965       * This method returns the Root Pane for this JInternalFrame.
966       *
967       * @return The Root Pane for this JInternalFrame.
968       */
969      public JRootPane getRootPane()
970      {
971        return rootPane;
972      }
973    
974      /**
975       * Returns the frame's title.
976       *
977       * @return The frame's title (can be <code>null</code>).
978       *
979       * @see #setTitle(String)
980       */
981      public String getTitle()
982      {
983        return title;
984      }
985    
986      /**
987       * This method returns the UI used to represent the JInternalFrame.
988       *
989       * @return The UI used to represent the JInternalFrame.
990       */
991      public InternalFrameUI getUI()
992      {
993        return (InternalFrameUI) ui;
994      }
995    
996      /**
997       * This method returns a String identifier that is used to determine which
998       * class acts as the JInternalFrame's UI.
999       *
1000       * @return A String identifier to determine a UI class.
1001       */
1002      public String getUIClassID()
1003      {
1004        return "InternalFrameUI";
1005      }
1006    
1007      /**
1008       * This method returns null.
1009       *
1010       * @return null.
1011       */
1012      public final String getWarningString()
1013      {
1014        // as defined.
1015        return null;
1016      }
1017    
1018      /**
1019       * This method deselects this JInternalFrame and hides it.
1020       */
1021      public void hide()
1022      {
1023        if (isIcon())
1024          getDesktopIcon().hide();
1025        super.hide();
1026      }
1027    
1028      /**
1029       * This method returns whether this JInternalFrame is closable.
1030       *
1031       * @return Whether this JInternalFrame is closable.
1032       */
1033      public boolean isClosable()
1034      {
1035        return closable;
1036      }
1037    
1038      /**
1039       * This method returns whether this JInternalFrame has been closed.
1040       *
1041       * @return Whether this JInternalFrame is closed.
1042       */
1043      public boolean isClosed()
1044      {
1045        return isClosed;
1046      }
1047    
1048      /**
1049       * This must always return true.
1050       *
1051       * @return always true
1052       *
1053       * @since 1.4
1054       */
1055      public final boolean isFocusCycleRoot()
1056      {
1057        return true;
1058      }
1059    
1060      /**
1061       * This method returns whether this JInternalFrame is currently iconified.
1062       *
1063       * @return Whether this JInternalFrame is currently iconified.
1064       */
1065      public boolean isIcon()
1066      {
1067        return isIcon;
1068      }
1069    
1070      /**
1071       * This method returns whether the JInternalFrame can be iconified.
1072       *
1073       * @return Whether the JInternalFrame can be iconified.
1074       */
1075      public boolean isIconifiable()
1076      {
1077        return iconable;
1078      }
1079    
1080      /**
1081       * This method returns whether this JInternalFrame can be maximized.
1082       *
1083       * @return Whether this JInternalFrame can be maximized.
1084       */
1085      public boolean isMaximizable()
1086      {
1087        return maximizable;
1088      }
1089    
1090      /**
1091       * This method returns whether this JInternalFrame is currently maximized.
1092       *
1093       * @return Whether this JInternalFrame is maximized.
1094       */
1095      public boolean isMaximum()
1096      {
1097        return isMaximum;
1098      }
1099    
1100      /**
1101       * This method returns whether this JInternalFrame is resizable.
1102       *
1103       * @return Whether this JInternalFrame is resizable.
1104       */
1105      public boolean isResizable()
1106      {
1107        return resizable;
1108      }
1109    
1110      /**
1111       * This method returns whether root pane checking is enabled. If root pane
1112       * checking is enabled, then calls to addImpl and setLayout will throw
1113       * exceptions.
1114       *
1115       * @return Whether root pane checking is enabled.
1116       */
1117      protected boolean isRootPaneCheckingEnabled()
1118      {
1119        return rootPaneCheckingEnabled;
1120      }
1121    
1122      /**
1123       * This method returns whether this JInternalFrame is selected.
1124       *
1125       * @return Whether this JInternalFrame is selected.
1126       */
1127      public boolean isSelected()
1128      {
1129        return isSelected;
1130      }
1131    
1132      /**
1133       * A helper method that moves this JInternalFrame to the back if the parent
1134       * is a JLayeredPane.
1135       */
1136      public void moveToBack()
1137      {
1138        Container p = getParent();
1139        if (p instanceof JLayeredPane)
1140          ((JLayeredPane) p).moveToBack(this);
1141      }
1142    
1143      /**
1144       * A helper method that moves this JInternalFrame to the front if the parent
1145       * is a JLayeredPane.
1146       */
1147      public void moveToFront()
1148      {
1149        Container p = getParent();
1150        if (p != null && p instanceof JLayeredPane)
1151          ((JLayeredPane) p).moveToFront(this);
1152      }
1153    
1154      /**
1155       * This method causes the children of this JInternalFrame to be laid out.
1156       * Before it begins, if this JInternalFrame is an icon, then it will be
1157       * deiconified. If it is maximized, then it will be restored. If either
1158       * operation fails, then this method will return.
1159       */
1160      public void pack()
1161      {
1162        try
1163          {
1164            if (isIcon())
1165              setIcon(false);
1166            else if (isMaximum())
1167              setMaximum(false);
1168          }
1169        catch (PropertyVetoException e)
1170          {
1171            // Do nothing if they don't want to be restored first.
1172          }
1173        setSize(getPreferredSize());
1174        validate();
1175      }
1176    
1177      /**
1178       * This method is overridden to allow for speedier painting while this
1179       * JInternalFramme is being dragged.
1180       *
1181       * @param g The Graphics object to paint with.
1182       */
1183      protected void paintComponent(Graphics g)
1184      {
1185        super.paintComponent(g);
1186      }
1187    
1188      /**
1189       * An implementation dependent string describing the current state of this
1190       * <code>JInternalFrame</code> instance.
1191       *
1192       * @return A string describing the current state of this
1193       *     <code>JInternalFrame</code> instance.
1194       */
1195      protected String paramString()
1196      {
1197        return super.paramString() + ",title=" + getTitle();
1198      }
1199    
1200      /**
1201       * This method removes the given Component from the Container.
1202       *
1203       * @param comp The Component to remove.
1204       */
1205      public void remove(Component comp)
1206      {
1207        // If we're removing the root pane, use super.remove.  Otherwise
1208        // pass it on to the content pane instead.
1209        if (comp==rootPane || ! isRootPaneCheckingEnabled())
1210          super.remove(comp);
1211        else
1212          getContentPane().remove(comp);
1213      }
1214    
1215      /**
1216       * This method removes an InternalFrameListener from this JInternalFrame.
1217       *
1218       * @param l The listener to remove.
1219       */
1220      public void removeInternalFrameListener(InternalFrameListener l)
1221      {
1222        listenerList.remove(InternalFrameListener.class, l);
1223      }
1224    
1225      /**
1226       * This method resizes and positions this JInternalFrame. It also forces a
1227       * relayout of the Container.
1228       *
1229       * @param x The x position of this JInternalFrame.
1230       * @param y The y position of this JInternalFrame.
1231       * @param width The width of this JInternalFrame.
1232       * @param height The height of this JInternalFrame.
1233       */
1234      public void reshape(int x, int y, int width, int height)
1235      {
1236        super.reshape(x, y, width, height);
1237        revalidate();
1238      }
1239    
1240      /**
1241       * This method gives focus to the last child Component that had focus. This
1242       * is used by the UI when this JInternalFrame is activated.
1243       */
1244      public void restoreSubcomponentFocus()
1245      {
1246        Component c = getMostRecentFocusOwner();
1247        if (c != null)
1248          c.requestFocus();
1249      }
1250    
1251      /**
1252       * This method sets whether this JInternalFrame can be closed.
1253       *
1254       * @param b Whether this JInternalFrame can be closed.
1255       */
1256      public void setClosable(boolean b)
1257      {
1258        if (closable != b)
1259          {
1260            closable = b;
1261            firePropertyChange("closable", ! closable, closable);
1262          }
1263      }
1264    
1265      /**
1266       * This method closes the JInternalFrame if the given boolean is true. If it
1267       * is false, then the result of this method is unspecified. If the
1268       * JInternalFrame is closed, this method does nothing. This method will
1269       * first fire an INTERNAL_FRAME_CLOSING event and give a chance for veto
1270       * listeners to cancel the close. If no listener vetoes the change, the
1271       * closed property is set to true and the JInternalFrame is hidden and
1272       * unselected. The method will finish by firing an INTERNAL_FRAME_CLOSED
1273       * event.
1274       *
1275       * @param b Whether the JInternalFrame will be closed.
1276       *
1277       * @throws PropertyVetoException If a VetoableChangeListener vetoes the change.
1278       */
1279      public void setClosed(boolean b) throws PropertyVetoException
1280      {
1281        if (b && ! isClosed())
1282          {
1283            fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
1284            fireVetoableChange(IS_CLOSED_PROPERTY, false, true);
1285    
1286            isClosed = b;
1287            dispose();
1288    
1289            firePropertyChange(IS_CLOSED_PROPERTY, false, true);
1290          }
1291      }
1292    
1293      /**
1294       * This method sets the Container to be used as a Content Pane for this
1295       * JInternalFrame.
1296       *
1297       * @param c The Container to use as a Content Pane.
1298       */
1299      public void setContentPane(Container c)
1300      {
1301        if (c != getContentPane())
1302          {
1303            Container old = getContentPane();
1304            getRootPane().setContentPane(c);
1305            firePropertyChange(CONTENT_PANE_PROPERTY, old, c);
1306          }
1307      }
1308    
1309      /**
1310       * Sets a code for the action to be taken when this
1311       * <code>JInternalFrame</code> is closed.  Note that no validation is
1312       * performed on the <code>operation</code> code, any integer will be
1313       * accepted (nevertheless, you should pass in one of the listed values).
1314       *
1315       * @param operation  one of {@link WindowConstants#DO_NOTHING_ON_CLOSE},
1316       *   {@link WindowConstants#HIDE_ON_CLOSE} or
1317       *   {@link WindowConstants#DISPOSE_ON_CLOSE}.
1318       *
1319       * @see #getDefaultCloseOperation()
1320       * @see #doDefaultCloseAction()
1321       */
1322      public void setDefaultCloseOperation(int operation)
1323      {
1324        /* Reference implementation allows invalid operations to be specified.
1325           In that case, behaviour defaults to DO_NOTHING_ON_CLOSE.
1326           processWindowEvent handles the behaviour. getDefaultCloseOperation
1327           must return the invalid operator code. */
1328        defaultCloseOperation = operation;
1329      }
1330    
1331      /**
1332       * Sets the <code>JDesktopIcon</code> instance that represents this
1333       * <code>JInternalFrame</code> while it is iconified and, if the new icon is
1334       * not the same instance as the existing icon, sends a
1335       * {@link PropertyChangeEvent} (with the property name
1336       * <code>"desktopIcon"</code>) to all registered listeners..
1337       *
1338       * @param d  the icon.
1339       *
1340       * @see #getDesktopIcon()
1341       */
1342      public void setDesktopIcon(JDesktopIcon d)
1343      {
1344        if (desktopIcon != d)
1345          {
1346            JDesktopIcon oldIcon = desktopIcon;
1347            desktopIcon = d;
1348            firePropertyChange("desktopIcon", oldIcon, d);
1349          }
1350      }
1351    
1352      /**
1353       * This method does nothing because this must be the root of a focus
1354       * traversal cycle.
1355       *
1356       * @param focusCycleRoot Not used.
1357       */
1358      public final void setFocusCycleRoot(boolean focusCycleRoot)
1359      {
1360        // Do nothing
1361      }
1362    
1363      /**
1364       * This method sets the Icon to be used in two places. The first is icon
1365       * that is painted at the top left corner of the JInternalFrame when it is
1366       * not iconified (clicking on that icon will activate the TitlePane
1367       * JMenuBar). When the JInternalFrame is iconified, it will be the icon
1368       * displayed in the JDesktopIcon. If no icon is set, the JInternalFrame
1369       * will use a Look and Feel default.
1370       *
1371       * @param icon The Icon used in the TitlePane JMenuBar and iconified frames.
1372       */
1373      public void setFrameIcon(Icon icon)
1374      {
1375        if (icon != frameIcon)
1376          {
1377            Icon old = frameIcon;
1378            frameIcon = icon;
1379            firePropertyChange(FRAME_ICON_PROPERTY, old, frameIcon);
1380          }
1381      }
1382    
1383      /**
1384       * This method sets the Glass Pane used with this JInternalFrame.
1385       *
1386       * @param glass The Glass Pane to use with this JInternalFrame.
1387       */
1388      public void setGlassPane(Component glass)
1389      {
1390        if (glass != getGlassPane())
1391          {
1392            Component old = getGlassPane();
1393            getRootPane().setGlassPane(glass);
1394            firePropertyChange(GLASS_PANE_PROPERTY, old, glass);
1395          }
1396      }
1397    
1398      /**
1399       * This method iconifies or deiconifies this JInternalFrame given the
1400       * boolean argument. If the JInternalFrame becomes iconified, it will fire
1401       * an INTERNAL_FRAME_ICONIFIED event. If the JInternalFrame becomes
1402       * deiconified, it will fire anINTERNAL_FRAME_DEICONIFIED event.
1403       *
1404       * @param b Whether this JInternalFrame is to be iconified or deiconified.
1405       *
1406       * @throws PropertyVetoException DOCUMENT ME!
1407       */
1408      public void setIcon(boolean b) throws PropertyVetoException
1409      {
1410        if (b != isIcon())
1411          {
1412            fireVetoableChange(IS_ICON_PROPERTY, b, isIcon);
1413    
1414            isIcon = b;
1415    
1416            firePropertyChange(IS_ICON_PROPERTY, ! isIcon, isIcon);
1417            if (b)
1418              fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED);
1419            else
1420              fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
1421          }
1422      }
1423    
1424      /**
1425       * This method sets whether the JInternalFrame can be iconified. (This means
1426       * that the JInternalFrame can be turned into an icon if minimized).
1427       *
1428       * @param b Whether the JInternalFrame can be iconified.
1429       */
1430      public void setIconifiable(boolean b)
1431      {
1432        if (iconable != b)
1433          {
1434            iconable = b;
1435            firePropertyChange("iconable", ! iconable, iconable);
1436          }
1437      }
1438    
1439      /**
1440       * This method sets the JMenuBar to be used with this JInternalFrame.
1441       *
1442       * @param b The JMenuBar to be used with this JInternalFrame.
1443       */
1444      public void setJMenuBar(JMenuBar b)
1445      {
1446        JMenuBar old = getJMenuBar();
1447        getRootPane().setJMenuBar(b);
1448        firePropertyChange(MENU_BAR_PROPERTY, old, b);
1449      }
1450    
1451      /**
1452       * A helper method that set the layer that this JInternalFrame resides in.
1453       * Using this version of the method means that the user should not set it
1454       * to values that are already defined in JLayeredPane. If predefined values
1455       * are to be used, the user should use the setLayer(Integer) version.
1456       *
1457       * @param layer The layer to place this JInternalFrame in.
1458       */
1459      public void setLayer(int layer)
1460      {
1461        setLayer(new Integer(layer));
1462      }
1463    
1464      /**
1465       * A helper method that sets the layer that this JInternalFrame resides in.
1466       * Calling this version of the method should use layer values that are
1467       * already defined in JLayeredPane.
1468       *
1469       * @param layer The layer to place this JInternalFrame in.
1470       */
1471      public void setLayer(Integer layer)
1472      {
1473        Container p = getParent();
1474        if (p instanceof JLayeredPane)
1475          {
1476            JLayeredPane lp = (JLayeredPane) p;
1477            lp.setLayer(this, layer.intValue(), lp.getPosition(this));
1478          }
1479        else
1480          {
1481            JLayeredPane.putLayer(this, layer.intValue());
1482            if (p != null)
1483              p.repaint(getX(), getY(), getWidth(), getHeight());
1484          }
1485      }
1486    
1487      /**
1488       * This method sets the JLayeredPane to use with this JInternalFrame.
1489       *
1490       * @param layered The JLayeredPane to use as a layeredPane.
1491       */
1492      public void setLayeredPane(JLayeredPane layered)
1493      {
1494        if (layered == null)
1495          throw new IllegalComponentStateException("LayeredPane must not be null");
1496    
1497        if (layered != getLayeredPane())
1498          {
1499            JLayeredPane old = getLayeredPane();
1500            getRootPane().setLayeredPane(layered);
1501            firePropertyChange(LAYERED_PANE_PROPERTY, old, layered);
1502          }
1503      }
1504    
1505      /**
1506       * This method sets whether the JInternalFrame can be maximized.
1507       *
1508       * @param b Whether this JInternalFrame can be maximized.
1509       */
1510      public void setMaximizable(boolean b)
1511      {
1512        if (maximizable != b)
1513          {
1514            maximizable = b;
1515            firePropertyChange("maximizable", ! maximizable, maximizable);
1516          }
1517      }
1518    
1519      /**
1520       * This method sets the Layout Manager used in the JInternalFrame. SetLayout
1521       * should not be called on the JInternalFrame directly. Instead, it should
1522       * be called with JInternalFrame.getContentPane().setLayout. Calls to this
1523       * method with root pane checking enabled will cause exceptions to be
1524       * thrown.
1525       *
1526       * @param manager The Layout Manager to be used with the JInternalFrame.
1527       *
1528       * @throws Error If rootPaneChecking is enabled.
1529       */
1530      public void setLayout(LayoutManager manager)
1531      {
1532        // Check if we're in initialization stage.  If so, call super.setLayout
1533        // otherwise, valid calls go to the content pane.
1534        if (isRootPaneCheckingEnabled())
1535          getContentPane().setLayout(manager);
1536        else
1537          super.setLayout(manager);
1538      }
1539    
1540      /**
1541       * This method sets the JInternalFrame to maximized (if the given argument
1542       * is true) or restores the JInternalFrame to its normal bounds otherwise.
1543       *
1544       * @param b Whether this JInteralFrame will be maximized or restored.
1545       *
1546       * @throws PropertyVetoException If a VetoableChangeListener vetoes the change.
1547       */
1548      public void setMaximum(boolean b) throws PropertyVetoException
1549      {
1550        if (b != isMaximum)
1551          {
1552            fireVetoableChange(IS_MAXIMUM_PROPERTY, isMaximum, b);
1553            isMaximum = b;
1554            firePropertyChange(IS_MAXIMUM_PROPERTY, ! isMaximum, isMaximum);
1555          }
1556      }
1557    
1558      /**
1559       * This method is deprecated. This method sets the JMenuBar used with this
1560       * JInternalFrame.
1561       *
1562       * @param m The JMenuBar to use with this JInternalFrame.
1563       *
1564       * @deprecated 1.0.3
1565       */
1566      public void setMenuBar(JMenuBar m)
1567      {
1568        setJMenuBar(m);
1569      }
1570    
1571      /**
1572       * This method sets the bounds that this JInternalFrame will be restored to.
1573       *
1574       * @param r The bounds that this JInternalFrame will be restored to.
1575       */
1576      public void setNormalBounds(Rectangle r)
1577      {
1578        storedBounds = r;
1579      }
1580    
1581      /**
1582       * This method sets whether the JInternalFrame can be resized by a user
1583       * action (like dragging at the frame borders).
1584       *
1585       * @param b Whether this JInternalFramer can be resized.
1586       */
1587      public void setResizable(boolean b)
1588      {
1589        if (b != resizable)
1590          {
1591            resizable = b;
1592            firePropertyChange("resizable", ! resizable, resizable);
1593          }
1594      }
1595    
1596      /**
1597       * This method sets the Root Pane for this JInternalFrame.
1598       *
1599       * @param root The Root Pane for this JInternalFrame.
1600       */
1601      protected void setRootPane(JRootPane root)
1602      {
1603        if (rootPane != null)
1604          remove(rootPane);
1605    
1606        JRootPane old = rootPane;
1607        rootPane = root;
1608    
1609        if (rootPane != null)
1610          {
1611            boolean checkingEnabled = isRootPaneCheckingEnabled();
1612            try
1613              {
1614                setRootPaneCheckingEnabled(false);
1615                add(rootPane, BorderLayout.CENTER);
1616              }
1617            finally
1618              {
1619                setRootPaneCheckingEnabled(checkingEnabled);
1620              }
1621          }
1622        firePropertyChange(ROOT_PANE_PROPERTY, old, rootPane);
1623      }
1624    
1625      /**
1626       * This method sets whether root pane checking is enabled. If root pane
1627       * checking is enabled, then calls to addImpl and setLayout will throw
1628       * exceptions.
1629       *
1630       * @param enabled Whether root pane checking is enabled.
1631       */
1632      protected void setRootPaneCheckingEnabled(boolean enabled)
1633      {
1634        rootPaneCheckingEnabled = enabled;
1635      }
1636    
1637      /**
1638       * This method sets whether this JInternalFrame is the selected frame in the
1639       * JDesktopPane (or other container). When selected, a JInternalFrame will
1640       * have focus and paint its TitlePane differently (usually a different
1641       * colour). If this method selects the frame, this JInternalFrame will fire
1642       * an INTERNAL_FRAME_ACTIVATED event. If it deselects this frame, it will
1643       * fire an INTERNAL_FRAME_DEACTIVATED event.
1644       *
1645       * @param selected Whether this JInternalFrame will become selected or
1646       *        deselected.
1647       *
1648       * @throws PropertyVetoException If a VetoableChangeListener vetoes the change.
1649       */
1650      public void setSelected(boolean selected) throws PropertyVetoException
1651      {
1652        if (selected != isSelected
1653            && (! selected || (isIcon ? desktopIcon.isShowing() : isShowing())))
1654          {
1655            fireVetoableChange(IS_SELECTED_PROPERTY, isSelected, selected);
1656    
1657            if (! selected)
1658              defaultFocus = getMostRecentFocusOwner();
1659    
1660            isSelected = selected;
1661            firePropertyChange(IS_SELECTED_PROPERTY, ! isSelected, isSelected);
1662    
1663            if (isSelected)
1664              fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED);
1665            else
1666              fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
1667    
1668            if (selected)
1669              restoreSubcomponentFocus();
1670    
1671            repaint();
1672          }
1673      }
1674    
1675      /**
1676       * Sets the title for the <code>JInternalFrame</code> and sends a
1677       * {@link PropertyChangeEvent} (with the property name
1678       * {@link #TITLE_PROPERTY}) to all registered listeners.
1679       *
1680       * @param title  the new title (<code>null</code> permitted).
1681       *
1682       * @see #getTitle()
1683       */
1684      public void setTitle(String title)
1685      {
1686        String old = this.title;
1687        this.title = title;
1688        firePropertyChange(TITLE_PROPERTY, old, this.title);
1689      }
1690    
1691      /**
1692       * This method displays the JInternalFrame. If it is not visible, this
1693       * method will bring this JInternalFrame to the front, make it visible and
1694       * select it. If this is the first time this JInternalFrame is made
1695       * visible, an INTERNAL_FRAME_OPENED event will be fired.
1696       */
1697      public void show()
1698      {
1699        if (! isVisible())
1700          {
1701            if (isFirstTimeVisible)
1702              {
1703                isFirstTimeVisible = false;
1704                fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
1705              }
1706    
1707            getDesktopIcon().setVisible(true);
1708    
1709            toFront();
1710            super.show();
1711    
1712            if (isIcon())
1713              return;
1714    
1715            if (! isSelected())
1716              {
1717                try
1718                  {
1719                    setSelected(true);
1720                  }
1721                catch (PropertyVetoException e)
1722                  {
1723                    // Do nothing. if they don't want to be selected.
1724                  }
1725              }
1726          }
1727      }
1728    
1729      /**
1730       * This method is used to set the UI responsible for the JInternalFrame.
1731       *
1732       * @param ui The UI responsible for the JInternalFrame.
1733       */
1734      public void setUI(InternalFrameUI ui)
1735      {
1736        // We must temporarily go into init mode so that the UI can directly
1737        // manipulate the JInternalFrame.
1738        boolean old = isRootPaneCheckingEnabled();
1739        setRootPaneCheckingEnabled(false);
1740        super.setUI(ui);
1741        setRootPaneCheckingEnabled(old);
1742      }
1743    
1744      /**
1745       * This method causes the JInternalFrame to be brough to back in the
1746       * z-order.
1747       */
1748      public void toBack()
1749      {
1750        moveToBack();
1751      }
1752    
1753      /**
1754       * This method causes the JInternalFrame to be brought to front in the
1755       * z-order.
1756       */
1757      public void toFront()
1758      {
1759        moveToFront();
1760      }
1761    
1762      /**
1763       * This method resets the UI to the Look and Feel defaults.
1764       */
1765      public void updateUI()
1766      {
1767        // We must go into the init stage when updating the UI, so the UI can
1768        // set layout and components directly on the internal frame, not its
1769        // content pane.
1770            boolean old = isRootPaneCheckingEnabled();
1771        setRootPaneCheckingEnabled(false);
1772        setUI((InternalFrameUI) UIManager.getUI(this));
1773        setRootPaneCheckingEnabled(old);
1774      }
1775    
1776      /**
1777       * This helper method allows JInternalFrames to signal that they were
1778       * iconned for the first time.
1779       *
1780       * @param b Whether the JInternalFrame was iconned.
1781       * @param ID The identifier of the property change event to fire if the
1782       *        JInternalFrame is iconned for the first time.
1783       */
1784      void setWasIcon(boolean b, String ID)
1785      {
1786        if (b && ! wasIcon)
1787          {
1788            wasIcon = b;
1789            firePropertyChange(ID, ! b, b);
1790          }
1791      }
1792    
1793      /**
1794       * This helper method returns whether the JInternalFrame has been iconned
1795       * once already.
1796       *
1797       * @return Whether the JInternalFrame has been iconned once already.
1798       */
1799      boolean getWasIcon()
1800      {
1801        return wasIcon;
1802      }
1803    
1804      /**
1805       * This method is a convenience method to fire vetoable property changes.
1806       *
1807       * @param name The identifier of the property change.
1808       * @param oldValue The old value.
1809       * @param newValue The new value.
1810       *
1811       * @throws PropertyVetoException Fired if a vetoable change listener vetoes
1812       *         the change.
1813       */
1814      private void fireVetoableChange(String name, boolean oldValue,
1815                                      boolean newValue)
1816                               throws PropertyVetoException
1817      {
1818        super.fireVetoableChange(name, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
1819      }
1820    }