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