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