1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing;
  26 
  27 import java.awt.*;
  28 
  29 import java.beans.JavaBean;
  30 import java.beans.BeanProperty;
  31 import java.beans.PropertyVetoException;
  32 import java.beans.PropertyChangeEvent;
  33 import java.beans.PropertyChangeListener;
  34 
  35 import javax.swing.event.InternalFrameEvent;
  36 import javax.swing.event.InternalFrameListener;
  37 import javax.swing.plaf.*;
  38 
  39 import javax.accessibility.*;
  40 
  41 import java.io.ObjectOutputStream;
  42 import java.io.IOException;
  43 import java.lang.StringBuilder;
  44 
  45 import sun.awt.AppContext;
  46 import sun.swing.SwingUtilities2;
  47 
  48 /**
  49  * A lightweight object that provides many of the features of
  50  * a native frame, including dragging, closing, becoming an icon,
  51  * resizing, title display, and support for a menu bar.
  52  * For task-oriented documentation and examples of using internal frames,
  53  * see <a
  54  href="http://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html" target="_top">How to Use Internal Frames</a>,
  55  * a section in <em>The Java Tutorial</em>.
  56  *
  57  * <p>
  58  *
  59  * Generally,
  60  * you add <code>JInternalFrame</code>s to a <code>JDesktopPane</code>. The UI
  61  * delegates the look-and-feel-specific actions to the
  62  * <code>DesktopManager</code>
  63  * object maintained by the <code>JDesktopPane</code>.
  64  * <p>
  65  * The <code>JInternalFrame</code> content pane
  66  * is where you add child components.
  67  * As a convenience, the {@code add}, {@code remove}, and {@code setLayout}
  68  * methods of this class are overridden, so that they delegate calls
  69  * to the corresponding methods of the {@code ContentPane}.
  70  * For example, you can add a child component to an internal frame as follows:
  71  * <pre>
  72  *       internalFrame.add(child);
  73  * </pre>
  74  * And the child will be added to the contentPane.
  75  * The content pane is actually managed by an instance of
  76  * <code>JRootPane</code>,
  77  * which also manages a layout pane, glass pane, and
  78  * optional menu bar for the internal frame. Please see the
  79  * <code>JRootPane</code>
  80  * documentation for a complete description of these components.
  81  * Refer to {@link javax.swing.RootPaneContainer}
  82  * for details on adding, removing and setting the <code>LayoutManager</code>
  83  * of a <code>JInternalFrame</code>.
  84  * <p>
  85  * <strong>Warning:</strong> Swing is not thread safe. For more
  86  * information see <a
  87  * href="package-summary.html#threading">Swing's Threading
  88  * Policy</a>.
  89  * <p>
  90  * <strong>Warning:</strong>
  91  * Serialized objects of this class will not be compatible with
  92  * future Swing releases. The current serialization support is
  93  * appropriate for short term storage or RMI between applications running
  94  * the same version of Swing.  As of 1.4, support for long term storage
  95  * of all JavaBeans&trade;
  96  * has been added to the <code>java.beans</code> package.
  97  * Please see {@link java.beans.XMLEncoder}.
  98  *
  99  * @see InternalFrameEvent
 100  * @see JDesktopPane
 101  * @see DesktopManager
 102  * @see JInternalFrame.JDesktopIcon
 103  * @see JRootPane
 104  * @see javax.swing.RootPaneContainer
 105  *
 106  * @author David Kloba
 107  * @author Rich Schiavi
 108  * @since 1.2
 109  */
 110 @JavaBean(defaultProperty = "JMenuBar", description = "A frame container which is contained within another window.")
 111 @SwingContainer(delegate = "getContentPane")
 112 @SuppressWarnings("serial") // Same-version serialization only
 113 public class JInternalFrame extends JComponent implements
 114         Accessible, WindowConstants,
 115         RootPaneContainer
 116 {
 117     /**
 118      * @see #getUIClassID
 119      * @see #readObject
 120      */
 121     private static final String uiClassID = "InternalFrameUI";
 122 
 123     /**
 124      * The <code>JRootPane</code> instance that manages the
 125      * content pane
 126      * and optional menu bar for this internal frame, as well as the
 127      * glass pane.
 128      *
 129      * @see JRootPane
 130      * @see RootPaneContainer
 131      */
 132     protected JRootPane rootPane;
 133 
 134     /**
 135      * If true then calls to <code>add</code> and <code>setLayout</code>
 136      * will be forwarded to the <code>contentPane</code>. This is initially
 137      * false, but is set to true when the <code>JInternalFrame</code> is
 138      * constructed.
 139      *
 140      * @see #isRootPaneCheckingEnabled
 141      * @see #setRootPaneCheckingEnabled
 142      * @see javax.swing.RootPaneContainer
 143      */
 144     protected boolean rootPaneCheckingEnabled = false;
 145 
 146     /** The frame can be closed. */
 147     protected boolean closable;
 148     /** The frame has been closed. */
 149     protected boolean isClosed;
 150     /** The frame can be expanded to the size of the desktop pane. */
 151     protected boolean maximizable;
 152     /**
 153      * The frame has been expanded to its maximum size.
 154      * @see #maximizable
 155      */
 156     protected boolean isMaximum;
 157     /**
 158      * The frame can "iconified" (shrunk down and displayed as
 159      * an icon-image).
 160      * @see JInternalFrame.JDesktopIcon
 161      * @see #setIconifiable
 162      */
 163     protected boolean iconable;
 164     /**
 165      * The frame has been iconified.
 166      * @see #isIcon()
 167      */
 168     protected boolean isIcon;
 169     /** The frame's size can be changed. */
 170     protected boolean resizable;
 171     /** The frame is currently selected. */
 172     protected boolean isSelected;
 173     /** The icon shown in the top-left corner of this internal frame. */
 174     protected Icon frameIcon;
 175     /** The title displayed in this internal frame's title bar. */
 176     protected String  title;
 177     /**
 178      * The icon that is displayed when this internal frame is iconified.
 179      * @see #iconable
 180      */
 181     protected JDesktopIcon desktopIcon;
 182 
 183     private Cursor lastCursor;
 184 
 185     private boolean opened;
 186 
 187     private Rectangle normalBounds = null;
 188 
 189     private int defaultCloseOperation = DISPOSE_ON_CLOSE;
 190 
 191     /**
 192      * Contains the Component that focus is to go when
 193      * <code>restoreSubcomponentFocus</code> is invoked, that is,
 194      * <code>restoreSubcomponentFocus</code> sets this to the value returned
 195      * from <code>getMostRecentFocusOwner</code>.
 196      */
 197     private Component lastFocusOwner;
 198 
 199     /** Bound property name. */
 200     public final static String CONTENT_PANE_PROPERTY = "contentPane";
 201     /** Bound property name. */
 202     public final static String MENU_BAR_PROPERTY = "JMenuBar";
 203     /** Bound property name. */
 204     public final static String TITLE_PROPERTY = "title";
 205     /** Bound property name. */
 206     public final static String LAYERED_PANE_PROPERTY = "layeredPane";
 207     /** Bound property name. */
 208     public final static String ROOT_PANE_PROPERTY = "rootPane";
 209     /** Bound property name. */
 210     public final static String GLASS_PANE_PROPERTY = "glassPane";
 211     /** Bound property name. */
 212     public final static String FRAME_ICON_PROPERTY = "frameIcon";
 213 
 214     /**
 215      * Constrained property name indicated that this frame has
 216      * selected status.
 217      */
 218     public final static String IS_SELECTED_PROPERTY = "selected";
 219     /** Constrained property name indicating that the internal frame is closed. */
 220     public final static String IS_CLOSED_PROPERTY = "closed";
 221     /** Constrained property name indicating that the internal frame is maximized. */
 222     public final static String IS_MAXIMUM_PROPERTY = "maximum";
 223     /** Constrained property name indicating that the internal frame is iconified. */
 224     public final static String IS_ICON_PROPERTY = "icon";
 225 
 226     private static final Object PROPERTY_CHANGE_LISTENER_KEY =
 227         new StringBuilder("InternalFramePropertyChangeListener");
 228 
 229     private static void addPropertyChangeListenerIfNecessary() {
 230         if (AppContext.getAppContext().get(PROPERTY_CHANGE_LISTENER_KEY) ==
 231             null) {
 232             PropertyChangeListener focusListener =
 233                 new FocusPropertyChangeListener();
 234 
 235             AppContext.getAppContext().put(PROPERTY_CHANGE_LISTENER_KEY,
 236                 focusListener);
 237 
 238             KeyboardFocusManager.getCurrentKeyboardFocusManager().
 239                 addPropertyChangeListener(focusListener);
 240         }
 241     }
 242 
 243     private static class FocusPropertyChangeListener implements
 244         PropertyChangeListener {
 245         public void propertyChange(PropertyChangeEvent e) {
 246             if (e.getPropertyName() == "permanentFocusOwner") {
 247                 updateLastFocusOwner((Component)e.getNewValue());
 248             }
 249         }
 250     }
 251 
 252     private static void updateLastFocusOwner(Component component) {
 253         if (component != null) {
 254             Component parent = component;
 255             while (parent != null && !(parent instanceof Window)) {
 256                 if (parent instanceof JInternalFrame) {
 257                     // Update lastFocusOwner for parent.
 258                     ((JInternalFrame)parent).setLastFocusOwner(component);
 259                 }
 260                 parent = parent.getParent();
 261             }
 262         }
 263     }
 264 
 265     /**
 266      * Creates a non-resizable, non-closable, non-maximizable,
 267      * non-iconifiable <code>JInternalFrame</code> with no title.
 268      */
 269     public JInternalFrame() {
 270         this("", false, false, false, false);
 271     }
 272 
 273     /**
 274      * Creates a non-resizable, non-closable, non-maximizable,
 275      * non-iconifiable <code>JInternalFrame</code> with the specified title.
 276      * Note that passing in a <code>null</code> <code>title</code> results in
 277      * unspecified behavior and possibly an exception.
 278      *
 279      * @param title  the non-<code>null</code> <code>String</code>
 280      *     to display in the title bar
 281      */
 282     public JInternalFrame(String title) {
 283         this(title, false, false, false, false);
 284     }
 285 
 286     /**
 287      * Creates a non-closable, non-maximizable, non-iconifiable
 288      * <code>JInternalFrame</code> with the specified title
 289      * and resizability.
 290      *
 291      * @param title      the <code>String</code> to display in the title bar
 292      * @param resizable  if <code>true</code>, the internal frame can be resized
 293      */
 294     public JInternalFrame(String title, boolean resizable) {
 295         this(title, resizable, false, false, false);
 296     }
 297 
 298     /**
 299      * Creates a non-maximizable, non-iconifiable <code>JInternalFrame</code>
 300      * with the specified title, resizability, and
 301      * closability.
 302      *
 303      * @param title      the <code>String</code> to display in the title bar
 304      * @param resizable  if <code>true</code>, the internal frame can be resized
 305      * @param closable   if <code>true</code>, the internal frame can be closed
 306      */
 307     public JInternalFrame(String title, boolean resizable, boolean closable) {
 308         this(title, resizable, closable, false, false);
 309     }
 310 
 311     /**
 312      * Creates a non-iconifiable <code>JInternalFrame</code>
 313      * with the specified title,
 314      * resizability, closability, and maximizability.
 315      *
 316      * @param title       the <code>String</code> to display in the title bar
 317      * @param resizable   if <code>true</code>, the internal frame can be resized
 318      * @param closable    if <code>true</code>, the internal frame can be closed
 319      * @param maximizable if <code>true</code>, the internal frame can be maximized
 320      */
 321     public JInternalFrame(String title, boolean resizable, boolean closable,
 322                           boolean maximizable) {
 323         this(title, resizable, closable, maximizable, false);
 324     }
 325 
 326     /**
 327      * Creates a <code>JInternalFrame</code> with the specified title,
 328      * resizability, closability, maximizability, and iconifiability.
 329      * All <code>JInternalFrame</code> constructors use this one.
 330      *
 331      * @param title       the <code>String</code> to display in the title bar
 332      * @param resizable   if <code>true</code>, the internal frame can be resized
 333      * @param closable    if <code>true</code>, the internal frame can be closed
 334      * @param maximizable if <code>true</code>, the internal frame can be maximized
 335      * @param iconifiable if <code>true</code>, the internal frame can be iconified
 336      */
 337     public JInternalFrame(String title, boolean resizable, boolean closable,
 338                                 boolean maximizable, boolean iconifiable) {
 339 
 340         setRootPane(createRootPane());
 341         setLayout(new BorderLayout());
 342         this.title = title;
 343         this.resizable = resizable;
 344         this.closable = closable;
 345         this.maximizable = maximizable;
 346         isMaximum = false;
 347         this.iconable = iconifiable;
 348         isIcon = false;
 349         setVisible(false);
 350         setRootPaneCheckingEnabled(true);
 351         desktopIcon = new JDesktopIcon(this);
 352         updateUI();
 353         sun.awt.SunToolkit.checkAndSetPolicy(this);
 354         addPropertyChangeListenerIfNecessary();
 355     }
 356 
 357     /**
 358      * Called by the constructor to set up the <code>JRootPane</code>.
 359      * @return  a new <code>JRootPane</code>
 360      * @see JRootPane
 361      */
 362     protected JRootPane createRootPane() {
 363         return new JRootPane();
 364     }
 365 
 366     /**
 367      * Returns the look-and-feel object that renders this component.
 368      *
 369      * @return the <code>InternalFrameUI</code> object that renders
 370      *          this component
 371      */
 372     public InternalFrameUI getUI() {
 373         return (InternalFrameUI)ui;
 374     }
 375 
 376     /**
 377      * Sets the UI delegate for this <code>JInternalFrame</code>.
 378      * @param ui  the UI delegate
 379      */
 380     @BeanProperty(hidden = true, visualUpdate = true, description
 381             = "The UI object that implements the Component's LookAndFeel.")
 382     public void setUI(InternalFrameUI ui) {
 383         boolean checkingEnabled = isRootPaneCheckingEnabled();
 384         try {
 385             setRootPaneCheckingEnabled(false);
 386             super.setUI(ui);
 387         }
 388         finally {
 389             setRootPaneCheckingEnabled(checkingEnabled);
 390         }
 391     }
 392 
 393     /**
 394      * Notification from the <code>UIManager</code> that the look and feel
 395      * has changed.
 396      * Replaces the current UI object with the latest version from the
 397      * <code>UIManager</code>.
 398      *
 399      * @see JComponent#updateUI
 400      */
 401     public void updateUI() {
 402         setUI((InternalFrameUI)UIManager.getUI(this));
 403         invalidate();
 404         if (desktopIcon != null) {
 405             desktopIcon.updateUIWhenHidden();
 406         }
 407     }
 408 
 409     /* This method is called if <code>updateUI</code> was called
 410      * on the associated
 411      * JDesktopIcon.  It's necessary to avoid infinite recursion.
 412      */
 413     void updateUIWhenHidden() {
 414         setUI((InternalFrameUI)UIManager.getUI(this));
 415         invalidate();
 416         Component[] children = getComponents();
 417         if (children != null) {
 418             for (Component child : children) {
 419                 SwingUtilities.updateComponentTreeUI(child);
 420             }
 421         }
 422     }
 423 
 424 
 425     /**
 426      * Returns the name of the look-and-feel
 427      * class that renders this component.
 428      *
 429      * @return the string "InternalFrameUI"
 430      *
 431      * @see JComponent#getUIClassID
 432      * @see UIDefaults#getUI
 433      */
 434     @BeanProperty(bound = false, description
 435             = "UIClassID")
 436     public String getUIClassID() {
 437         return uiClassID;
 438     }
 439 
 440     /**
 441      * Returns whether calls to <code>add</code> and
 442      * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
 443      *
 444      * @return true if <code>add</code> and <code>setLayout</code>
 445      *         are forwarded; false otherwise
 446      *
 447      * @see #addImpl
 448      * @see #setLayout
 449      * @see #setRootPaneCheckingEnabled
 450      * @see javax.swing.RootPaneContainer
 451      */
 452     protected boolean isRootPaneCheckingEnabled() {
 453         return rootPaneCheckingEnabled;
 454     }
 455 
 456     /**
 457      * Sets whether calls to <code>add</code> and
 458      * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
 459      *
 460      * @param enabled  true if <code>add</code> and <code>setLayout</code>
 461      *        are forwarded, false if they should operate directly on the
 462      *        <code>JInternalFrame</code>.
 463      *
 464      * @see #addImpl
 465      * @see #setLayout
 466      * @see #isRootPaneCheckingEnabled
 467      * @see javax.swing.RootPaneContainer
 468      */
 469     @BeanProperty(hidden = true, description
 470             = "Whether the add and setLayout methods are forwarded")
 471     protected void setRootPaneCheckingEnabled(boolean enabled) {
 472         rootPaneCheckingEnabled = enabled;
 473     }
 474 
 475     /**
 476      * Adds the specified child <code>Component</code>.
 477      * This method is overridden to conditionally forward calls to the
 478      * <code>contentPane</code>.
 479      * By default, children are added to the <code>contentPane</code> instead
 480      * of the frame, refer to {@link javax.swing.RootPaneContainer} for
 481      * details.
 482      *
 483      * @param comp the component to be enhanced
 484      * @param constraints the constraints to be respected
 485      * @param index the index
 486      * @exception IllegalArgumentException if <code>index</code> is invalid
 487      * @exception IllegalArgumentException if adding the container's parent
 488      *                  to itself
 489      * @exception IllegalArgumentException if adding a window to a container
 490      *
 491      * @see #setRootPaneCheckingEnabled
 492      * @see javax.swing.RootPaneContainer
 493      */
 494     protected void addImpl(Component comp, Object constraints, int index) {
 495         if(isRootPaneCheckingEnabled()) {
 496             getContentPane().add(comp, constraints, index);
 497         }
 498         else {
 499             super.addImpl(comp, constraints, index);
 500         }
 501     }
 502 
 503     /**
 504      * Removes the specified component from the container. If
 505      * <code>comp</code> is not a child of the <code>JInternalFrame</code>
 506      * this will forward the call to the <code>contentPane</code>.
 507      *
 508      * @param comp the component to be removed
 509      * @throws NullPointerException if <code>comp</code> is null
 510      * @see #add
 511      * @see javax.swing.RootPaneContainer
 512      */
 513     public void remove(Component comp) {
 514         int oldCount = getComponentCount();
 515         super.remove(comp);
 516         if (oldCount == getComponentCount()) {
 517             getContentPane().remove(comp);
 518         }
 519     }
 520 
 521 
 522     /**
 523      * Ensures that, by default, the layout of this component cannot be set.
 524      * Overridden to conditionally forward the call to the
 525      * <code>contentPane</code>.
 526      * Refer to {@link javax.swing.RootPaneContainer} for
 527      * more information.
 528      *
 529      * @param manager the <code>LayoutManager</code>
 530      * @see #setRootPaneCheckingEnabled
 531      */
 532     public void setLayout(LayoutManager manager) {
 533         if(isRootPaneCheckingEnabled()) {
 534             getContentPane().setLayout(manager);
 535         }
 536         else {
 537             super.setLayout(manager);
 538         }
 539     }
 540 
 541 
 542 //////////////////////////////////////////////////////////////////////////
 543 /// Property Methods
 544 //////////////////////////////////////////////////////////////////////////
 545 
 546     /**
 547      * Returns the current <code>JMenuBar</code> for this
 548      * <code>JInternalFrame</code>, or <code>null</code>
 549      * if no menu bar has been set.
 550      * @return the current menu bar, or <code>null</code> if none has been set
 551      *
 552      * @deprecated As of Swing version 1.0.3,
 553      * replaced by <code>getJMenuBar()</code>.
 554      */
 555     @Deprecated
 556     public JMenuBar getMenuBar() {
 557       return getRootPane().getMenuBar();
 558     }
 559 
 560     /**
 561      * Returns the current <code>JMenuBar</code> for this
 562      * <code>JInternalFrame</code>, or <code>null</code>
 563      * if no menu bar has been set.
 564      *
 565      * @return  the <code>JMenuBar</code> used by this internal frame
 566      * @see #setJMenuBar
 567      */
 568     public JMenuBar getJMenuBar() {
 569         return getRootPane().getJMenuBar();
 570     }
 571 
 572     /**
 573      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
 574      *
 575      * @param m  the <code>JMenuBar</code> to use in this internal frame
 576      * @see #getJMenuBar
 577      * @deprecated As of Swing version 1.0.3
 578      *  replaced by <code>setJMenuBar(JMenuBar m)</code>.
 579      */
 580     @Deprecated
 581     public void setMenuBar(JMenuBar m) {
 582         JMenuBar oldValue = getMenuBar();
 583         getRootPane().setJMenuBar(m);
 584         firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
 585     }
 586 
 587     /**
 588      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
 589      *
 590      * @param m  the <code>JMenuBar</code> to use in this internal frame
 591      * @see #getJMenuBar
 592      */
 593     @BeanProperty(preferred = true, description
 594             = "The menu bar for accessing pulldown menus from this internal frame.")
 595     public void setJMenuBar(JMenuBar m){
 596         JMenuBar oldValue = getMenuBar();
 597         getRootPane().setJMenuBar(m);
 598         firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
 599     }
 600 
 601     // implements javax.swing.RootPaneContainer
 602     /**
 603      * Returns the content pane for this internal frame.
 604      * @return the content pane
 605      */
 606     public Container getContentPane() {
 607         return getRootPane().getContentPane();
 608     }
 609 
 610 
 611     /**
 612      * Sets this <code>JInternalFrame</code>'s <code>contentPane</code>
 613      * property.
 614      *
 615      * @param c  the content pane for this internal frame
 616      *
 617      * @exception java.awt.IllegalComponentStateException (a runtime
 618      *           exception) if the content pane parameter is <code>null</code>
 619      * @see RootPaneContainer#getContentPane
 620      */
 621     @BeanProperty(hidden = true, description
 622             = "The client area of the internal frame where child components are normally inserted.")
 623     public void setContentPane(Container c) {
 624         Container oldValue = getContentPane();
 625         getRootPane().setContentPane(c);
 626         firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c);
 627     }
 628 
 629     /**
 630      * Returns the layered pane for this internal frame.
 631      *
 632      * @return a <code>JLayeredPane</code> object
 633      * @see RootPaneContainer#setLayeredPane
 634      * @see RootPaneContainer#getLayeredPane
 635      */
 636     public JLayeredPane getLayeredPane() {
 637         return getRootPane().getLayeredPane();
 638     }
 639 
 640     /**
 641      * Sets this <code>JInternalFrame</code>'s
 642      * <code>layeredPane</code> property.
 643      *
 644      * @param layered the <code>JLayeredPane</code> for this internal frame
 645      *
 646      * @exception java.awt.IllegalComponentStateException (a runtime
 647      *           exception) if the layered pane parameter is <code>null</code>
 648      * @see RootPaneContainer#setLayeredPane
 649      */
 650     @BeanProperty(hidden = true, description
 651             = "The pane which holds the various desktop layers.")
 652     public void setLayeredPane(JLayeredPane layered) {
 653         JLayeredPane oldValue = getLayeredPane();
 654         getRootPane().setLayeredPane(layered);
 655         firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered);
 656     }
 657 
 658     /**
 659      * Returns the glass pane for this internal frame.
 660      *
 661      * @return the glass pane
 662      * @see RootPaneContainer#setGlassPane
 663      */
 664     public Component getGlassPane() {
 665         return getRootPane().getGlassPane();
 666     }
 667 
 668     /**
 669      * Sets this <code>JInternalFrame</code>'s
 670      * <code>glassPane</code> property.
 671      *
 672      * @param glass the glass pane for this internal frame
 673      * @see RootPaneContainer#getGlassPane
 674      */
 675     @BeanProperty(hidden = true, description
 676             = "A transparent pane used for menu rendering.")
 677     public void setGlassPane(Component glass) {
 678         Component oldValue = getGlassPane();
 679         getRootPane().setGlassPane(glass);
 680         firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass);
 681     }
 682 
 683     /**
 684      * Returns the <code>rootPane</code> object for this internal frame.
 685      *
 686      * @return the <code>rootPane</code> property
 687      * @see RootPaneContainer#getRootPane
 688      */
 689     @BeanProperty(hidden = true, description
 690             = "The root pane used by this internal frame.")
 691     public JRootPane getRootPane() {
 692         return rootPane;
 693     }
 694 
 695 
 696     /**
 697      * Sets the <code>rootPane</code> property
 698      * for this <code>JInternalFrame</code>.
 699      * This method is called by the constructor.
 700      *
 701      * @param root  the new <code>JRootPane</code> object
 702      */
 703     protected void setRootPane(JRootPane root) {
 704         if(rootPane != null) {
 705             remove(rootPane);
 706         }
 707         JRootPane oldValue = getRootPane();
 708         rootPane = root;
 709         if(rootPane != null) {
 710             boolean checkingEnabled = isRootPaneCheckingEnabled();
 711             try {
 712                 setRootPaneCheckingEnabled(false);
 713                 add(rootPane, BorderLayout.CENTER);
 714             }
 715             finally {
 716                 setRootPaneCheckingEnabled(checkingEnabled);
 717             }
 718         }
 719         firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root);
 720     }
 721 
 722     /**
 723      * Sets whether this <code>JInternalFrame</code> can be closed by
 724      * some user action.
 725      * @param b a boolean value, where <code>true</code> means this internal frame can be closed
 726      */
 727     @BeanProperty(preferred = true, description
 728             = "Indicates whether this internal frame can be closed.")
 729     public void setClosable(boolean b) {
 730         Boolean oldValue = closable ? Boolean.TRUE : Boolean.FALSE;
 731         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 732         closable = b;
 733         firePropertyChange("closable", oldValue, newValue);
 734     }
 735 
 736     /**
 737      * Returns whether this <code>JInternalFrame</code> can be closed by
 738      * some user action.
 739      * @return <code>true</code> if this internal frame can be closed
 740      */
 741     public boolean isClosable() {
 742         return closable;
 743     }
 744 
 745     /**
 746      * Returns whether this <code>JInternalFrame</code> is currently closed.
 747      * @return <code>true</code> if this internal frame is closed, <code>false</code> otherwise
 748      */
 749     public boolean isClosed() {
 750         return isClosed;
 751     }
 752 
 753     /**
 754      * Closes this internal frame if the argument is <code>true</code>.
 755      * Do not invoke this method with a <code>false</code> argument;
 756      * the result of invoking <code>setClosed(false)</code>
 757      * is unspecified.
 758      *
 759      * <p>
 760      *
 761      * If the internal frame is already closed,
 762      * this method does nothing and returns immediately.
 763      * Otherwise,
 764      * this method begins by firing
 765      * an <code>INTERNAL_FRAME_CLOSING</code> event.
 766      * Then this method sets the <code>closed</code> property to <code>true</code>
 767      * unless a listener vetoes the property change.
 768      * This method finishes by making the internal frame
 769      * invisible and unselected,
 770      * and then firing an <code>INTERNAL_FRAME_CLOSED</code> event.
 771      *
 772      * <p>
 773      *
 774      * <b>Note:</b>
 775      * To reuse an internal frame that has been closed,
 776      * you must add it to a container
 777      * (even if you never removed it from its previous container).
 778      * Typically, this container will be the <code>JDesktopPane</code>
 779      * that previously contained the internal frame.
 780      *
 781      * @param b must be <code>true</code>
 782      *
 783      * @exception PropertyVetoException when the attempt to set the
 784      *            property is vetoed by the <code>JInternalFrame</code>
 785      *
 786      * @see #isClosed()
 787      * @see #setDefaultCloseOperation
 788      * @see #dispose
 789      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
 790      */
 791     @BeanProperty(description
 792             = "Indicates whether this internal frame has been closed.")
 793     public void setClosed(boolean b) throws PropertyVetoException {
 794         if (isClosed == b) {
 795             return;
 796         }
 797 
 798         Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE;
 799         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 800         if (b) {
 801           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
 802         }
 803         fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue);
 804         isClosed = b;
 805         if (isClosed) {
 806           setVisible(false);
 807         }
 808         firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue);
 809         if (isClosed) {
 810           dispose();
 811         } else if (!opened) {
 812           /* this bogus -- we haven't defined what
 813              setClosed(false) means. */
 814           //        fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
 815           //            opened = true;
 816         }
 817     }
 818 
 819     /**
 820      * Sets whether the <code>JInternalFrame</code> can be resized by some
 821      * user action.
 822      *
 823      * @param b  a boolean, where <code>true</code> means this internal frame can be resized
 824      */
 825     @BeanProperty(preferred = true, description
 826             = "Determines whether this internal frame can be resized by the user.")
 827     public void setResizable(boolean b) {
 828         Boolean oldValue = resizable ? Boolean.TRUE : Boolean.FALSE;
 829         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 830         resizable = b;
 831         firePropertyChange("resizable", oldValue, newValue);
 832     }
 833 
 834     /**
 835      * Returns whether the <code>JInternalFrame</code> can be resized
 836      * by some user action.
 837      *
 838      * @return <code>true</code> if this internal frame can be resized, <code>false</code> otherwise
 839      */
 840     public boolean isResizable() {
 841         // don't allow resizing when maximized.
 842         return isMaximum ? false : resizable;
 843     }
 844 
 845     /**
 846      * Sets the <code>iconable</code> property,
 847      * which must be <code>true</code>
 848      * for the user to be able to
 849      * make the <code>JInternalFrame</code> an icon.
 850      * Some look and feels might not implement iconification;
 851      * they will ignore this property.
 852      *
 853      * @param b  a boolean, where <code>true</code> means this internal frame can be iconified
 854      */
 855     @BeanProperty(preferred = true, description
 856             = "Determines whether this internal frame can be iconified.")
 857     public void setIconifiable(boolean b) {
 858         Boolean oldValue = iconable ? Boolean.TRUE : Boolean.FALSE;
 859         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 860         iconable = b;
 861         firePropertyChange("iconable", oldValue, newValue);
 862     }
 863 
 864     /**
 865      * Gets the <code>iconable</code> property,
 866      * which by default is <code>false</code>.
 867      *
 868      * @return the value of the <code>iconable</code> property.
 869      *
 870      * @see #setIconifiable
 871      */
 872     public boolean isIconifiable() {
 873         return iconable;
 874     }
 875 
 876     /**
 877      * Returns whether the <code>JInternalFrame</code> is currently iconified.
 878      *
 879      * @return <code>true</code> if this internal frame is iconified
 880      */
 881     public boolean isIcon() {
 882         return isIcon;
 883     }
 884 
 885     /**
 886      * Iconifies or de-iconifies this internal frame,
 887      * if the look and feel supports iconification.
 888      * If the internal frame's state changes to iconified,
 889      * this method fires an <code>INTERNAL_FRAME_ICONIFIED</code> event.
 890      * If the state changes to de-iconified,
 891      * an <code>INTERNAL_FRAME_DEICONIFIED</code> event is fired.
 892      *
 893      * @param b a boolean, where <code>true</code> means to iconify this internal frame and
 894      *          <code>false</code> means to de-iconify it
 895      * @exception PropertyVetoException when the attempt to set the
 896      *            property is vetoed by the <code>JInternalFrame</code>
 897      *
 898      * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED
 899      * @see InternalFrameEvent#INTERNAL_FRAME_DEICONIFIED
 900      */
 901     @BeanProperty(description
 902             = "The image displayed when this internal frame is minimized.")
 903     public void setIcon(boolean b) throws PropertyVetoException {
 904         if (isIcon == b) {
 905             return;
 906         }
 907 
 908         /* If an internal frame is being iconified before it has a
 909            parent, (e.g., client wants it to start iconic), create the
 910            parent if possible so that we can place the icon in its
 911            proper place on the desktop. I am not sure the call to
 912            validate() is necessary, since we are not going to display
 913            this frame yet */
 914         firePropertyChange("ancestor", null, getParent());
 915 
 916         Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE;
 917         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 918         fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue);
 919         isIcon = b;
 920         firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue);
 921         if (b)
 922           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED);
 923         else
 924           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
 925     }
 926 
 927     /**
 928      * Sets the <code>maximizable</code> property,
 929      * which determines whether the <code>JInternalFrame</code>
 930      * can be maximized by
 931      * some user action.
 932      * Some look and feels might not support maximizing internal frames;
 933      * they will ignore this property.
 934      *
 935      * @param b <code>true</code> to specify that this internal frame should be maximizable; <code>false</code> to specify that it should not be
 936      */
 937     @BeanProperty(preferred = true, description
 938             = "Determines whether this internal frame can be maximized.")
 939     public void setMaximizable(boolean b) {
 940         Boolean oldValue = maximizable ? Boolean.TRUE : Boolean.FALSE;
 941         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 942         maximizable = b;
 943         firePropertyChange("maximizable", oldValue, newValue);
 944     }
 945 
 946     /**
 947      * Gets the value of the <code>maximizable</code> property.
 948      *
 949      * @return the value of the <code>maximizable</code> property
 950      * @see #setMaximizable
 951      */
 952     public boolean isMaximizable() {
 953         return maximizable;
 954     }
 955 
 956     /**
 957      * Returns whether the <code>JInternalFrame</code> is currently maximized.
 958      *
 959      * @return <code>true</code> if this internal frame is maximized, <code>false</code> otherwise
 960      */
 961     public boolean isMaximum() {
 962         return isMaximum;
 963     }
 964 
 965     /**
 966      * Maximizes and restores this internal frame.  A maximized frame is resized to
 967      * fully fit the <code>JDesktopPane</code> area associated with the
 968      * <code>JInternalFrame</code>.
 969      * A restored frame's size is set to the <code>JInternalFrame</code>'s
 970      * actual size.
 971      *
 972      * @param b  a boolean, where <code>true</code> maximizes this internal frame and <code>false</code>
 973      *           restores it
 974      * @exception PropertyVetoException when the attempt to set the
 975      *            property is vetoed by the <code>JInternalFrame</code>
 976      */
 977     @BeanProperty(description
 978             = "Indicates whether this internal frame is maximized.")
 979     public void setMaximum(boolean b) throws PropertyVetoException {
 980         if (isMaximum == b) {
 981             return;
 982         }
 983 
 984         Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE;
 985         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
 986         fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
 987         /* setting isMaximum above the event firing means that
 988            property listeners that, for some reason, test it will
 989            get it wrong... See, for example, getNormalBounds() */
 990         isMaximum = b;
 991         firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
 992     }
 993 
 994     /**
 995      * Returns the title of the <code>JInternalFrame</code>.
 996      *
 997      * @return a <code>String</code> containing this internal frame's title
 998      * @see #setTitle
 999      */
