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