Home » openjdk-7 » javax » swing » [javadoc | source]

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

Home » openjdk-7 » javax » swing » [javadoc | source]