1000     public String getTitle() {
1001         return title;
1002     }
1003 
1004     /**
1005      * Sets the <code>JInternalFrame</code> title. <code>title</code>
1006      * may have a <code>null</code> value.
1007      * @see #getTitle
1008      *
1009      * @param title  the <code>String</code> to display in the title bar
1010      */
1011     @BeanProperty(preferred = true, description
1012             = "The text displayed in the title bar.")
1013     public void setTitle(String title) {
1014         String oldValue = this.title;
1015         this.title = title;
1016         firePropertyChange(TITLE_PROPERTY, oldValue, title);
1017     }
1018 
1019     /**
1020      * Selects or deselects the internal frame
1021      * if it's showing.
1022      * A <code>JInternalFrame</code> normally draws its title bar
1023      * differently if it is
1024      * the selected frame, which indicates to the user that this
1025      * internal frame has the focus.
1026      * When this method changes the state of the internal frame
1027      * from deselected to selected, it fires an
1028      * <code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> event.
1029      * If the change is from selected to deselected,
1030      * an <code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> event
1031      * is fired.
1032      *
1033      * @param selected  a boolean, where <code>true</code> means this internal frame
1034      *                  should become selected (currently active)
1035      *                  and <code>false</code> means it should become deselected
1036      * @exception PropertyVetoException when the attempt to set the
1037      *            property is vetoed by the <code>JInternalFrame</code>
1038      *
1039      * @see #isShowing
1040      * @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED
1041      * @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED
1042      */
1043     @BeanProperty(description
1044             = "Indicates whether this internal frame is currently the active frame.")
1045     public void setSelected(boolean selected) throws PropertyVetoException {
1046        // The InternalFrame may already be selected, but the focus
1047        // may be outside it, so restore the focus to the subcomponent
1048        // which previously had it. See Bug 4302764.
1049         if (selected && isSelected) {
1050             restoreSubcomponentFocus();
1051             return;
1052         }
1053         // The internal frame or the desktop icon must be showing to allow
1054         // selection.  We may deselect even if neither is showing.
1055         if ((isSelected == selected) || (selected &&
1056             (isIcon ? !desktopIcon.isShowing() : !isShowing()))) {
1057             return;
1058         }
1059 
1060         Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE;
1061         Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE;
1062         fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1063 
1064         /* We don't want to leave focus in the previously selected
1065            frame, so we have to set it to *something* in case it
1066            doesn't get set in some other way (as if a user clicked on
1067            a component that doesn't request focus).  If this call is
1068            happening because the user clicked on a component that will
1069            want focus, then it will get transfered there later.
1070 
1071            We test for parent.isShowing() above, because AWT throws a
1072            NPE if you try to request focus on a lightweight before its
1073            parent has been made visible */
1074 
1075         if (selected) {
1076             restoreSubcomponentFocus();
1077         }
1078 
1079         isSelected = selected;
1080         firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1081         if (isSelected)
1082           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED);
1083         else
1084           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
1085         repaint();
1086     }
1087 
1088     /**
1089      * Returns whether the <code>JInternalFrame</code> is the
1090      * currently "selected" or active frame.
1091      *
1092      * @return <code>true</code> if this internal frame is currently selected (active)
1093      * @see #setSelected
1094      */
1095     public boolean isSelected() {
1096         return isSelected;
1097     }
1098 
1099     /**
1100      * Sets an image to be displayed in the titlebar of this internal frame (usually
1101      * in the top-left corner).
1102      * This image is not the <code>desktopIcon</code> object, which
1103      * is the image displayed in the <code>JDesktop</code> when
1104      * this internal frame is iconified.
1105      *
1106      * Passing <code>null</code> to this function is valid,
1107      * but the look and feel
1108      * can choose the
1109      * appropriate behavior for that situation, such as displaying no icon
1110      * or a default icon for the look and feel.
1111      *
1112      * @param icon the <code>Icon</code> to display in the title bar
1113      * @see #getFrameIcon
1114      */
1115     @BeanProperty(description
1116             = "The icon shown in the top-left corner of this internal frame.")
1117   public void setFrameIcon(Icon icon) {
1118         Icon oldIcon = frameIcon;
1119         frameIcon = icon;
1120         firePropertyChange(FRAME_ICON_PROPERTY, oldIcon, icon);
1121     }
1122 
1123     /**
1124      * Returns the image displayed in the title bar of this internal frame (usually
1125      * in the top-left corner).
1126      *
1127      * @return the <code>Icon</code> displayed in the title bar
1128      * @see #setFrameIcon
1129      */
1130     public Icon getFrameIcon()  {
1131         return frameIcon;
1132     }
1133 
1134     /**
1135       * Convenience method that moves this component to position 0 if its
1136       * parent is a <code>JLayeredPane</code>.
1137       */
1138     public void moveToFront() {
1139         if (isIcon()) {
1140             if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1141                 ((JLayeredPane)getDesktopIcon().getParent()).
1142                     moveToFront(getDesktopIcon());
1143             }
1144         }
1145         else if (getParent() instanceof JLayeredPane) {
1146             ((JLayeredPane)getParent()).moveToFront(this);
1147         }
1148     }
1149 
1150     /**
1151       * Convenience method that moves this component to position -1 if its
1152       * parent is a <code>JLayeredPane</code>.
1153       */
1154     public void moveToBack() {
1155         if (isIcon()) {
1156             if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1157                 ((JLayeredPane)getDesktopIcon().getParent()).
1158                     moveToBack(getDesktopIcon());
1159             }
1160         }
1161         else if (getParent() instanceof JLayeredPane) {
1162             ((JLayeredPane)getParent()).moveToBack(this);
1163         }
1164     }
1165 
1166     /**
1167      * Returns the last <code>Cursor</code> that was set by the
1168      * <code>setCursor</code> method that is not a resizable
1169      * <code>Cursor</code>.
1170      *
1171      * @return the last non-resizable <code>Cursor</code>
1172      * @since 1.6
1173      */
1174     @BeanProperty(bound = false)
1175     public Cursor getLastCursor() {
1176         return lastCursor;
1177     }
1178 
1179     /**
1180      * {@inheritDoc}
1181      * @since 1.6
1182      */
1183     public void setCursor(Cursor cursor) {
1184         if (cursor == null) {
1185             lastCursor = null;
1186             super.setCursor(cursor);
1187             return;
1188         }
1189         int type = cursor.getType();
1190         if (!(type == Cursor.SW_RESIZE_CURSOR  ||
1191               type == Cursor.SE_RESIZE_CURSOR  ||
1192               type == Cursor.NW_RESIZE_CURSOR  ||
1193               type == Cursor.NE_RESIZE_CURSOR  ||
1194               type == Cursor.N_RESIZE_CURSOR   ||
1195               type == Cursor.S_RESIZE_CURSOR   ||
1196               type == Cursor.W_RESIZE_CURSOR   ||
1197               type == Cursor.E_RESIZE_CURSOR)) {
1198             lastCursor = cursor;
1199         }
1200         super.setCursor(cursor);
1201     }
1202 
1203     /**
1204      * Convenience method for setting the layer attribute of this component.
1205      *
1206      * @param layer  an <code>Integer</code> object specifying this
1207      *          frame's desktop layer
1208      * @see JLayeredPane
1209      */
1210     @BeanProperty(bound = false, expert = true, description
1211             = "Specifies what desktop layer is used.")
1212     public void setLayer(Integer layer) {
1213         if(getParent() != null && getParent() instanceof JLayeredPane) {
1214             // Normally we want to do this, as it causes the LayeredPane
1215             // to draw properly.
1216             JLayeredPane p = (JLayeredPane)getParent();
1217             p.setLayer(this, layer.intValue(), p.getPosition(this));
1218         } else {
1219              // Try to do the right thing
1220              JLayeredPane.putLayer(this, layer.intValue());
1221              if(getParent() != null)
1222                  getParent().repaint(getX(), getY(), getWidth(), getHeight());
1223         }
1224     }
1225 
1226     /**
1227      * Convenience method for setting the layer attribute of this component.
1228      * The method <code>setLayer(Integer)</code> should be used for
1229      * layer values predefined in <code>JLayeredPane</code>.
1230      * When using <code>setLayer(int)</code>, care must be taken not to
1231      * accidentally clash with those values.
1232      *
1233      * @param layer  an integer specifying this internal frame's desktop layer
1234      *
1235      * @since 1.3
1236      *
1237      * @see #setLayer(Integer)
1238      * @see JLayeredPane
1239      */
1240     @BeanProperty(bound = false, expert = true, description
1241             = "Specifies what desktop layer is used.")
1242     public void setLayer(int layer) {
1243       this.setLayer(Integer.valueOf(layer));
1244     }
1245 
1246     /**
1247      * Convenience method for getting the layer attribute of this component.
1248      *
1249      * @return  an <code>Integer</code> object specifying this
1250      *          frame's desktop layer
1251      * @see JLayeredPane
1252       */
1253     public int getLayer() {
1254         return JLayeredPane.getLayer(this);
1255     }
1256 
1257     /**
1258       * Convenience method that searches the ancestor hierarchy for a
1259       * <code>JDesktop</code> instance. If <code>JInternalFrame</code>
1260       * finds none, the <code>desktopIcon</code> tree is searched.
1261       *
1262       * @return the <code>JDesktopPane</code> this internal frame belongs to,
1263       *         or <code>null</code> if none is found
1264       */
1265     @BeanProperty(bound = false)
1266     public JDesktopPane getDesktopPane() {
1267         Container p;
1268 
1269         // Search upward for desktop
1270         p = getParent();
1271         while(p != null && !(p instanceof JDesktopPane))
1272             p = p.getParent();
1273 
1274         if(p == null) {
1275            // search its icon parent for desktop
1276            p = getDesktopIcon().getParent();
1277            while(p != null && !(p instanceof JDesktopPane))
1278                 p = p.getParent();
1279         }
1280 
1281         return (JDesktopPane)p;
1282     }
1283 
1284     /**
1285      * Sets the <code>JDesktopIcon</code> associated with this
1286      * <code>JInternalFrame</code>.
1287      *
1288      * @param d the <code>JDesktopIcon</code> to display on the desktop
1289      * @see #getDesktopIcon
1290      */
1291     @BeanProperty(description
1292             = "The icon shown when this internal frame is minimized.")
1293     public void setDesktopIcon(JDesktopIcon d) {
1294         JDesktopIcon oldValue = getDesktopIcon();
1295         desktopIcon = d;
1296         firePropertyChange("desktopIcon", oldValue, d);
1297     }
1298 
1299     /**
1300      * Returns the <code>JDesktopIcon</code> used when this
1301      * <code>JInternalFrame</code> is iconified.
1302      *
1303      * @return the <code>JDesktopIcon</code> displayed on the desktop
1304      * @see #setDesktopIcon
1305      */
1306     public JDesktopIcon getDesktopIcon() {
1307         return desktopIcon;
1308     }
1309 
1310     /**
1311      * If the <code>JInternalFrame</code> is not in maximized state, returns
1312      * <code>getBounds()</code>; otherwise, returns the bounds that the
1313      * <code>JInternalFrame</code> would be restored to.
1314      *
1315      * @return a <code>Rectangle</code> containing the bounds of this
1316      *          frame when in the normal state
1317      * @since 1.3
1318      */
1319     public Rectangle getNormalBounds() {
1320 
1321       /* we used to test (!isMaximum) here, but since this
1322          method is used by the property listener for the
1323          IS_MAXIMUM_PROPERTY, it ended up getting the wrong
1324          answer... Since normalBounds get set to null when the
1325          frame is restored, this should work better */
1326 
1327       if (normalBounds != null) {
1328         return normalBounds;
1329       } else {
1330         return getBounds();
1331       }
1332     }
1333 
1334     /**
1335      * Sets the normal bounds for this internal frame, the bounds that
1336      * this internal frame would be restored to from its maximized state.
1337      * This method is intended for use only by desktop managers.
1338      *
1339      * @param r the bounds that this internal frame should be restored to
1340      * @since 1.3
1341      */
1342     public void setNormalBounds(Rectangle r) {
1343         normalBounds = r;
1344     }
1345 
1346     /**
1347      * If this <code>JInternalFrame</code> is active,
1348      * returns the child that has focus.
1349      * Otherwise, returns <code>null</code>.
1350      *
1351      * @return the component with focus, or <code>null</code> if no children have focus
1352      * @since 1.3
1353      */
1354     public Component getFocusOwner() {
1355         if (isSelected()) {
1356             return lastFocusOwner;
1357         }
1358         return null;
1359     }
1360 
1361     /**
1362      * Returns the child component of this <code>JInternalFrame</code>
1363      * that will receive the
1364      * focus when this <code>JInternalFrame</code> is selected.
1365      * If this <code>JInternalFrame</code> is
1366      * currently selected, this method returns the same component as
1367      * the <code>getFocusOwner</code> method.
1368      * If this <code>JInternalFrame</code> is not selected,
1369      * then the child component that most recently requested focus will be
1370      * returned. If no child component has ever requested focus, then this
1371      * <code>JInternalFrame</code>'s initial focusable component is returned.
1372      * If no such
1373      * child exists, then this <code>JInternalFrame</code>'s default component
1374      * to focus is returned.
1375      *
1376      * @return the child component that will receive focus when this
1377      *         <code>JInternalFrame</code> is selected
1378      * @see #getFocusOwner
1379      * @see #isSelected
1380      * @since 1.4
1381      */
1382     @BeanProperty(bound = false)
1383     public Component getMostRecentFocusOwner() {
1384         if (isSelected()) {
1385             return getFocusOwner();
1386         }
1387 
1388         if (lastFocusOwner != null) {
1389             return lastFocusOwner;
1390         }
1391 
1392         FocusTraversalPolicy policy = getFocusTraversalPolicy();
1393         if (policy instanceof InternalFrameFocusTraversalPolicy) {
1394             return ((InternalFrameFocusTraversalPolicy)policy).
1395                 getInitialComponent(this);
1396         }
1397 
1398         Component toFocus = policy.getDefaultComponent(this);
1399         if (toFocus != null) {
1400             return toFocus;
1401         }
1402         return getContentPane();
1403     }
1404 
1405     /**
1406      * Requests the internal frame to restore focus to the
1407      * last subcomponent that had focus. This is used by the UI when
1408      * the user selected this internal frame --
1409      * for example, by clicking on the title bar.
1410      *
1411      * @since 1.3
1412      */
1413     public void restoreSubcomponentFocus() {
1414         if (isIcon()) {
1415             SwingUtilities2.compositeRequestFocus(getDesktopIcon());
1416         }
1417         else {
1418             Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
1419             if ((component == null) || !SwingUtilities.isDescendingFrom(component, this)) {
1420                 // FocusPropertyChangeListener will eventually update
1421                 // lastFocusOwner. As focus requests are asynchronous
1422                 // lastFocusOwner may be accessed before it has been correctly
1423                 // updated. To avoid any problems, lastFocusOwner is immediately
1424                 // set, assuming the request will succeed.
1425                 setLastFocusOwner(getMostRecentFocusOwner());
1426                 if (lastFocusOwner == null) {
1427                     // Make sure focus is restored somewhere, so that
1428                     // we don't leave a focused component in another frame while
1429                     // this frame is selected.
1430                     setLastFocusOwner(getContentPane());
1431                 }
1432                 lastFocusOwner.requestFocus();
1433             }
1434         }
1435     }
1436 
1437     private void setLastFocusOwner(Component component) {
1438         lastFocusOwner = component;
1439     }
1440 
1441     /**
1442      * Moves and resizes this component.  Unlike other components,
1443      * this implementation also forces re-layout, so that frame
1444      * decorations such as the title bar are always redisplayed.
1445      *
1446      * @param x  an integer giving the component's new horizontal position
1447      *           measured in pixels from the left of its container
1448      * @param y  an integer giving the component's new vertical position,
1449      *           measured in pixels from the bottom of its container
1450      * @param width  an integer giving the component's new width in pixels
1451      * @param height an integer giving the component's new height in pixels
1452      */
1453     public void reshape(int x, int y, int width, int height) {
1454         super.reshape(x, y, width, height);
1455         validate();
1456         repaint();
1457     }
1458 
1459 ///////////////////////////
1460 // Frame/Window equivalents
1461 ///////////////////////////
1462 
1463     /**
1464      * Adds the specified listener to receive internal
1465      * frame events from this internal frame.
1466      *
1467      * @param l the internal frame listener
1468      */
1469     public void addInternalFrameListener(InternalFrameListener l) {  // remind: sync ??
1470       listenerList.add(InternalFrameListener.class, l);
1471       // remind: needed?
1472       enableEvents(0);   // turn on the newEventsOnly flag in Component.
1473     }
1474 
1475     /**
1476      * Removes the specified internal frame listener so that it no longer
1477      * receives internal frame events from this internal frame.
1478      *
1479      * @param l the internal frame listener
1480      */
1481     public void removeInternalFrameListener(InternalFrameListener l) {  // remind: sync??
1482       listenerList.remove(InternalFrameListener.class, l);
1483     }
1484 
1485     /**
1486      * Returns an array of all the <code>InternalFrameListener</code>s added
1487      * to this <code>JInternalFrame</code> with
1488      * <code>addInternalFrameListener</code>.
1489      *
1490      * @return all of the <code>InternalFrameListener</code>s added or an empty
1491      *         array if no listeners have been added
1492      * @since 1.4
1493      *
1494      * @see #addInternalFrameListener
1495      */
1496     @BeanProperty(bound = false)
1497     public InternalFrameListener[] getInternalFrameListeners() {
1498         return listenerList.getListeners(InternalFrameListener.class);
1499     }
1500 
1501     // remind: name ok? all one method ok? need to be synchronized?
1502     /**
1503      * Fires an internal frame event.
1504      *
1505      * @param id  the type of the event being fired; one of the following:
1506      * <ul>
1507      * <li><code>InternalFrameEvent.INTERNAL_FRAME_OPENED</code>
1508      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSING</code>
1509      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSED</code>
1510      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ICONIFIED</code>
1511      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED</code>
1512      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code>
1513      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code>
1514      * </ul>
1515      * If the event type is not one of the above, nothing happens.
1516      */
1517     protected void fireInternalFrameEvent(int id){
1518       Object[] listeners = listenerList.getListenerList();
1519       InternalFrameEvent e = null;
1520       for (int i = listeners.length -2; i >=0; i -= 2){
1521         if (listeners[i] == InternalFrameListener.class){
1522           if (e == null){
1523             e = new InternalFrameEvent(this, id);
1524             //      System.out.println("InternalFrameEvent: " + e.paramString());
1525           }
1526           switch(e.getID()) {
1527           case InternalFrameEvent.INTERNAL_FRAME_OPENED:
1528             ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e);
1529             break;
1530           case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
1531             ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e);
1532             break;
1533           case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
1534             ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e);
1535             break;
1536           case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
1537             ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e);
1538             break;
1539           case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
1540             ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e);
1541             break;
1542           case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
1543             ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e);
1544             break;
1545           case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
1546             ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e);
1547             break;
1548           default:
1549             break;
1550           }
1551         }
1552       }
1553       /* we could do it off the event, but at the moment, that's not how
1554          I'm implementing it */
1555       //      if (id == InternalFrameEvent.INTERNAL_FRAME_CLOSING) {
1556       //          doDefaultCloseAction();
1557       //      }
1558     }
1559 
1560     /**
1561      * Fires an
1562      * <code>INTERNAL_FRAME_CLOSING</code> event
1563      * and then performs the action specified by
1564      * the internal frame's default close operation.
1565      * This method is typically invoked by the
1566      * look-and-feel-implemented action handler
1567      * for the internal frame's close button.
1568      *
1569      * @since 1.3
1570      * @see #setDefaultCloseOperation
1571      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
1572      */
1573     public void doDefaultCloseAction() {
1574         fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
1575         switch(defaultCloseOperation) {
1576           case DO_NOTHING_ON_CLOSE:
1577             break;
1578           case HIDE_ON_CLOSE:
1579             setVisible(false);
1580             if (isSelected())
1581                 try {
1582                     setSelected(false);
1583                 } catch (PropertyVetoException pve) {}
1584 
1585             /* should this activate the next frame? that's really
1586                desktopmanager's policy... */
1587             break;
1588           case DISPOSE_ON_CLOSE:
1589               try {
1590                 fireVetoableChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1591                                    Boolean.TRUE);
1592                 isClosed = true;
1593                 setVisible(false);
1594                 firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1595                                    Boolean.TRUE);
1596                 dispose();
1597               } catch (PropertyVetoException pve) {}
1598               break;
1599           default:
1600               break;
1601         }
1602     }
1603 
1604     /**
1605      * Sets the operation that will happen by default when
1606      * the user initiates a "close" on this internal frame.
1607      * The possible choices are:
1608      * <br><br>
1609      * <dl>
1610      * <dt><code>DO_NOTHING_ON_CLOSE</code>
1611      * <dd> Do nothing.
1612      *      This requires the program to handle the operation
1613      *      in the <code>windowClosing</code> method
1614      *      of a registered <code>InternalFrameListener</code> object.
1615      * <dt><code>HIDE_ON_CLOSE</code>
1616      * <dd> Automatically make the internal frame invisible.
1617      * <dt><code>DISPOSE_ON_CLOSE</code>
1618      * <dd> Automatically dispose of the internal frame.
1619      * </dl>
1620      * <p>
1621      * The default value is <code>DISPOSE_ON_CLOSE</code>.
1622      * Before performing the specified close operation,
1623      * the internal frame fires
1624      * an <code>INTERNAL_FRAME_CLOSING</code> event.
1625      *
1626      * @param operation one of the following constants defined in
1627      *                  <code>javax.swing.WindowConstants</code>
1628      *                  (an interface implemented by
1629      *                  <code>JInternalFrame</code>):
1630      *                  <code>DO_NOTHING_ON_CLOSE</code>,
1631      *                  <code>HIDE_ON_CLOSE</code>, or
1632      *                  <code>DISPOSE_ON_CLOSE</code>
1633      *
1634      * @see #addInternalFrameListener
1635      * @see #getDefaultCloseOperation
1636      * @see #setVisible
1637      * @see #dispose
1638      * @see InternalFrameEvent#INTERNAL_FRAME_CLOSING
1639      */
1640     public void setDefaultCloseOperation(int operation) {
1641         this.defaultCloseOperation = operation;
1642     }
1643 
1644    /**
1645     * Returns the default operation that occurs when the user
1646     * initiates a "close" on this internal frame.
1647     * @return the operation that will occur when the user closes the internal
1648     *         frame
1649     * @see #setDefaultCloseOperation
1650     */
1651     public int getDefaultCloseOperation() {
1652         return defaultCloseOperation;
1653     }
1654 
1655     /**
1656      * Causes subcomponents of this <code>JInternalFrame</code>
1657      * to be laid out at their preferred size.  Internal frames that are
1658      * iconized or maximized are first restored and then packed.  If the
1659      * internal frame is unable to be restored its state is not changed
1660      * and will not be packed.
1661      *
1662      * @see       java.awt.Window#pack
1663      */
1664     public void pack() {
1665         try {
1666             if (isIcon()) {
1667                 setIcon(false);
1668             } else if (isMaximum()) {
1669                 setMaximum(false);
1670             }
1671         } catch(PropertyVetoException e) {
1672             return;
1673         }
1674         setSize(getPreferredSize());
1675         validate();
1676     }
1677 
1678     /**
1679      * If the internal frame is not visible,
1680      * brings the internal frame to the front,
1681      * makes it visible,
1682      * and attempts to select it.
1683      * The first time the internal frame is made visible,
1684      * this method also fires an <code>INTERNAL_FRAME_OPENED</code> event.
1685      * This method does nothing if the internal frame is already visible.
1686      * Invoking this method
1687      * has the same result as invoking
1688      * <code>setVisible(true)</code>.
1689      *
1690      * @see #moveToFront
1691      * @see #setSelected
1692      * @see InternalFrameEvent#INTERNAL_FRAME_OPENED
1693      * @see #setVisible
1694      */
1695     public void show() {
1696         // bug 4312922
1697         if (isVisible()) {
1698             //match the behavior of setVisible(true): do nothing
1699             return;
1700         }
1701 
1702         // bug 4149505
1703         if (!opened) {
1704           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
1705           opened = true;
1706         }
1707 
1708         /* icon default visibility is false; set it to true so that it shows
1709            up when user iconifies frame */
1710         getDesktopIcon().setVisible(true);
1711 
1712         toFront();
1713         super.show();
1714 
1715         if (isIcon) {
1716             return;
1717         }
1718 
1719         if (!isSelected()) {
1720             try {
1721                 setSelected(true);
1722             } catch (PropertyVetoException pve) {}
1723         }
1724     }
1725 
1726     public void hide() {
1727         if (isIcon()) {
1728             getDesktopIcon().setVisible(false);
1729         }
1730         super.hide();
1731     }
1732 
1733     /**
1734      * Makes this internal frame
1735      * invisible, unselected, and closed.
1736      * If the frame is not already closed,
1737      * this method fires an
1738      * <code>INTERNAL_FRAME_CLOSED</code> event.
1739      * The results of invoking this method are similar to
1740      * <code>setClosed(true)</code>,
1741      * but <code>dispose</code> always succeeds in closing
1742      * the internal frame and does not fire
1743      * an <code>INTERNAL_FRAME_CLOSING</code> event.
1744      *
1745      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSED
1746      * @see #setVisible
1747      * @see #setSelected
1748      * @see #setClosed
1749      */
1750     public void dispose() {
1751         if (isVisible()) {
1752             setVisible(false);
1753         }
1754         if (isSelected()) {
1755             try {
1756                 setSelected(false);
1757             } catch (PropertyVetoException pve) {}
1758         }
1759         if (!isClosed) {
1760           firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE);
1761           isClosed = true;
1762         }
1763         fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
1764     }
1765 
1766     /**
1767      * Brings this internal frame to the front.
1768      * Places this internal frame  at the top of the stacking order
1769      * and makes the corresponding adjustment to other visible internal
1770      * frames.
1771      *
1772      * @see       java.awt.Window#toFront
1773      * @see       #moveToFront
1774      */
1775     public void toFront() {
1776         moveToFront();
1777     }
1778 
1779     /**
1780      * Sends this internal frame to the back.
1781      * Places this internal frame at the bottom of the stacking order
1782      * and makes the corresponding adjustment to other visible
1783      * internal frames.
1784      *
1785      * @see       java.awt.Window#toBack
1786      * @see       #moveToBack
1787      */
1788     public void toBack() {
1789         moveToBack();
1790     }
1791 
1792     /**
1793      * Does nothing because <code>JInternalFrame</code>s must always be roots of a focus
1794      * traversal cycle.
1795      *
1796      * @param focusCycleRoot this value is ignored
1797      * @see #isFocusCycleRoot
1798      * @see java.awt.Container#setFocusTraversalPolicy
1799      * @see java.awt.Container#getFocusTraversalPolicy
1800      * @since 1.4
1801      */
1802     public final void setFocusCycleRoot(boolean focusCycleRoot) {
1803     }
1804 
1805     /**
1806      * Always returns <code>true</code> because all <code>JInternalFrame</code>s must be
1807      * roots of a focus traversal cycle.
1808      *
1809      * @return <code>true</code>
1810      * @see #setFocusCycleRoot
1811      * @see java.awt.Container#setFocusTraversalPolicy
1812      * @see java.awt.Container#getFocusTraversalPolicy
1813      * @since 1.4
1814      */
1815     public final boolean isFocusCycleRoot() {
1816         return true;
1817     }
1818 
1819     /**
1820      * Always returns <code>null</code> because <code>JInternalFrame</code>s
1821      * must always be roots of a focus
1822      * traversal cycle.
1823      *
1824      * @return <code>null</code>
1825      * @see java.awt.Container#isFocusCycleRoot()
1826      * @since 1.4
1827      */
1828     @BeanProperty(bound = false)
1829     public final Container getFocusCycleRootAncestor() {
1830         return null;
1831     }
1832 
1833     /**
1834      * Gets the warning string that is displayed with this internal frame.
1835      * Since an internal frame is always secure (since it's fully
1836      * contained within a window that might need a warning string)
1837      * this method always returns <code>null</code>.
1838      * @return    <code>null</code>
1839      * @see       java.awt.Window#getWarningString
1840      */
1841     @BeanProperty(bound = false)
1842     public final String getWarningString() {
1843         return null;
1844     }
1845 
1846     /**
1847      * See <code>readObject</code> and <code>writeObject</code>
1848      * in <code>JComponent</code> for more
1849      * information about serialization in Swing.
1850      */
1851     private void writeObject(ObjectOutputStream s) throws IOException {
1852         s.defaultWriteObject();
1853         if (getUIClassID().equals(uiClassID)) {
1854             byte count = JComponent.getWriteObjCounter(this);
1855             JComponent.setWriteObjCounter(this, --count);
1856             if (count == 0 && ui != null) {
1857                 boolean old = isRootPaneCheckingEnabled();
1858                 try {
1859                     setRootPaneCheckingEnabled(false);
1860                     ui.installUI(this);
1861                 } finally {
1862                     setRootPaneCheckingEnabled(old);
1863                 }
1864             }
1865         }
1866     }
1867 
1868     /* Called from the JComponent's EnableSerializationFocusListener to
1869      * do any Swing-specific pre-serialization configuration.
1870      */
1871     void compWriteObjectNotify() {
1872       // need to disable rootpane checking for InternalFrame: 4172083
1873       boolean old = isRootPaneCheckingEnabled();
1874       try {
1875         setRootPaneCheckingEnabled(false);
1876         super.compWriteObjectNotify();
1877       }
1878       finally {
1879         setRootPaneCheckingEnabled(old);
1880       }
1881     }
1882 
1883     /**
1884      * Returns a string representation of this <code>JInternalFrame</code>.
1885      * This method
1886      * is intended to be used only for debugging purposes, and the
1887      * content and format of the returned string may vary between
1888      * implementations. The returned string may be empty but may not
1889      * be <code>null</code>.
1890      *
1891      * @return  a string representation of this <code>JInternalFrame</code>
1892      */
1893     protected String paramString() {
1894         String rootPaneString = (rootPane != null ?
1895                                  rootPane.toString() : "");
1896         String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
1897                                                 "true" : "false");
1898         String closableString = (closable ? "true" : "false");
1899         String isClosedString = (isClosed ? "true" : "false");
1900         String maximizableString = (maximizable ? "true" : "false");
1901         String isMaximumString = (isMaximum ? "true" : "false");
1902         String iconableString = (iconable ? "true" : "false");
1903         String isIconString = (isIcon ? "true" : "false");
1904         String resizableString = (resizable ? "true" : "false");
1905         String isSelectedString = (isSelected ? "true" : "false");
1906         String frameIconString = (frameIcon != null ?
1907                                   frameIcon.toString() : "");
1908         String titleString = (title != null ?
1909                               title : "");
1910         String desktopIconString = (desktopIcon != null ?
1911                                     desktopIcon.toString() : "");
1912         String openedString = (opened ? "true" : "false");
1913         String defaultCloseOperationString;
1914         if (defaultCloseOperation == HIDE_ON_CLOSE) {
1915             defaultCloseOperationString = "HIDE_ON_CLOSE";
1916         } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
1917             defaultCloseOperationString = "DISPOSE_ON_CLOSE";
1918         } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
1919             defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
1920         } else defaultCloseOperationString = "";
1921 
1922         return super.paramString() +
1923         ",closable=" + closableString +
1924         ",defaultCloseOperation=" + defaultCloseOperationString +
1925         ",desktopIcon=" + desktopIconString +
1926         ",frameIcon=" + frameIconString +
1927         ",iconable=" + iconableString +
1928         ",isClosed=" + isClosedString +
1929         ",isIcon=" + isIconString +
1930         ",isMaximum=" + isMaximumString +
1931         ",isSelected=" + isSelectedString +
1932         ",maximizable=" + maximizableString +
1933         ",opened=" + openedString +
1934         ",resizable=" + resizableString +
1935         ",rootPane=" + rootPaneString +
1936         ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString +
1937         ",title=" + titleString;
1938     }
1939 
1940     // ======= begin optimized frame dragging defence code ==============
1941 
1942     boolean isDragging = false;
1943     boolean danger = false;
1944 
1945     /**
1946      * Overridden to allow optimized painting when the
1947      * internal frame is being dragged.
1948      */
1949     protected void paintComponent(Graphics g) {
1950       if (isDragging) {
1951         //         System.out.println("ouch");
1952          danger = true;
1953       }
1954 
1955       super.paintComponent(g);
1956    }
1957 
1958     // ======= end optimized frame dragging defence code ==============
1959 
1960 /////////////////
1961 // Accessibility support
1962 ////////////////
1963 
1964     /**
1965      * Gets the <code>AccessibleContext</code> associated with this
1966      * <code>JInternalFrame</code>.
1967      * For internal frames, the <code>AccessibleContext</code>
1968      * takes the form of an
1969      * <code>AccessibleJInternalFrame</code> object.
1970      * A new <code>AccessibleJInternalFrame</code> instance is created if necessary.
1971      *
1972      * @return an <code>AccessibleJInternalFrame</code> that serves as the
1973      *         <code>AccessibleContext</code> of this
1974      *         <code>JInternalFrame</code>
1975      * @see AccessibleJInternalFrame
1976      */
1977     @BeanProperty(bound = false)
1978     public AccessibleContext getAccessibleContext() {
1979         if (accessibleContext == null) {
1980             accessibleContext = new AccessibleJInternalFrame();
1981         }
1982         return accessibleContext;
1983     }
1984 
1985     /**
1986      * This class implements accessibility support for the
1987      * <code>JInternalFrame</code> class.  It provides an implementation of the
1988      * Java Accessibility API appropriate to internal frame user-interface
1989      * elements.
1990      * <p>
1991      * <strong>Warning:</strong>
1992      * Serialized objects of this class will not be compatible with
1993      * future Swing releases. The current serialization support is
1994      * appropriate for short term storage or RMI between applications running
1995      * the same version of Swing.  As of 1.4, support for long term storage
1996      * of all JavaBeans&trade;
1997      * has been added to the <code>java.beans</code> package.
1998      * Please see {@link java.beans.XMLEncoder}.
1999      */
2000     @SuppressWarnings("serial") // Same-version serialization only
2001     protected class AccessibleJInternalFrame extends AccessibleJComponent
2002         implements AccessibleValue {
2003 
2004         /**
2005          * Get the accessible name of this object.
2006          *
2007          * @return the localized name of the object -- can be <code>null</code> if this
2008          * object does not have a name
2009          * @see #setAccessibleName
2010          */
2011         public String getAccessibleName() {
2012             String name = accessibleName;
2013 
2014             if (name == null) {
2015                 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
2016             }
2017             if (name == null) {
2018                 name = getTitle();
2019             }
2020             return name;
2021         }
2022 
2023         /**
2024          * Get the role of this object.
2025          *
2026          * @return an instance of AccessibleRole describing the role of the
2027          * object
2028          * @see AccessibleRole
2029          */
2030         public AccessibleRole getAccessibleRole() {
2031             return AccessibleRole.INTERNAL_FRAME;
2032         }
2033 
2034         /**
2035          * Gets the AccessibleValue associated with this object.  In the
2036          * implementation of the Java Accessibility API for this class,
2037          * returns this object, which is responsible for implementing the
2038          * <code>AccessibleValue</code> interface on behalf of itself.
2039          *
2040          * @return this object
2041          */
2042         public AccessibleValue getAccessibleValue() {
2043             return this;
2044         }
2045 
2046 
2047         //
2048         // AccessibleValue methods
2049         //
2050 
2051         /**
2052          * Get the value of this object as a Number.
2053          *
2054          * @return value of the object -- can be <code>null</code> if this object does not
2055          * have a value
2056          */
2057         public Number getCurrentAccessibleValue() {
2058             return Integer.valueOf(getLayer());
2059         }
2060 
2061         /**
2062          * Set the value of this object as a Number.
2063          *
2064          * @return <code>true</code> if the value was set
2065          */
2066         public boolean setCurrentAccessibleValue(Number n) {
2067             // TIGER - 4422535
2068             if (n == null) {
2069                 return false;
2070             }
2071             setLayer(Integer.valueOf(n.intValue()));
2072             return true;
2073         }
2074 
2075         /**
2076          * Get the minimum value of this object as a Number.
2077          *
2078          * @return Minimum value of the object; <code>null</code> if this object does not
2079          * have a minimum value
2080          */
2081         public Number getMinimumAccessibleValue() {
2082             return Integer.MIN_VALUE;
2083         }
2084 
2085         /**
2086          * Get the maximum value of this object as a Number.
2087          *
2088          * @return Maximum value of the object; <code>null</code> if this object does not
2089          * have a maximum value
2090          */
2091         public Number getMaximumAccessibleValue() {
2092             return Integer.MAX_VALUE;
2093         }
2094 
2095     } // AccessibleJInternalFrame
2096 
2097     /**
2098      * This component represents an iconified version of a
2099      * <code>JInternalFrame</code>.
2100      * This API should NOT BE USED by Swing applications, as it will go
2101      * away in future versions of Swing as its functionality is moved into
2102      * <code>JInternalFrame</code>.  This class is public only so that
2103      * UI objects can display a desktop icon.  If an application
2104      * wants to display a desktop icon, it should create a
2105      * <code>JInternalFrame</code> instance and iconify it.
2106      * <p>
2107      * <strong>Warning:</strong>
2108      * Serialized objects of this class will not be compatible with
2109      * future Swing releases. The current serialization support is
2110      * appropriate for short term storage or RMI between applications running
2111      * the same version of Swing.  As of 1.4, support for long term storage
2112      * of all JavaBeans&trade;
2113      * has been added to the <code>java.beans</code> package.
2114      * Please see {@link java.beans.XMLEncoder}.
2115      *
2116      * @author David Kloba
2117      */
2118     @SuppressWarnings("serial") // Same-version serialization only
2119     static public class JDesktopIcon extends JComponent implements Accessible
2120     {
2121         JInternalFrame internalFrame;
2122 
2123         /**
2124          * Creates an icon for an internal frame.
2125          *
2126          * @param f  the <code>JInternalFrame</code>
2127          *              for which the icon is created
2128          */
2129         public JDesktopIcon(JInternalFrame f) {
2130             setVisible(false);
2131             setInternalFrame(f);
2132             updateUI();
2133         }
2134 
2135         /**
2136          * Returns the look-and-feel object that renders this component.
2137          *
2138          * @return the <code>DesktopIconUI</code> object that renders
2139          *              this component
2140          */
2141         public DesktopIconUI getUI() {
2142             return (DesktopIconUI)ui;
2143         }
2144 
2145         /**
2146          * Sets the look-and-feel object that renders this component.
2147          *
2148          * @param ui  the <code>DesktopIconUI</code> look-and-feel object
2149          * @see UIDefaults#getUI
2150          */
2151         public void setUI(DesktopIconUI ui) {
2152             super.setUI(ui);
2153         }
2154 
2155         /**
2156          * Returns the <code>JInternalFrame</code> that this
2157          * <code>DesktopIcon</code> is associated with.
2158          *
2159          * @return the <code>JInternalFrame</code> with which this icon
2160          *              is associated
2161          */
2162         public JInternalFrame getInternalFrame() {
2163             return internalFrame;
2164         }
2165 
2166         /**
2167          * Sets the <code>JInternalFrame</code> with which this
2168          * <code>DesktopIcon</code> is associated.
2169          *
2170          * @param f  the <code>JInternalFrame</code> with which this icon
2171          *              is associated
2172          */
2173         public void setInternalFrame(JInternalFrame f) {
2174             internalFrame = f;
2175         }
2176 
2177         /**
2178          * Convenience method to ask the icon for the <code>Desktop</code>
2179          * object it belongs to.
2180          *
2181          * @return the <code>JDesktopPane</code> that contains this
2182          *           icon's internal frame, or <code>null</code> if none found
2183          */
2184         public JDesktopPane getDesktopPane() {
2185             if(getInternalFrame() != null)
2186                 return getInternalFrame().getDesktopPane();
2187             return null;
2188         }
2189 
2190         /**
2191          * Notification from the <code>UIManager</code> that the look and feel
2192          * has changed.
2193          * Replaces the current UI object with the latest version from the
2194          * <code>UIManager</code>.
2195          *
2196          * @see JComponent#updateUI
2197          */
2198         public void updateUI() {
2199             boolean hadUI = (ui != null);
2200             setUI((DesktopIconUI)UIManager.getUI(this));
2201             invalidate();
2202 
2203             Dimension r = getPreferredSize();
2204             setSize(r.width, r.height);
2205 
2206 
2207             if (internalFrame != null && internalFrame.getUI() != null) {  // don't do this if UI not created yet
2208                 SwingUtilities.updateComponentTreeUI(internalFrame);
2209             }
2210         }
2211 
2212         /* This method is called if updateUI was called on the associated
2213          * JInternalFrame.  It's necessary to avoid infinite recursion.
2214          */
2215         void updateUIWhenHidden() {
2216             /* Update this UI and any associated internal frame */
2217             setUI((DesktopIconUI)UIManager.getUI(this));
2218 
2219             Dimension r = getPreferredSize();
2220             setSize(r.width, r.height);
2221 
2222             invalidate();
2223             Component[] children = getComponents();
2224             if (children != null) {
2225                 for (Component child : children) {
2226                     SwingUtilities.updateComponentTreeUI(child);
2227                 }
2228             }
2229         }
2230 
2231         /**
2232          * Returns the name of the look-and-feel
2233          * class that renders this component.
2234          *
2235          * @return the string "DesktopIconUI"
2236          * @see JComponent#getUIClassID
2237          * @see UIDefaults#getUI
2238          */
2239         public String getUIClassID() {
2240             return "DesktopIconUI";
2241         }
2242         ////////////////
2243         // Serialization support
2244         ////////////////
2245         private void writeObject(ObjectOutputStream s) throws IOException {
2246             s.defaultWriteObject();
2247             if (getUIClassID().equals("DesktopIconUI")) {
2248                 byte count = JComponent.getWriteObjCounter(this);
2249                 JComponent.setWriteObjCounter(this, --count);
2250                 if (count == 0 && ui != null) {
2251                     ui.installUI(this);
2252                 }
2253             }
2254         }
2255 
2256        /////////////////
2257        // Accessibility support
2258        ////////////////
2259 
2260         /**
2261          * Gets the AccessibleContext associated with this JDesktopIcon.
2262          * For desktop icons, the AccessibleContext takes the form of an
2263          * AccessibleJDesktopIcon.
2264          * A new AccessibleJDesktopIcon instance is created if necessary.
2265          *
2266          * @return an AccessibleJDesktopIcon that serves as the
2267          *         AccessibleContext of this JDesktopIcon
2268          */
2269         public AccessibleContext getAccessibleContext() {
2270             if (accessibleContext == null) {
2271                 accessibleContext = new AccessibleJDesktopIcon();
2272             }
2273             return accessibleContext;
2274         }
2275 
2276         /**
2277          * This class implements accessibility support for the
2278          * <code>JInternalFrame.JDesktopIcon</code> class.  It provides an
2279          * implementation of the Java Accessibility API appropriate to
2280          * desktop icon user-interface elements.
2281          * <p>
2282          * <strong>Warning:</strong>
2283          * Serialized objects of this class will not be compatible with
2284          * future Swing releases. The current serialization support is
2285          * appropriate for short term storage or RMI between applications running
2286          * the same version of Swing.  As of 1.4, support for long term storage
2287          * of all JavaBeans&trade;
2288          * has been added to the <code>java.beans</code> package.
2289          * Please see {@link java.beans.XMLEncoder}.
2290          */
2291         @SuppressWarnings("serial") // Same-version serialization only
2292         protected class AccessibleJDesktopIcon extends AccessibleJComponent
2293             implements AccessibleValue {
2294 
2295             /**
2296              * Gets the role of this object.
2297              *
2298              * @return an instance of AccessibleRole describing the role of the
2299              * object
2300              * @see AccessibleRole
2301              */
2302             public AccessibleRole getAccessibleRole() {
2303                 return AccessibleRole.DESKTOP_ICON;
2304             }
2305 
2306             /**
2307              * Gets the AccessibleValue associated with this object.  In the
2308              * implementation of the Java Accessibility API for this class,
2309              * returns this object, which is responsible for implementing the
2310              * <code>AccessibleValue</code> interface on behalf of itself.
2311              *
2312              * @return this object
2313              */
2314             public AccessibleValue getAccessibleValue() {
2315                 return this;
2316             }
2317 
2318             //
2319             // AccessibleValue methods
2320             //
2321 
2322             /**
2323              * Gets the value of this object as a <code>Number</code>.
2324              *
2325              * @return value of the object -- can be <code>null</code> if this object does not
2326              * have a value
2327              */
2328             public Number getCurrentAccessibleValue() {
2329                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2330                 AccessibleValue v = a.getAccessibleValue();
2331                 if (v != null) {
2332                     return v.getCurrentAccessibleValue();
2333                 } else {
2334                     return null;
2335                 }
2336             }
2337 
2338             /**
2339              * Sets the value of this object as a <code>Number</code>.
2340              *
2341              * @return <code>true</code> if the value was set
2342              */
2343             public boolean setCurrentAccessibleValue(Number n) {
2344                 // TIGER - 4422535
2345                 if (n == null) {
2346                     return false;
2347                 }
2348                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2349                 AccessibleValue v = a.getAccessibleValue();
2350                 if (v != null) {
2351                     return v.setCurrentAccessibleValue(n);
2352                 } else {
2353                     return false;
2354                 }
2355             }
2356 
2357             /**
2358              * Gets the minimum value of this object as a <code>Number</code>.
2359              *
2360              * @return minimum value of the object; <code>null</code> if this object does not
2361              * have a minimum value
2362              */
2363             public Number getMinimumAccessibleValue() {
2364                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2365                 if (a instanceof AccessibleValue) {
2366                     return ((AccessibleValue)a).getMinimumAccessibleValue();
2367                 } else {
2368                     return null;
2369                 }
2370             }
2371 
2372             /**
2373              * Gets the maximum value of this object as a <code>Number</code>.
2374              *
2375              * @return maximum value of the object; <code>null</code> if this object does not
2376              * have a maximum value
2377              */
2378             public Number getMaximumAccessibleValue() {
2379                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2380                 if (a instanceof AccessibleValue) {
2381                     return ((AccessibleValue)a).getMaximumAccessibleValue();
2382                 } else {
2383                     return null;
2384                 }
2385             }
2386 
2387         } // AccessibleJDesktopIcon
2388     }
2389 }