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

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