| /* | |
|  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. | |
|  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
|  * | |
|  * This code is free software; you can redistribute it and/or modify it | |
|  * under the terms of the GNU General Public License version 2 only, as | |
|  * published by the Free Software Foundation.  Oracle designates this | |
|  * particular file as subject to the "Classpath" exception as provided | |
|  * by Oracle in the LICENSE file that accompanied this code. | |
|  * | |
|  * This code is distributed in the hope that it will be useful, but WITHOUT | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | |
|  * version 2 for more details (a copy is included in the LICENSE file that | |
|  * accompanied this code). | |
|  * | |
|  * You should have received a copy of the GNU General Public License version | |
|  * 2 along with this work; if not, write to the Free Software Foundation, | |
|  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
|  * | |
|  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
|  * or visit www.oracle.com if you need additional information or have any | |
|  * questions. | |
| */ | |
| package javax.swing; | |
| import java.awt.*; | |
| import java.beans.PropertyVetoException; | |
| import java.beans.PropertyChangeEvent; | |
| import javax.swing.event.InternalFrameEvent; | |
| import javax.swing.event.InternalFrameListener; | |
| import javax.swing.plaf.*; | |
| import javax.accessibility.*; | |
| import java.io.ObjectOutputStream; | |
| import java.io.IOException; | |
| import java.beans.PropertyChangeListener; | |
| import sun.awt.AppContext; | |
| import sun.swing.SwingUtilities2; | |
| /** | |
|  * A lightweight object that provides many of the features of | |
|  * a native frame, including dragging, closing, becoming an icon, | |
|  * resizing, title display, and support for a menu bar. | |
|  * For task-oriented documentation and examples of using internal frames, | |
|  * see <a | |
|  href="https://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html" target="_top">How to Use Internal Frames</a>, | |
|  * a section in <em>The Java Tutorial</em>. | |
|  * | |
|  * <p> | |
|  * | |
|  * Generally, | |
|  * you add <code>JInternalFrame</code>s to a <code>JDesktopPane</code>. The UI | |
|  * delegates the look-and-feel-specific actions to the | |
|  * <code>DesktopManager</code> | |
|  * object maintained by the <code>JDesktopPane</code>. | |
|  * <p> | |
|  * The <code>JInternalFrame</code> content pane | |
|  * is where you add child components. | |
|  * As a convenience, the {@code add}, {@code remove}, and {@code setLayout} | |
|  * methods of this class are overridden, so that they delegate calls | |
|  * to the corresponding methods of the {@code ContentPane}. | |
|  * For example, you can add a child component to an internal frame as follows: | |
|  * <pre> | |
|  *       internalFrame.add(child); | |
|  * </pre> | |
|  * And the child will be added to the contentPane. | |
|  * The content pane is actually managed by an instance of | |
|  * <code>JRootPane</code>, | |
|  * which also manages a layout pane, glass pane, and | |
|  * optional menu bar for the internal frame. Please see the | |
|  * <code>JRootPane</code> | |
|  * documentation for a complete description of these components. | |
|  * Refer to {@link javax.swing.RootPaneContainer} | |
|  * for details on adding, removing and setting the <code>LayoutManager</code> | |
|  * of a <code>JInternalFrame</code>. | |
|  * <p> | |
|  * <strong>Warning:</strong> Swing is not thread safe. For more | |
|  * information see <a | |
|  * href="package-summary.html#threading">Swing's Threading | |
|  * Policy</a>. | |
|  * <p> | |
|  * <strong>Warning:</strong> | |
|  * Serialized objects of this class will not be compatible with | |
|  * future Swing releases. The current serialization support is | |
|  * appropriate for short term storage or RMI between applications running | |
|  * the same version of Swing.  As of 1.4, support for long term storage | |
|  * of all JavaBeans™ | |
|  * has been added to the <code>java.beans</code> package. | |
|  * Please see {@link java.beans.XMLEncoder}. | |
|  * | |
|  * @see InternalFrameEvent | |
|  * @see JDesktopPane | |
|  * @see DesktopManager | |
|  * @see JInternalFrame.JDesktopIcon | |
|  * @see JRootPane | |
|  * @see javax.swing.RootPaneContainer | |
|  * | |
|  * @author David Kloba | |
|  * @author Rich Schiavi | |
|  * @beaninfo | |
|  *      attribute: isContainer true | |
|  *      attribute: containerDelegate getContentPane | |
|  *      description: A frame container which is contained within | |
|  *                   another window. | |
| */ | |
| public class JInternalFrame extends JComponent implements | |
| Accessible, WindowConstants, | |
| RootPaneContainer | |
| { | |
|     /** | |
|      * @see #getUIClassID | |
|      * @see #readObject | |
| */ | |
| private static final String uiClassID = "InternalFrameUI"; | |
|     /** | |
|      * The <code>JRootPane</code> instance that manages the | |
|      * content pane | |
|      * and optional menu bar for this internal frame, as well as the | |
|      * glass pane. | |
|      * | |
|      * @see JRootPane | |
|      * @see RootPaneContainer | |
| */ | |
| protected JRootPane rootPane; | |
|     /** | |
|      * If true then calls to <code>add</code> and <code>setLayout</code> | |
|      * will be forwarded to the <code>contentPane</code>. This is initially | |
|      * false, but is set to true when the <code>JInternalFrame</code> is | |
|      * constructed. | |
|      * | |
|      * @see #isRootPaneCheckingEnabled | |
|      * @see #setRootPaneCheckingEnabled | |
|      * @see javax.swing.RootPaneContainer | |
| */ | |
| protected boolean rootPaneCheckingEnabled = false; | |
|     /** The frame can be closed. */ | |
| protected boolean closable; | |
|     /** The frame has been closed. */ | |
| protected boolean isClosed; | |
|     /** The frame can be expanded to the size of the desktop pane. */ | |
| protected boolean maximizable; | |
|     /** | |
|      * The frame has been expanded to its maximum size. | |
|      * @see #maximizable | |
| */ | |
| protected boolean isMaximum; | |
|     /** | |
|      * The frame can "iconified" (shrunk down and displayed as | |
|      * an icon-image). | |
|      * @see JInternalFrame.JDesktopIcon | |
|      * @see #setIconifiable | |
| */ | |
| protected boolean iconable; | |
|     /** | |
|      * The frame has been iconified. | |
|      * @see #isIcon() | |
| */ | |
| protected boolean isIcon; | |
|     /** The frame's size can be changed. */ | |
| protected boolean resizable; | |
|     /** The frame is currently selected. */ | |
| protected boolean isSelected; | |
|     /** The icon shown in the top-left corner of this internal frame. */ | |
| protected Icon frameIcon; | |
|     /** The title displayed in this internal frame's title bar. */ | |
| protected String title; | |
|     /** | |
|      * The icon that is displayed when this internal frame is iconified. | |
|      * @see #iconable | |
| */ | |
| protected JDesktopIcon desktopIcon; | |
| private Cursor lastCursor; | |
| private boolean opened; | |
| private Rectangle normalBounds = null; | |
| private int defaultCloseOperation = DISPOSE_ON_CLOSE; | |
|     /** | |
|      * Contains the Component that focus is to go when | |
|      * <code>restoreSubcomponentFocus</code> is invoked, that is, | |
|      * <code>restoreSubcomponentFocus</code> sets this to the value returned | |
|      * from <code>getMostRecentFocusOwner</code>. | |
| */ | |
| private Component lastFocusOwner; | |
|     /** Bound property name. */ | |
| public final static String CONTENT_PANE_PROPERTY = "contentPane"; | |
|     /** Bound property name. */ | |
| public final static String MENU_BAR_PROPERTY = "JMenuBar"; | |
|     /** Bound property name. */ | |
| public final static String TITLE_PROPERTY = "title"; | |
|     /** Bound property name. */ | |
| public final static String LAYERED_PANE_PROPERTY = "layeredPane"; | |
|     /** Bound property name. */ | |
| public final static String ROOT_PANE_PROPERTY = "rootPane"; | |
|     /** Bound property name. */ | |
| public final static String GLASS_PANE_PROPERTY = "glassPane"; | |
|     /** Bound property name. */ | |
| public final static String FRAME_ICON_PROPERTY = "frameIcon"; | |
|     /** | |
|      * Constrained property name indicated that this frame has | |
|      * selected status. | |
| */ | |
| public final static String IS_SELECTED_PROPERTY = "selected"; | |
|     /** Constrained property name indicating that the internal frame is closed. */ | |
| public final static String IS_CLOSED_PROPERTY = "closed"; | |
|     /** Constrained property name indicating that the internal frame is maximized. */ | |
| public final static String IS_MAXIMUM_PROPERTY = "maximum"; | |
|     /** Constrained property name indicating that the internal frame is iconified. */ | |
| public final static String IS_ICON_PROPERTY = "icon"; | |
| private static final Object PROPERTY_CHANGE_LISTENER_KEY = | |
| new StringBuilder("InternalFramePropertyChangeListener"); | |
|     private static void addPropertyChangeListenerIfNecessary() { | |
| if (AppContext.getAppContext().get(PROPERTY_CHANGE_LISTENER_KEY) == | |
|             null) { | |
| PropertyChangeListener focusListener = | |
| new FocusPropertyChangeListener(); | |
| AppContext.getAppContext().put(PROPERTY_CHANGE_LISTENER_KEY, | |
| focusListener); | |
| KeyboardFocusManager.getCurrentKeyboardFocusManager(). | |
| addPropertyChangeListener(focusListener); | |
| } | |
| } | |
| private static class FocusPropertyChangeListener implements | |
| PropertyChangeListener { | |
| public void propertyChange(PropertyChangeEvent e) { | |
| if (e.getPropertyName() == "permanentFocusOwner") { | |
| updateLastFocusOwner((Component)e.getNewValue()); | |
| } | |
| } | |
| } | |
| private static void updateLastFocusOwner(Component component) { | |
| if (component != null) { | |
| Component parent = component; | |
| while (parent != null && !(parent instanceof Window)) { | |
| if (parent instanceof JInternalFrame) { | |
|                     // Update lastFocusOwner for parent. | |
| ((JInternalFrame)parent).setLastFocusOwner(component); | |
| } | |
| parent = parent.getParent(); | |
| } | |
| } | |
| } | |
|     /** | |
|      * Creates a non-resizable, non-closable, non-maximizable, | |
|      * non-iconifiable <code>JInternalFrame</code> with no title. | |
| */ | |
|     public JInternalFrame() { | |
|         this("", false, false, false, false); | |
| } | |
|     /** | |
|      * Creates a non-resizable, non-closable, non-maximizable, | |
|      * non-iconifiable <code>JInternalFrame</code> with the specified title. | |
|      * Note that passing in a <code>null</code> <code>title</code> results in | |
|      * unspecified behavior and possibly an exception. | |
|      * | |
|      * @param title  the non-<code>null</code> <code>String</code> | |
|      *     to display in the title bar | |
| */ | |
| public JInternalFrame(String title) { | |
| this(title, false, false, false, false); | |
| } | |
|     /** | |
|      * Creates a non-closable, non-maximizable, non-iconifiable | |
|      * <code>JInternalFrame</code> with the specified title | |
|      * and resizability. | |
|      * | |
|      * @param title      the <code>String</code> to display in the title bar | |
|      * @param resizable  if <code>true</code>, the internal frame can be resized | |
| */ | |
| public JInternalFrame(String title, boolean resizable) { | |
| this(title, resizable, false, false, false); | |
| } | |
|     /** | |
|      * Creates a non-maximizable, non-iconifiable <code>JInternalFrame</code> | |
|      * with the specified title, resizability, and | |
|      * closability. | |
|      * | |
|      * @param title      the <code>String</code> to display in the title bar | |
|      * @param resizable  if <code>true</code>, the internal frame can be resized | |
|      * @param closable   if <code>true</code>, the internal frame can be closed | |
| */ | |
| public JInternalFrame(String title, boolean resizable, boolean closable) { | |
| this(title, resizable, closable, false, false); | |
| } | |
|     /** | |
|      * Creates a non-iconifiable <code>JInternalFrame</code> | |
|      * with the specified title, | |
|      * resizability, closability, and maximizability. | |
|      * | |
|      * @param title       the <code>String</code> to display in the title bar | |
|      * @param resizable   if <code>true</code>, the internal frame can be resized | |
|      * @param closable    if <code>true</code>, the internal frame can be closed | |
|      * @param maximizable if <code>true</code>, the internal frame can be maximized | |
| */ | |
| public JInternalFrame(String title, boolean resizable, boolean closable, | |
|                           boolean maximizable) { | |
| this(title, resizable, closable, maximizable, false); | |
| } | |
|     /** | |
|      * Creates a <code>JInternalFrame</code> with the specified title, | |
|      * resizability, closability, maximizability, and iconifiability. | |
|      * All <code>JInternalFrame</code> constructors use this one. | |
|      * | |
|      * @param title       the <code>String</code> to display in the title bar | |
|      * @param resizable   if <code>true</code>, the internal frame can be resized | |
|      * @param closable    if <code>true</code>, the internal frame can be closed | |
|      * @param maximizable if <code>true</code>, the internal frame can be maximized | |
|      * @param iconifiable if <code>true</code>, the internal frame can be iconified | |
| */ | |
| public JInternalFrame(String title, boolean resizable, boolean closable, | |
|                                 boolean maximizable, boolean iconifiable) { | |
| setRootPane(createRootPane()); | |
| setLayout(new BorderLayout()); | |
| this.title = title; | |
| this.resizable = resizable; | |
| this.closable = closable; | |
| this.maximizable = maximizable; | |
| isMaximum = false; | |
| this.iconable = iconifiable; | |
| isIcon = false; | |
| setVisible(false); | |
| setRootPaneCheckingEnabled(true); | |
| desktopIcon = new JDesktopIcon(this); | |
| updateUI(); | |
| sun.awt.SunToolkit.checkAndSetPolicy(this); | |
| addPropertyChangeListenerIfNecessary(); | |
| } | |
|     /** | |
|      * Called by the constructor to set up the <code>JRootPane</code>. | |
|      * @return  a new <code>JRootPane</code> | |
|      * @see JRootPane | |
| */ | |
| protected JRootPane createRootPane() { | |
| return new JRootPane(); | |
| } | |
|     /** | |
|      * Returns the look-and-feel object that renders this component. | |
|      * | |
|      * @return the <code>InternalFrameUI</code> object that renders | |
|      *          this component | |
| */ | |
| public InternalFrameUI getUI() { | |
| return (InternalFrameUI)ui; | |
| } | |
|     /** | |
|      * Sets the UI delegate for this <code>JInternalFrame</code>. | |
|      * @param ui  the UI delegate | |
|      * @beaninfo | |
|      *        bound: true | |
|      *       hidden: true | |
|      *    attribute: visualUpdate true | |
|      *  description: The UI object that implements the Component's LookAndFeel. | |
| */ | |
| public void setUI(InternalFrameUI ui) { | |
| boolean checkingEnabled = isRootPaneCheckingEnabled(); | |
|         try { | |
| setRootPaneCheckingEnabled(false); | |
| super.setUI(ui); | |
| } | |
|         finally { | |
| setRootPaneCheckingEnabled(checkingEnabled); | |
| } | |
| } | |
|     /** | |
|      * Notification from the <code>UIManager</code> that the look and feel | |
|      * has changed. | |
|      * Replaces the current UI object with the latest version from the | |
|      * <code>UIManager</code>. | |
|      * | |
|      * @see JComponent#updateUI | |
| */ | |
|     public void updateUI() { | |
| setUI((InternalFrameUI)UIManager.getUI(this)); | |
| invalidate(); | |
| if (desktopIcon != null) { | |
| desktopIcon.updateUIWhenHidden(); | |
| } | |
| } | |
|     /* This method is called if <code>updateUI</code> was called | |
|      * on the associated | |
|      * JDesktopIcon.  It's necessary to avoid infinite recursion. | |
| */ | |
|     void updateUIWhenHidden() { | |
| setUI((InternalFrameUI)UIManager.getUI(this)); | |
| invalidate(); | |
| Component[] children = getComponents(); | |
| if (children != null) { | |
| for (Component child : children) { | |
| SwingUtilities.updateComponentTreeUI(child); | |
| } | |
| } | |
| } | |
|     /** | |
|      * Returns the name of the look-and-feel | |
|      * class that renders this component. | |
|      * | |
|      * @return the string "InternalFrameUI" | |
|      * | |
|      * @see JComponent#getUIClassID | |
|      * @see UIDefaults#getUI | |
|      * | |
|      * @beaninfo | |
|      *     description: UIClassID | |
| */ | |
| public String getUIClassID() { | |
| return uiClassID; | |
| } | |
|     /** | |
|      * Returns whether calls to <code>add</code> and | |
|      * <code>setLayout</code> are forwarded to the <code>contentPane</code>. | |
|      * | |
|      * @return true if <code>add</code> and <code>setLayout</code> | |
|      *         are forwarded; false otherwise | |
|      * | |
|      * @see #addImpl | |
|      * @see #setLayout | |
|      * @see #setRootPaneCheckingEnabled | |
|      * @see javax.swing.RootPaneContainer | |
| */ | |
|     protected boolean isRootPaneCheckingEnabled() { | |
| return rootPaneCheckingEnabled; | |
| } | |
|     /** | |
|      * Sets whether calls to <code>add</code> and | |
|      * <code>setLayout</code> are forwarded to the <code>contentPane</code>. | |
|      * | |
|      * @param enabled  true if <code>add</code> and <code>setLayout</code> | |
|      *        are forwarded, false if they should operate directly on the | |
|      *        <code>JInternalFrame</code>. | |
|      * | |
|      * @see #addImpl | |
|      * @see #setLayout | |
|      * @see #isRootPaneCheckingEnabled | |
|      * @see javax.swing.RootPaneContainer | |
|      * @beaninfo | |
|      *      hidden: true | |
|      * description: Whether the add and setLayout methods are forwarded | |
| */ | |
|     protected void setRootPaneCheckingEnabled(boolean enabled) { | |
| rootPaneCheckingEnabled = enabled; | |
| } | |
|     /** | |
|      * Adds the specified child <code>Component</code>. | |
|      * This method is overridden to conditionally forward calls to the | |
|      * <code>contentPane</code>. | |
|      * By default, children are added to the <code>contentPane</code> instead | |
|      * of the frame, refer to {@link javax.swing.RootPaneContainer} for | |
|      * details. | |
|      * | |
|      * @param comp the component to be enhanced | |
|      * @param constraints the constraints to be respected | |
|      * @param index the index | |
|      * @exception IllegalArgumentException if <code>index</code> is invalid | |
|      * @exception IllegalArgumentException if adding the container's parent | |
|      *                  to itself | |
|      * @exception IllegalArgumentException if adding a window to a container | |
|      * | |
|      * @see #setRootPaneCheckingEnabled | |
|      * @see javax.swing.RootPaneContainer | |
| */ | |
| protected void addImpl(Component comp, Object constraints, int index) { | |
| if(isRootPaneCheckingEnabled()) { | |
| getContentPane().add(comp, constraints, index); | |
| } | |
|         else { | |
| super.addImpl(comp, constraints, index); | |
| } | |
| } | |
|     /** | |
|      * Removes the specified component from the container. If | |
|      * <code>comp</code> is not a child of the <code>JInternalFrame</code> | |
|      * this will forward the call to the <code>contentPane</code>. | |
|      * | |
|      * @param comp the component to be removed | |
|      * @throws NullPointerException if <code>comp</code> is null | |
|      * @see #add | |
|      * @see javax.swing.RootPaneContainer | |
| */ | |
| public void remove(Component comp) { | |
| int oldCount = getComponentCount(); | |
| super.remove(comp); | |
| if (oldCount == getComponentCount()) { | |
| getContentPane().remove(comp); | |
| } | |
| } | |
|     /** | |
|      * Ensures that, by default, the layout of this component cannot be set. | |
|      * Overridden to conditionally forward the call to the | |
|      * <code>contentPane</code>. | |
|      * Refer to {@link javax.swing.RootPaneContainer} for | |
|      * more information. | |
|      * | |
|      * @param manager the <code>LayoutManager</code> | |
|      * @see #setRootPaneCheckingEnabled | |
| */ | |
| public void setLayout(LayoutManager manager) { | |
| if(isRootPaneCheckingEnabled()) { | |
| getContentPane().setLayout(manager); | |
| } | |
|         else { | |
| super.setLayout(manager); | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| /// Property Methods | |
| ////////////////////////////////////////////////////////////////////////// | |
|     /** | |
|      * Returns the current <code>JMenuBar</code> for this | |
|      * <code>JInternalFrame</code>, or <code>null</code> | |
|      * if no menu bar has been set. | |
|      * @return the current menu bar, or <code>null</code> if none has been set | |
|      * | |
|      * @deprecated As of Swing version 1.0.3, | |
|      * replaced by <code>getJMenuBar()</code>. | |
| */ | |
| @Deprecated | |
| public JMenuBar getMenuBar() { | |
| return getRootPane().getMenuBar(); | |
| } | |
|     /** | |
|      * Returns the current <code>JMenuBar</code> for this | |
|      * <code>JInternalFrame</code>, or <code>null</code> | |
|      * if no menu bar has been set. | |
|      * | |
|      * @return  the <code>JMenuBar</code> used by this internal frame | |
|      * @see #setJMenuBar | |
| */ | |
| public JMenuBar getJMenuBar() { | |
| return getRootPane().getJMenuBar(); | |
| } | |
|     /** | |
|      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>. | |
|      * | |
|      * @param m  the <code>JMenuBar</code> to use in this internal frame | |
|      * @see #getJMenuBar | |
|      * @deprecated As of Swing version 1.0.3 | |
|      *  replaced by <code>setJMenuBar(JMenuBar m)</code>. | |
| */ | |
| @Deprecated | |
| public void setMenuBar(JMenuBar m) { | |
| JMenuBar oldValue = getMenuBar(); | |
| getRootPane().setJMenuBar(m); | |
| firePropertyChange(MENU_BAR_PROPERTY, oldValue, m); | |
| } | |
|     /** | |
|      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>. | |
|      * | |
|      * @param m  the <code>JMenuBar</code> to use in this internal frame | |
|      * @see #getJMenuBar | |
|      * @beaninfo | |
|      *     bound: true | |
|      *     preferred: true | |
|      *     description: The menu bar for accessing pulldown menus | |
|      *                  from this internal frame. | |
| */ | |
| public void setJMenuBar(JMenuBar m){ | |
| JMenuBar oldValue = getMenuBar(); | |
| getRootPane().setJMenuBar(m); | |
| firePropertyChange(MENU_BAR_PROPERTY, oldValue, m); | |
| } | |
| // implements javax.swing.RootPaneContainer | |
|     /** | |
|      * Returns the content pane for this internal frame. | |
|      * @return the content pane | |
| */ | |
| public Container getContentPane() { | |
| return getRootPane().getContentPane(); | |
| } | |
|     /** | |
|      * Sets this <code>JInternalFrame</code>'s <code>contentPane</code> | |
|      * property. | |
|      * | |
|      * @param c  the content pane for this internal frame | |
|      * | |
|      * @exception java.awt.IllegalComponentStateException (a runtime | |
|      *           exception) if the content pane parameter is <code>null</code> | |
|      * @see RootPaneContainer#getContentPane | |
|      * @beaninfo | |
|      *     bound: true | |
|      *     hidden: true | |
|      *     description: The client area of the internal frame where child | |
|      *                  components are normally inserted. | |
| */ | |
| public void setContentPane(Container c) { | |
| Container oldValue = getContentPane(); | |
| getRootPane().setContentPane(c); | |
| firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c); | |
| } | |
|     /** | |
|      * Returns the layered pane for this internal frame. | |
|      * | |
|      * @return a <code>JLayeredPane</code> object | |
|      * @see RootPaneContainer#setLayeredPane | |
|      * @see RootPaneContainer#getLayeredPane | |
| */ | |
| public JLayeredPane getLayeredPane() { | |
| return getRootPane().getLayeredPane(); | |
| } | |
|     /** | |
|      * Sets this <code>JInternalFrame</code>'s | |
|      * <code>layeredPane</code> property. | |
|      * | |
|      * @param layered the <code>JLayeredPane</code> for this internal frame | |
|      * | |
|      * @exception java.awt.IllegalComponentStateException (a runtime | |
|      *           exception) if the layered pane parameter is <code>null</code> | |
|      * @see RootPaneContainer#setLayeredPane | |
|      * @beaninfo | |
|      *     hidden: true | |
|      *     bound: true | |
|      *     description: The pane which holds the various desktop layers. | |
| */ | |
| public void setLayeredPane(JLayeredPane layered) { | |
| JLayeredPane oldValue = getLayeredPane(); | |
| getRootPane().setLayeredPane(layered); | |
| firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered); | |
| } | |
|     /** | |
|      * Returns the glass pane for this internal frame. | |
|      * | |
|      * @return the glass pane | |
|      * @see RootPaneContainer#setGlassPane | |
| */ | |
| public Component getGlassPane() { | |
| return getRootPane().getGlassPane(); | |
| } | |
|     /** | |
|      * Sets this <code>JInternalFrame</code>'s | |
|      * <code>glassPane</code> property. | |
|      * | |
|      * @param glass the glass pane for this internal frame | |
|      * @see RootPaneContainer#getGlassPane | |
|      * @beaninfo | |
|      *     bound: true | |
|      *     hidden: true | |
|      *     description: A transparent pane used for menu rendering. | |
| */ | |
| public void setGlassPane(Component glass) { | |
| Component oldValue = getGlassPane(); | |
| getRootPane().setGlassPane(glass); | |
| firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass); | |
| } | |
|     /** | |
|      * Returns the <code>rootPane</code> object for this internal frame. | |
|      * | |
|      * @return the <code>rootPane</code> property | |
|      * @see RootPaneContainer#getRootPane | |
| */ | |
| public JRootPane getRootPane() { | |
| return rootPane; | |
| } | |
|     /** | |
|      * Sets the <code>rootPane</code> property | |
|      * for this <code>JInternalFrame</code>. | |
|      * This method is called by the constructor. | |
|      * | |
|      * @param root  the new <code>JRootPane</code> object | |
|      * @beaninfo | |
|      *     bound: true | |
|      *     hidden: true | |
|      *     description: The root pane used by this internal frame. | |
| */ | |
| protected void setRootPane(JRootPane root) { | |
| if(rootPane != null) { | |
| remove(rootPane); | |
| } | |
| JRootPane oldValue = getRootPane(); | |
| rootPane = root; | |
| if(rootPane != null) { | |
| boolean checkingEnabled = isRootPaneCheckingEnabled(); | |
|             try { | |
| setRootPaneCheckingEnabled(false); | |
| add(rootPane, BorderLayout.CENTER); | |
| } | |
|             finally { | |
| setRootPaneCheckingEnabled(checkingEnabled); | |
| } | |
| } | |
| firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root); | |
| } | |
|     /** | |
|      * Sets whether this <code>JInternalFrame</code> can be closed by | |
|      * some user action. | |
|      * @param b a boolean value, where <code>true</code> means this internal frame can be closed | |
|      * @beaninfo | |
|      *     preferred: true | |
|      *           bound: true | |
|      *     description: Indicates whether this internal frame can be closed. | |
| */ | |
|     public void setClosable(boolean b) { | |
| Boolean oldValue = closable ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| closable = b; | |
| firePropertyChange("closable", oldValue, newValue); | |
| } | |
|     /** | |
|      * Returns whether this <code>JInternalFrame</code> can be closed by | |
|      * some user action. | |
|      * @return <code>true</code> if this internal frame can be closed | |
| */ | |
|     public boolean isClosable() { | |
| return closable; | |
| } | |
|     /** | |
|      * Returns whether this <code>JInternalFrame</code> is currently closed. | |
|      * @return <code>true</code> if this internal frame is closed, <code>false</code> otherwise | |
| */ | |
|     public boolean isClosed() { | |
| return isClosed; | |
| } | |
|     /** | |
|      * Closes this internal frame if the argument is <code>true</code>. | |
|      * Do not invoke this method with a <code>false</code> argument; | |
|      * the result of invoking <code>setClosed(false)</code> | |
|      * is unspecified. | |
|      * | |
|      * <p> | |
|      * | |
|      * If the internal frame is already closed, | |
|      * this method does nothing and returns immediately. | |
|      * Otherwise, | |
|      * this method begins by firing | |
|      * an <code>INTERNAL_FRAME_CLOSING</code> event. | |
|      * Then this method sets the <code>closed</code> property to <code>true</code> | |
|      * unless a listener vetoes the property change. | |
|      * This method finishes by making the internal frame | |
|      * invisible and unselected, | |
|      * and then firing an <code>INTERNAL_FRAME_CLOSED</code> event. | |
|      * | |
|      * <p> | |
|      * | |
|      * <b>Note:</b> | |
|      * To reuse an internal frame that has been closed, | |
|      * you must add it to a container | |
|      * (even if you never removed it from its previous container). | |
|      * Typically, this container will be the <code>JDesktopPane</code> | |
|      * that previously contained the internal frame. | |
|      * | |
|      * @param b must be <code>true</code> | |
|      * | |
|      * @exception PropertyVetoException when the attempt to set the | |
|      *            property is vetoed by the <code>JInternalFrame</code> | |
|      * | |
|      * @see #isClosed() | |
|      * @see #setDefaultCloseOperation | |
|      * @see #dispose | |
|      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING | |
|      * | |
|      * @beaninfo | |
|      *           bound: true | |
|      *     constrained: true | |
|      *     description: Indicates whether this internal frame has been closed. | |
| */ | |
| public void setClosed(boolean b) throws PropertyVetoException { | |
| if (isClosed == b) { | |
| return; | |
| } | |
| Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| if (b) { | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); | |
| } | |
| fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue); | |
| isClosed = b; | |
| if (isClosed) { | |
| setVisible(false); | |
| } | |
| firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue); | |
| if (isClosed) { | |
| dispose(); | |
| } else if (!opened) { | |
| /* this bogus -- we haven't defined what | |
| setClosed(false) means. */ | |
| // fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED); | |
| // opened = true; | |
| } | |
| } | |
|     /** | |
|      * Sets whether the <code>JInternalFrame</code> can be resized by some | |
|      * user action. | |
|      * | |
|      * @param b  a boolean, where <code>true</code> means this internal frame can be resized | |
|      * @beaninfo | |
|      *     preferred: true | |
|      *           bound: true | |
|      *     description: Determines whether this internal frame can be resized | |
|      *                  by the user. | |
| */ | |
|     public void setResizable(boolean b) { | |
| Boolean oldValue = resizable ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| resizable = b; | |
| firePropertyChange("resizable", oldValue, newValue); | |
| } | |
|     /** | |
|      * Returns whether the <code>JInternalFrame</code> can be resized | |
|      * by some user action. | |
|      * | |
|      * @return <code>true</code> if this internal frame can be resized, <code>false</code> otherwise | |
| */ | |
|     public boolean isResizable() { | |
|         // don't allow resizing when maximized. | |
| return isMaximum ? false : resizable; | |
| } | |
|     /** | |
|      * Sets the <code>iconable</code> property, | |
|      * which must be <code>true</code> | |
|      * for the user to be able to | |
|      * make the <code>JInternalFrame</code> an icon. | |
|      * Some look and feels might not implement iconification; | |
|      * they will ignore this property. | |
|      * | |
|      * @param b  a boolean, where <code>true</code> means this internal frame can be iconified | |
|      * @beaninfo | |
|      *     preferred: true | |
|                bound: true | |
|      *     description: Determines whether this internal frame can be iconified. | |
| */ | |
|     public void setIconifiable(boolean b) { | |
| Boolean oldValue = iconable ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| iconable = b; | |
| firePropertyChange("iconable", oldValue, newValue); | |
| } | |
|     /** | |
|      * Gets the <code>iconable</code> property, | |
|      * which by default is <code>false</code>. | |
|      * | |
|      * @return the value of the <code>iconable</code> property. | |
|      * | |
|      * @see #setIconifiable | |
| */ | |
|     public boolean isIconifiable() { | |
| return iconable; | |
| } | |
|     /** | |
|      * Returns whether the <code>JInternalFrame</code> is currently iconified. | |
|      * | |
|      * @return <code>true</code> if this internal frame is iconified | |
| */ | |
|     public boolean isIcon() { | |
| return isIcon; | |
| } | |
|     /** | |
|      * Iconifies or de-iconifies this internal frame, | |
|      * if the look and feel supports iconification. | |
|      * If the internal frame's state changes to iconified, | |
|      * this method fires an <code>INTERNAL_FRAME_ICONIFIED</code> event. | |
|      * If the state changes to de-iconified, | |
|      * an <code>INTERNAL_FRAME_DEICONIFIED</code> event is fired. | |
|      * | |
|      * @param b a boolean, where <code>true</code> means to iconify this internal frame and | |
|      *          <code>false</code> means to de-iconify it | |
|      * @exception PropertyVetoException when the attempt to set the | |
|      *            property is vetoed by the <code>JInternalFrame</code> | |
|      * | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_DEICONIFIED | |
|      * | |
|      * @beaninfo | |
|      *           bound: true | |
|      *     constrained: true | |
|      *     description: The image displayed when this internal frame is minimized. | |
| */ | |
| public void setIcon(boolean b) throws PropertyVetoException { | |
| if (isIcon == b) { | |
| return; | |
| } | |
|         /* If an internal frame is being iconified before it has a | |
|            parent, (e.g., client wants it to start iconic), create the | |
|            parent if possible so that we can place the icon in its | |
|            proper place on the desktop. I am not sure the call to | |
|            validate() is necessary, since we are not going to display | |
| this frame yet */ | |
| firePropertyChange("ancestor", null, getParent()); | |
| Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue); | |
| isIcon = b; | |
| firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue); | |
| if (b) | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED); | |
| else | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED); | |
| } | |
|     /** | |
|      * Sets the <code>maximizable</code> property, | |
|      * which determines whether the <code>JInternalFrame</code> | |
|      * can be maximized by | |
|      * some user action. | |
|      * Some look and feels might not support maximizing internal frames; | |
|      * they will ignore this property. | |
|      * | |
|      * @param b <code>true</code> to specify that this internal frame should be maximizable; <code>false</code> to specify that it should not be | |
|      * @beaninfo | |
|      *         bound: true | |
|      *     preferred: true | |
|      *     description: Determines whether this internal frame can be maximized. | |
| */ | |
|     public void setMaximizable(boolean b) { | |
| Boolean oldValue = maximizable ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| maximizable = b; | |
| firePropertyChange("maximizable", oldValue, newValue); | |
| } | |
|     /** | |
|      * Gets the value of the <code>maximizable</code> property. | |
|      * | |
|      * @return the value of the <code>maximizable</code> property | |
|      * @see #setMaximizable | |
| */ | |
|     public boolean isMaximizable() { | |
| return maximizable; | |
| } | |
|     /** | |
|      * Returns whether the <code>JInternalFrame</code> is currently maximized. | |
|      * | |
|      * @return <code>true</code> if this internal frame is maximized, <code>false</code> otherwise | |
| */ | |
|     public boolean isMaximum() { | |
| return isMaximum; | |
| } | |
|     /** | |
|      * Maximizes and restores this internal frame.  A maximized frame is resized to | |
|      * fully fit the <code>JDesktopPane</code> area associated with the | |
|      * <code>JInternalFrame</code>. | |
|      * A restored frame's size is set to the <code>JInternalFrame</code>'s | |
|      * actual size. | |
|      * | |
|      * @param b  a boolean, where <code>true</code> maximizes this internal frame and <code>false</code> | |
|      *           restores it | |
|      * @exception PropertyVetoException when the attempt to set the | |
|      *            property is vetoed by the <code>JInternalFrame</code> | |
|      * @beaninfo | |
|      *     bound: true | |
|      *     constrained: true | |
|      *     description: Indicates whether this internal frame is maximized. | |
| */ | |
| public void setMaximum(boolean b) throws PropertyVetoException { | |
| if (isMaximum == b) { | |
| return; | |
| } | |
| Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE; | |
| fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue); | |
|         /* setting isMaximum above the event firing means that | |
|            property listeners that, for some reason, test it will | |
| get it wrong... See, for example, getNormalBounds() */ | |
| isMaximum = b; | |
| firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue); | |
| } | |
|     /** | |
|      * Returns the title of the <code>JInternalFrame</code>. | |
|      * | |
|      * @return a <code>String</code> containing this internal frame's title | |
|      * @see #setTitle | |
| */ | |
| public String getTitle() { | |
| return title; | |
| } | |
|     /** | |
|      * Sets the <code>JInternalFrame</code> title. <code>title</code> | |
|      * may have a <code>null</code> value. | |
|      * @see #getTitle | |
|      * | |
|      * @param title  the <code>String</code> to display in the title bar | |
|      * @beaninfo | |
|      *     preferred: true | |
|      *     bound: true | |
|      *     description: The text displayed in the title bar. | |
| */ | |
| public void setTitle(String title) { | |
| String oldValue = this.title; | |
| this.title = title; | |
| firePropertyChange(TITLE_PROPERTY, oldValue, title); | |
| } | |
|     /** | |
|      * Selects or deselects the internal frame | |
|      * if it's showing. | |
|      * A <code>JInternalFrame</code> normally draws its title bar | |
|      * differently if it is | |
|      * the selected frame, which indicates to the user that this | |
|      * internal frame has the focus. | |
|      * When this method changes the state of the internal frame | |
|      * from deselected to selected, it fires an | |
|      * <code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> event. | |
|      * If the change is from selected to deselected, | |
|      * an <code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> event | |
|      * is fired. | |
|      * | |
|      * @param selected  a boolean, where <code>true</code> means this internal frame | |
|      *                  should become selected (currently active) | |
|      *                  and <code>false</code> means it should become deselected | |
|      * @exception PropertyVetoException when the attempt to set the | |
|      *            property is vetoed by the <code>JInternalFrame</code> | |
|      * | |
|      * @see #isShowing | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED | |
|      * | |
|      * @beaninfo | |
|      *     constrained: true | |
|      *           bound: true | |
|      *     description: Indicates whether this internal frame is currently | |
|      *                  the active frame. | |
| */ | |
| public void setSelected(boolean selected) throws PropertyVetoException { | |
| // The InternalFrame may already be selected, but the focus | |
| // may be outside it, so restore the focus to the subcomponent | |
|        // which previously had it. See Bug 4302764. | |
| if (selected && isSelected) { | |
| restoreSubcomponentFocus(); | |
| return; | |
| } | |
| // The internal frame or the desktop icon must be showing to allow | |
|         // selection.  We may deselect even if neither is showing. | |
| if ((isSelected == selected) || (selected && | |
| (isIcon ? !desktopIcon.isShowing() : !isShowing()))) { | |
| return; | |
| } | |
| Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE; | |
| Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE; | |
| fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue); | |
| /* We don't want to leave focus in the previously selected | |
| frame, so we have to set it to *something* in case it | |
| doesn't get set in some other way (as if a user clicked on | |
| a component that doesn't request focus). If this call is | |
| happening because the user clicked on a component that will | |
| want focus, then it will get transfered there later. | |
| We test for parent.isShowing() above, because AWT throws a | |
| NPE if you try to request focus on a lightweight before its | |
| parent has been made visible */ | |
| if (selected) { | |
| restoreSubcomponentFocus(); | |
| } | |
| isSelected = selected; | |
| firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue); | |
| if (isSelected) | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED); | |
| else | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED); | |
| repaint(); | |
| } | |
|     /** | |
|      * Returns whether the <code>JInternalFrame</code> is the | |
|      * currently "selected" or active frame. | |
|      * | |
|      * @return <code>true</code> if this internal frame is currently selected (active) | |
|      * @see #setSelected | |
| */ | |
|     public boolean isSelected() { | |
| return isSelected; | |
| } | |
|     /** | |
|      * Sets an image to be displayed in the titlebar of this internal frame (usually | |
|      * in the top-left corner). | |
|      * This image is not the <code>desktopIcon</code> object, which | |
|      * is the image displayed in the <code>JDesktop</code> when | |
|      * this internal frame is iconified. | |
|      * | |
|      * Passing <code>null</code> to this function is valid, | |
|      * but the look and feel | |
|      * can choose the | |
|      * appropriate behavior for that situation, such as displaying no icon | |
|      * or a default icon for the look and feel. | |
|      * | |
|      * @param icon the <code>Icon</code> to display in the title bar | |
|      * @see #getFrameIcon | |
|      * @beaninfo | |
|      *           bound: true | |
|      *     description: The icon shown in the top-left corner of this internal frame. | |
| */ | |
| public void setFrameIcon(Icon icon) { | |
| Icon oldIcon = frameIcon; | |
| frameIcon = icon; | |
| firePropertyChange(FRAME_ICON_PROPERTY, oldIcon, icon); | |
| } | |
|     /** | |
|      * Returns the image displayed in the title bar of this internal frame (usually | |
|      * in the top-left corner). | |
|      * | |
|      * @return the <code>Icon</code> displayed in the title bar | |
|      * @see #setFrameIcon | |
| */ | |
| public Icon getFrameIcon() { | |
| return frameIcon; | |
| } | |
|     /** | |
|       * Convenience method that moves this component to position 0 if its | |
|       * parent is a <code>JLayeredPane</code>. | |
| */ | |
|     public void moveToFront() { | |
| if (isIcon()) { | |
| if (getDesktopIcon().getParent() instanceof JLayeredPane) { | |
| ((JLayeredPane)getDesktopIcon().getParent()). | |
| moveToFront(getDesktopIcon()); | |
| } | |
| } | |
| else if (getParent() instanceof JLayeredPane) { | |
| ((JLayeredPane)getParent()).moveToFront(this); | |
| } | |
| } | |
|     /** | |
|       * Convenience method that moves this component to position -1 if its | |
|       * parent is a <code>JLayeredPane</code>. | |
| */ | |
|     public void moveToBack() { | |
| if (isIcon()) { | |
| if (getDesktopIcon().getParent() instanceof JLayeredPane) { | |
| ((JLayeredPane)getDesktopIcon().getParent()). | |
| moveToBack(getDesktopIcon()); | |
| } | |
| } | |
| else if (getParent() instanceof JLayeredPane) { | |
| ((JLayeredPane)getParent()).moveToBack(this); | |
| } | |
| } | |
|     /** | |
|      * Returns the last <code>Cursor</code> that was set by the | |
|      * <code>setCursor</code> method that is not a resizable | |
|      * <code>Cursor</code>. | |
|      * | |
|      * @return the last non-resizable <code>Cursor</code> | |
|      * @since 1.6 | |
| */ | |
| public Cursor getLastCursor() { | |
| return lastCursor; | |
| } | |
|     /** | |
|      * {@inheritDoc} | |
|      * @since 1.6 | |
| */ | |
| public void setCursor(Cursor cursor) { | |
| if (cursor == null) { | |
| lastCursor = null; | |
| super.setCursor(cursor); | |
| return; | |
| } | |
| int type = cursor.getType(); | |
| if (!(type == Cursor.SW_RESIZE_CURSOR || | |
| type == Cursor.SE_RESIZE_CURSOR || | |
| type == Cursor.NW_RESIZE_CURSOR || | |
| type == Cursor.NE_RESIZE_CURSOR || | |
| type == Cursor.N_RESIZE_CURSOR || | |
| type == Cursor.S_RESIZE_CURSOR || | |
| type == Cursor.W_RESIZE_CURSOR || | |
| type == Cursor.E_RESIZE_CURSOR)) { | |
| lastCursor = cursor; | |
| } | |
| super.setCursor(cursor); | |
| } | |
|     /** | |
|      * Convenience method for setting the layer attribute of this component. | |
|      * | |
|      * @param layer  an <code>Integer</code> object specifying this | |
|      *          frame's desktop layer | |
|      * @see JLayeredPane | |
|      * @beaninfo | |
|      *     expert: true | |
|      *     description: Specifies what desktop layer is used. | |
| */ | |
| public void setLayer(Integer layer) { | |
| if(getParent() != null && getParent() instanceof JLayeredPane) { | |
| // Normally we want to do this, as it causes the LayeredPane | |
|             // to draw properly. | |
| JLayeredPane p = (JLayeredPane)getParent(); | |
| p.setLayer(this, layer.intValue(), p.getPosition(this)); | |
|         } else { | |
|              // Try to do the right thing | |
| JLayeredPane.putLayer(this, layer.intValue()); | |
| if(getParent() != null) | |
| getParent().repaint(getX(), getY(), getWidth(), getHeight()); | |
| } | |
| } | |
|     /** | |
|      * Convenience method for setting the layer attribute of this component. | |
|      * The method <code>setLayer(Integer)</code> should be used for | |
|      * layer values predefined in <code>JLayeredPane</code>. | |
|      * When using <code>setLayer(int)</code>, care must be taken not to | |
|      * accidentally clash with those values. | |
|      * | |
|      * @param layer  an integer specifying this internal frame's desktop layer | |
|      * | |
|      * @since 1.3 | |
|      * | |
|      * @see #setLayer(Integer) | |
|      * @see JLayeredPane | |
|      * @beaninfo | |
|      *     expert: true | |
|      *     description: Specifies what desktop layer is used. | |
| */ | |
|     public void setLayer(int layer) { | |
| this.setLayer(Integer.valueOf(layer)); | |
| } | |
|     /** | |
|      * Convenience method for getting the layer attribute of this component. | |
|      * | |
|      * @return  an <code>Integer</code> object specifying this | |
|      *          frame's desktop layer | |
|      * @see JLayeredPane | |
| */ | |
|     public int getLayer() { | |
| return JLayeredPane.getLayer(this); | |
| } | |
|     /** | |
|       * Convenience method that searches the ancestor hierarchy for a | |
|       * <code>JDesktop</code> instance. If <code>JInternalFrame</code> | |
|       * finds none, the <code>desktopIcon</code> tree is searched. | |
|       * | |
|       * @return the <code>JDesktopPane</code> this internal frame belongs to, | |
|       *         or <code>null</code> if none is found | |
| */ | |
| public JDesktopPane getDesktopPane() { | |
| Container p; | |
|         // Search upward for desktop | |
| p = getParent(); | |
| while(p != null && !(p instanceof JDesktopPane)) | |
| p = p.getParent(); | |
| if(p == null) { | |
|            // search its icon parent for desktop | |
| p = getDesktopIcon().getParent(); | |
| while(p != null && !(p instanceof JDesktopPane)) | |
| p = p.getParent(); | |
| } | |
| return (JDesktopPane)p; | |
| } | |
|     /** | |
|      * Sets the <code>JDesktopIcon</code> associated with this | |
|      * <code>JInternalFrame</code>. | |
|      * | |
|      * @param d the <code>JDesktopIcon</code> to display on the desktop | |
|      * @see #getDesktopIcon | |
|      * @beaninfo | |
|      *           bound: true | |
|      *     description: The icon shown when this internal frame is minimized. | |
| */ | |
|     public void setDesktopIcon(JDesktopIcon d) { | |
| JDesktopIcon oldValue = getDesktopIcon(); | |
| desktopIcon = d; | |
| firePropertyChange("desktopIcon", oldValue, d); | |
| } | |
|     /** | |
|      * Returns the <code>JDesktopIcon</code> used when this | |
|      * <code>JInternalFrame</code> is iconified. | |
|      * | |
|      * @return the <code>JDesktopIcon</code> displayed on the desktop | |
|      * @see #setDesktopIcon | |
| */ | |
|     public JDesktopIcon getDesktopIcon() { | |
| return desktopIcon; | |
| } | |
|     /** | |
|      * If the <code>JInternalFrame</code> is not in maximized state, returns | |
|      * <code>getBounds()</code>; otherwise, returns the bounds that the | |
|      * <code>JInternalFrame</code> would be restored to. | |
|      * | |
|      * @return a <code>Rectangle</code> containing the bounds of this | |
|      *          frame when in the normal state | |
|      * @since 1.3 | |
| */ | |
| public Rectangle getNormalBounds() { | |
| /* we used to test (!isMaximum) here, but since this | |
| method is used by the property listener for the | |
| IS_MAXIMUM_PROPERTY, it ended up getting the wrong | |
| answer... Since normalBounds get set to null when the | |
| frame is restored, this should work better */ | |
| if (normalBounds != null) { | |
| return normalBounds; | |
|       } else { | |
| return getBounds(); | |
| } | |
| } | |
|     /** | |
|      * Sets the normal bounds for this internal frame, the bounds that | |
|      * this internal frame would be restored to from its maximized state. | |
|      * This method is intended for use only by desktop managers. | |
|      * | |
|      * @param r the bounds that this internal frame should be restored to | |
|      * @since 1.3 | |
| */ | |
| public void setNormalBounds(Rectangle r) { | |
| normalBounds = r; | |
| } | |
|     /** | |
|      * If this <code>JInternalFrame</code> is active, | |
|      * returns the child that has focus. | |
|      * Otherwise, returns <code>null</code>. | |
|      * | |
|      * @return the component with focus, or <code>null</code> if no children have focus | |
|      * @since 1.3 | |
| */ | |
| public Component getFocusOwner() { | |
| if (isSelected()) { | |
| return lastFocusOwner; | |
| } | |
| return null; | |
| } | |
|     /** | |
|      * Returns the child component of this <code>JInternalFrame</code> | |
|      * that will receive the | |
|      * focus when this <code>JInternalFrame</code> is selected. | |
|      * If this <code>JInternalFrame</code> is | |
|      * currently selected, this method returns the same component as | |
|      * the <code>getFocusOwner</code> method. | |
|      * If this <code>JInternalFrame</code> is not selected, | |
|      * then the child component that most recently requested focus will be | |
|      * returned. If no child component has ever requested focus, then this | |
|      * <code>JInternalFrame</code>'s initial focusable component is returned. | |
|      * If no such | |
|      * child exists, then this <code>JInternalFrame</code>'s default component | |
|      * to focus is returned. | |
|      * | |
|      * @return the child component that will receive focus when this | |
|      *         <code>JInternalFrame</code> is selected | |
|      * @see #getFocusOwner | |
|      * @see #isSelected | |
|      * @since 1.4 | |
| */ | |
| public Component getMostRecentFocusOwner() { | |
| if (isSelected()) { | |
| return getFocusOwner(); | |
| } | |
| if (lastFocusOwner != null) { | |
| return lastFocusOwner; | |
| } | |
| FocusTraversalPolicy policy = getFocusTraversalPolicy(); | |
| if (policy instanceof InternalFrameFocusTraversalPolicy) { | |
| return ((InternalFrameFocusTraversalPolicy)policy). | |
| getInitialComponent(this); | |
| } | |
| Component toFocus = policy.getDefaultComponent(this); | |
| if (toFocus != null) { | |
| return toFocus; | |
| } | |
| return getContentPane(); | |
| } | |
|     /** | |
|      * Requests the internal frame to restore focus to the | |
|      * last subcomponent that had focus. This is used by the UI when | |
|      * the user selected this internal frame -- | |
|      * for example, by clicking on the title bar. | |
|      * | |
|      * @since 1.3 | |
| */ | |
|     public void restoreSubcomponentFocus() { | |
| if (isIcon()) { | |
| SwingUtilities2.compositeRequestFocus(getDesktopIcon()); | |
| } | |
|         else { | |
| Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); | |
| if ((component == null) || !SwingUtilities.isDescendingFrom(component, this)) { | |
| // FocusPropertyChangeListener will eventually update | |
| // lastFocusOwner. As focus requests are asynchronous | |
| // lastFocusOwner may be accessed before it has been correctly | |
| // updated. To avoid any problems, lastFocusOwner is immediately | |
|                 // set, assuming the request will succeed. | |
| setLastFocusOwner(getMostRecentFocusOwner()); | |
| if (lastFocusOwner == null) { | |
| // Make sure focus is restored somewhere, so that | |
| // we don't leave a focused component in another frame while | |
|                     // this frame is selected. | |
| setLastFocusOwner(getContentPane()); | |
| } | |
| lastFocusOwner.requestFocus(); | |
| } | |
| } | |
| } | |
| private void setLastFocusOwner(Component component) { | |
| lastFocusOwner = component; | |
| } | |
|     /** | |
|      * Moves and resizes this component.  Unlike other components, | |
|      * this implementation also forces re-layout, so that frame | |
|      * decorations such as the title bar are always redisplayed. | |
|      * | |
|      * @param x  an integer giving the component's new horizontal position | |
|      *           measured in pixels from the left of its container | |
|      * @param y  an integer giving the component's new vertical position, | |
|      *           measured in pixels from the bottom of its container | |
|      * @param width  an integer giving the component's new width in pixels | |
|      * @param height an integer giving the component's new height in pixels | |
| */ | |
|     public void reshape(int x, int y, int width, int height) { | |
| super.reshape(x, y, width, height); | |
| validate(); | |
| repaint(); | |
| } | |
| /////////////////////////// | |
| // Frame/Window equivalents | |
| /////////////////////////// | |
|     /** | |
|      * Adds the specified listener to receive internal | |
|      * frame events from this internal frame. | |
|      * | |
|      * @param l the internal frame listener | |
| */ | |
| public void addInternalFrameListener(InternalFrameListener l) { // remind: sync ?? | |
| listenerList.add(InternalFrameListener.class, l); | |
| // remind: needed? | |
| enableEvents(0); // turn on the newEventsOnly flag in Component. | |
| } | |
|     /** | |
|      * Removes the specified internal frame listener so that it no longer | |
|      * receives internal frame events from this internal frame. | |
|      * | |
|      * @param l the internal frame listener | |
| */ | |
| public void removeInternalFrameListener(InternalFrameListener l) { // remind: sync?? | |
| listenerList.remove(InternalFrameListener.class, l); | |
| } | |
|     /** | |
|      * Returns an array of all the <code>InternalFrameListener</code>s added | |
|      * to this <code>JInternalFrame</code> with | |
|      * <code>addInternalFrameListener</code>. | |
|      * | |
|      * @return all of the <code>InternalFrameListener</code>s added or an empty | |
|      *         array if no listeners have been added | |
|      * @since 1.4 | |
|      * | |
|      * @see #addInternalFrameListener | |
| */ | |
| public InternalFrameListener[] getInternalFrameListeners() { | |
| return listenerList.getListeners(InternalFrameListener.class); | |
| } | |
| // remind: name ok? all one method ok? need to be synchronized? | |
|     /** | |
|      * Fires an internal frame event. | |
|      * | |
|      * @param id  the type of the event being fired; one of the following: | |
|      * <ul> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_OPENED</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSING</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSED</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ICONIFIED</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> | |
|      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> | |
|      * </ul> | |
|      * If the event type is not one of the above, nothing happens. | |
| */ | |
|     protected void fireInternalFrameEvent(int id){ | |
| Object[] listeners = listenerList.getListenerList(); | |
| InternalFrameEvent e = null; | |
| for (int i = listeners.length -2; i >=0; i -= 2){ | |
| if (listeners[i] == InternalFrameListener.class){ | |
| if (e == null){ | |
| e = new InternalFrameEvent(this, id); | |
|             //      System.out.println("InternalFrameEvent: " + e.paramString()); | |
| } | |
| switch(e.getID()) { | |
| case InternalFrameEvent.INTERNAL_FRAME_OPENED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_CLOSING: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_CLOSED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e); | |
| break; | |
| case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED: | |
| ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| /* we could do it off the event, but at the moment, that's not how | |
| I'm implementing it */ | |
|       //      if (id == InternalFrameEvent.INTERNAL_FRAME_CLOSING) { | |
| // doDefaultCloseAction(); | |
| // } | |
| } | |
|     /** | |
|      * Fires an | |
|      * <code>INTERNAL_FRAME_CLOSING</code> event | |
|      * and then performs the action specified by | |
|      * the internal frame's default close operation. | |
|      * This method is typically invoked by the | |
|      * look-and-feel-implemented action handler | |
|      * for the internal frame's close button. | |
|      * | |
|      * @since 1.3 | |
|      * @see #setDefaultCloseOperation | |
|      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING | |
| */ | |
|     public void doDefaultCloseAction() { | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); | |
| switch(defaultCloseOperation) { | |
| case DO_NOTHING_ON_CLOSE: | |
| break; | |
| case HIDE_ON_CLOSE: | |
| setVisible(false); | |
| if (isSelected()) | |
|                 try { | |
| setSelected(false); | |
| } catch (PropertyVetoException pve) {} | |
|             /* should this activate the next frame? that's really | |
| desktopmanager's policy... */ | |
| break; | |
| case DISPOSE_ON_CLOSE: | |
|               try { | |
| fireVetoableChange(IS_CLOSED_PROPERTY, Boolean.FALSE, | |
| Boolean.TRUE); | |
| isClosed = true; | |
| setVisible(false); | |
| firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, | |
| Boolean.TRUE); | |
| dispose(); | |
| } catch (PropertyVetoException pve) {} | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
|     /** | |
|      * Sets the operation that will happen by default when | |
|      * the user initiates a "close" on this internal frame. | |
|      * The possible choices are: | |
|      * <br><br> | |
|      * <dl> | |
|      * <dt><code>DO_NOTHING_ON_CLOSE</code> | |
|      * <dd> Do nothing. | |
|      *      This requires the program to handle the operation | |
|      *      in the <code>internalFrameClosing</code> method | |
|      *      of a registered <code>InternalFrameListener</code> object. | |
|      * <dt><code>HIDE_ON_CLOSE</code> | |
|      * <dd> Automatically make the internal frame invisible. | |
|      * <dt><code>DISPOSE_ON_CLOSE</code> | |
|      * <dd> Automatically dispose of the internal frame. | |
|      * </dl> | |
|      * <p> | |
|      * The default value is <code>DISPOSE_ON_CLOSE</code>. | |
|      * Before performing the specified close operation, | |
|      * the internal frame fires | |
|      * an <code>INTERNAL_FRAME_CLOSING</code> event. | |
|      * | |
|      * @param operation one of the following constants defined in | |
|      *                  <code>javax.swing.WindowConstants</code> | |
|      *                  (an interface implemented by | |
|      *                  <code>JInternalFrame</code>): | |
|      *                  <code>DO_NOTHING_ON_CLOSE</code>, | |
|      *                  <code>HIDE_ON_CLOSE</code>, or | |
|      *                  <code>DISPOSE_ON_CLOSE</code> | |
|      * | |
|      * @see #addInternalFrameListener | |
|      * @see #getDefaultCloseOperation | |
|      * @see #setVisible | |
|      * @see #dispose | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_CLOSING | |
| */ | |
|     public void setDefaultCloseOperation(int operation) { | |
| this.defaultCloseOperation = operation; | |
| } | |
|    /** | |
|     * Returns the default operation that occurs when the user | |
|     * initiates a "close" on this internal frame. | |
|     * @return the operation that will occur when the user closes the internal | |
|     *         frame | |
|     * @see #setDefaultCloseOperation | |
| */ | |
|     public int getDefaultCloseOperation() { | |
| return defaultCloseOperation; | |
| } | |
|     /** | |
|      * Causes subcomponents of this <code>JInternalFrame</code> | |
|      * to be laid out at their preferred size.  Internal frames that are | |
|      * iconized or maximized are first restored and then packed.  If the | |
|      * internal frame is unable to be restored its state is not changed | |
|      * and will not be packed. | |
|      * | |
|      * @see       java.awt.Window#pack | |
| */ | |
|     public void pack() { | |
|         try { | |
| if (isIcon()) { | |
| setIcon(false); | |
| } else if (isMaximum()) { | |
| setMaximum(false); | |
| } | |
| } catch(PropertyVetoException e) { | |
| return; | |
| } | |
| setSize(getPreferredSize()); | |
| validate(); | |
| } | |
|     /** | |
|      * If the internal frame is not visible, | |
|      * brings the internal frame to the front, | |
|      * makes it visible, | |
|      * and attempts to select it. | |
|      * The first time the internal frame is made visible, | |
|      * this method also fires an <code>INTERNAL_FRAME_OPENED</code> event. | |
|      * This method does nothing if the internal frame is already visible. | |
|      * Invoking this method | |
|      * has the same result as invoking | |
|      * <code>setVisible(true)</code>. | |
|      * | |
|      * @see #moveToFront | |
|      * @see #setSelected | |
|      * @see InternalFrameEvent#INTERNAL_FRAME_OPENED | |
|      * @see #setVisible | |
| */ | |
|     public void show() { | |
|         // bug 4312922 | |
| if (isVisible()) { | |
|             //match the behavior of setVisible(true): do nothing | |
| return; | |
| } | |
|         // bug 4149505 | |
| if (!opened) { | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED); | |
| opened = true; | |
| } | |
|         /* icon default visibility is false; set it to true so that it shows | |
| up when user iconifies frame */ | |
| getDesktopIcon().setVisible(true); | |
| toFront(); | |
| super.show(); | |
| if (isIcon) { | |
| return; | |
| } | |
| if (!isSelected()) { | |
|             try { | |
| setSelected(true); | |
| } catch (PropertyVetoException pve) {} | |
| } | |
| } | |
|     public void hide() { | |
| if (isIcon()) { | |
| getDesktopIcon().setVisible(false); | |
| } | |
| super.hide(); | |
| } | |
|     /** | |
|      * Makes this internal frame | |
|      * invisible, unselected, and closed. | |
|      * If the frame is not already closed, | |
|      * this method fires an | |
|      * <code>INTERNAL_FRAME_CLOSED</code> event. | |
|      * The results of invoking this method are similar to | |
|      * <code>setClosed(true)</code>, | |
|      * but <code>dispose</code> always succeeds in closing | |
|      * the internal frame and does not fire | |
|      * an <code>INTERNAL_FRAME_CLOSING</code> event. | |
|      * | |
|      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSED | |
|      * @see #setVisible | |
|      * @see #setSelected | |
|      * @see #setClosed | |
| */ | |
|     public void dispose() { | |
| if (isVisible()) { | |
| setVisible(false); | |
| } | |
| if (isSelected()) { | |
|             try { | |
| setSelected(false); | |
| } catch (PropertyVetoException pve) {} | |
| } | |
| if (!isClosed) { | |
| firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE); | |
| isClosed = true; | |
| } | |
| fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED); | |
| } | |
|     /** | |
|      * Brings this internal frame to the front. | |
|      * Places this internal frame  at the top of the stacking order | |
|      * and makes the corresponding adjustment to other visible internal | |
|      * frames. | |
|      * | |
|      * @see       java.awt.Window#toFront | |
|      * @see       #moveToFront | |
| */ | |
|     public void toFront() { | |
| moveToFront(); | |
| } | |
|     /** | |
|      * Sends this internal frame to the back. | |
|      * Places this internal frame at the bottom of the stacking order | |
|      * and makes the corresponding adjustment to other visible | |
|      * internal frames. | |
|      * | |
|      * @see       java.awt.Window#toBack | |
|      * @see       #moveToBack | |
| */ | |
|     public void toBack() { | |
| moveToBack(); | |
| } | |
|     /** | |
|      * Does nothing because <code>JInternalFrame</code>s must always be roots of a focus | |
|      * traversal cycle. | |
|      * | |
|      * @param focusCycleRoot this value is ignored | |
|      * @see #isFocusCycleRoot | |
|      * @see java.awt.Container#setFocusTraversalPolicy | |
|      * @see java.awt.Container#getFocusTraversalPolicy | |
|      * @since 1.4 | |
| */ | |
|     public final void setFocusCycleRoot(boolean focusCycleRoot) { | |
| } | |
|     /** | |
|      * Always returns <code>true</code> because all <code>JInternalFrame</code>s must be | |
|      * roots of a focus traversal cycle. | |
|      * | |
|      * @return <code>true</code> | |
|      * @see #setFocusCycleRoot | |
|      * @see java.awt.Container#setFocusTraversalPolicy | |
|      * @see java.awt.Container#getFocusTraversalPolicy | |
|      * @since 1.4 | |
| */ | |
|     public final boolean isFocusCycleRoot() { | |
| return true; | |
| } | |
|     /** | |
|      * Always returns <code>null</code> because <code>JInternalFrame</code>s | |
|      * must always be roots of a focus | |
|      * traversal cycle. | |
|      * | |
|      * @return <code>null</code> | |
|      * @see java.awt.Container#isFocusCycleRoot() | |
|      * @since 1.4 | |
| */ | |
| public final Container getFocusCycleRootAncestor() { | |
| return null; | |
| } | |
|     /** | |
|      * Gets the warning string that is displayed with this internal frame. | |
|      * Since an internal frame is always secure (since it's fully | |
|      * contained within a window that might need a warning string) | |
|      * this method always returns <code>null</code>. | |
|      * @return    <code>null</code> | |
|      * @see       java.awt.Window#getWarningString | |
| */ | |
| public final String getWarningString() { | |
| return null; | |
| } | |
|     /** | |
|      * See <code>readObject</code> and <code>writeObject</code> | |
|      * in <code>JComponent</code> for more | |
|      * information about serialization in Swing. | |
| */ | |
| private void writeObject(ObjectOutputStream s) throws IOException { | |
| s.defaultWriteObject(); | |
| if (getUIClassID().equals(uiClassID)) { | |
| byte count = JComponent.getWriteObjCounter(this); | |
| JComponent.setWriteObjCounter(this, --count); | |
| if (count == 0 && ui != null) { | |
| boolean old = isRootPaneCheckingEnabled(); | |
|                 try { | |
| setRootPaneCheckingEnabled(false); | |
| ui.installUI(this); | |
|                 } finally { | |
| setRootPaneCheckingEnabled(old); | |
| } | |
| } | |
| } | |
| } | |
|     /* Called from the JComponent's EnableSerializationFocusListener to | |
|      * do any Swing-specific pre-serialization configuration. | |
| */ | |
|     void compWriteObjectNotify() { | |
|       // need to disable rootpane checking for InternalFrame: 4172083 | |
| boolean old = isRootPaneCheckingEnabled(); | |
|       try { | |
| setRootPaneCheckingEnabled(false); | |
| super.compWriteObjectNotify(); | |
| } | |
|       finally { | |
| setRootPaneCheckingEnabled(old); | |
| } | |
| } | |
|     /** | |
|      * Returns a string representation of this <code>JInternalFrame</code>. | |
|      * This method | |
|      * is intended to be used only for debugging purposes, and the | |
|      * content and format of the returned string may vary between | |
|      * implementations. The returned string may be empty but may not | |
|      * be <code>null</code>. | |
|      * | |
|      * @return  a string representation of this <code>JInternalFrame</code> | |
| */ | |
| protected String paramString() { | |
| String rootPaneString = (rootPane != null ? | |
| rootPane.toString() : ""); | |
| String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ? | |
| "true" : "false"); | |
| String closableString = (closable ? "true" : "false"); | |
| String isClosedString = (isClosed ? "true" : "false"); | |
| String maximizableString = (maximizable ? "true" : "false"); | |
| String isMaximumString = (isMaximum ? "true" : "false"); | |
| String iconableString = (iconable ? "true" : "false"); | |
| String isIconString = (isIcon ? "true" : "false"); | |
| String resizableString = (resizable ? "true" : "false"); | |
| String isSelectedString = (isSelected ? "true" : "false"); | |
| String frameIconString = (frameIcon != null ? | |
| frameIcon.toString() : ""); | |
| String titleString = (title != null ? | |
| title : ""); | |
| String desktopIconString = (desktopIcon != null ? | |
| desktopIcon.toString() : ""); | |
| String openedString = (opened ? "true" : "false"); | |
| String defaultCloseOperationString; | |
| if (defaultCloseOperation == HIDE_ON_CLOSE) { | |
| defaultCloseOperationString = "HIDE_ON_CLOSE"; | |
| } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) { | |
| defaultCloseOperationString = "DISPOSE_ON_CLOSE"; | |
| } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) { | |
| defaultCloseOperationString = "DO_NOTHING_ON_CLOSE"; | |
| } else defaultCloseOperationString = ""; | |
| return super.paramString() + | |
| ",closable=" + closableString + | |
| ",defaultCloseOperation=" + defaultCloseOperationString + | |
| ",desktopIcon=" + desktopIconString + | |
| ",frameIcon=" + frameIconString + | |
| ",iconable=" + iconableString + | |
| ",isClosed=" + isClosedString + | |
| ",isIcon=" + isIconString + | |
| ",isMaximum=" + isMaximumString + | |
| ",isSelected=" + isSelectedString + | |
| ",maximizable=" + maximizableString + | |
| ",opened=" + openedString + | |
| ",resizable=" + resizableString + | |
| ",rootPane=" + rootPaneString + | |
| ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString + | |
| ",title=" + titleString; | |
| } | |
| // ======= begin optimized frame dragging defence code ============== | |
| boolean isDragging = false; | |
| boolean danger = false; | |
|     /** | |
|      * Overridden to allow optimized painting when the | |
|      * internal frame is being dragged. | |
| */ | |
| protected void paintComponent(Graphics g) { | |
| if (isDragging) { | |
|         //         System.out.println("ouch"); | |
| danger = true; | |
| } | |
| super.paintComponent(g); | |
| } | |
| // ======= end optimized frame dragging defence code ============== | |
| ///////////////// | |
| // Accessibility support | |
| //////////////// | |
|     /** | |
|      * Gets the <code>AccessibleContext</code> associated with this | |
|      * <code>JInternalFrame</code>. | |
|      * For internal frames, the <code>AccessibleContext</code> | |
|      * takes the form of an | |
|      * <code>AccessibleJInternalFrame</code> object. | |
|      * A new <code>AccessibleJInternalFrame</code> instance is created if necessary. | |
|      * | |
|      * @return an <code>AccessibleJInternalFrame</code> that serves as the | |
|      *         <code>AccessibleContext</code> of this | |
|      *         <code>JInternalFrame</code> | |
|      * @see AccessibleJInternalFrame | |
| */ | |
| public AccessibleContext getAccessibleContext() { | |
|         if (accessibleContext == null) { | |
| accessibleContext = new AccessibleJInternalFrame(); | |
| } | |
| return accessibleContext; | |
| } | |
|     /** | |
|      * This class implements accessibility support for the | |
|      * <code>JInternalFrame</code> class.  It provides an implementation of the | |
|      * Java Accessibility API appropriate to internal frame user-interface | |
|      * elements. | |
|      * <p> | |
|      * <strong>Warning:</strong> | |
|      * Serialized objects of this class will not be compatible with | |
|      * future Swing releases. The current serialization support is | |
|      * appropriate for short term storage or RMI between applications running | |
|      * the same version of Swing.  As of 1.4, support for long term storage | |
|      * of all JavaBeans™ | |
|      * has been added to the <code>java.beans</code> package. | |
|      * Please see {@link java.beans.XMLEncoder}. | |
| */ | |
| protected class AccessibleJInternalFrame extends AccessibleJComponent | |
| implements AccessibleValue { | |
|         /** | |
|          * Get the accessible name of this object. | |
|          * | |
|          * @return the localized name of the object -- can be <code>null</code> if this | |
|          * object does not have a name | |
|          * @see #setAccessibleName | |
| */ | |
| public String getAccessibleName() { | |
| String name = accessibleName; | |
| if (name == null) { | |
| name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); | |
| } | |
| if (name == null) { | |
| name = getTitle(); | |
| } | |
| return name; | |
| } | |
|         /** | |
|          * Get the role of this object. | |
|          * | |
|          * @return an instance of AccessibleRole describing the role of the | |
|          * object | |
|          * @see AccessibleRole | |
| */ | |
| public AccessibleRole getAccessibleRole() { | |
| return AccessibleRole.INTERNAL_FRAME; | |
| } | |
|         /** | |
|          * Gets the AccessibleValue associated with this object.  In the | |
|          * implementation of the Java Accessibility API for this class, | |
|          * returns this object, which is responsible for implementing the | |
|          * <code>AccessibleValue</code> interface on behalf of itself. | |
|          * | |
|          * @return this object | |
| */ | |
| public AccessibleValue getAccessibleValue() { | |
| return this; | |
| } | |
| // | |
| // AccessibleValue methods | |
| // | |
|         /** | |
|          * Get the value of this object as a Number. | |
|          * | |
|          * @return value of the object -- can be <code>null</code> if this object does not | |
|          * have a value | |
| */ | |
| public Number getCurrentAccessibleValue() { | |
| return Integer.valueOf(getLayer()); | |
| } | |
|         /** | |
|          * Set the value of this object as a Number. | |
|          * | |
|          * @return <code>true</code> if the value was set | |
| */ | |
| public boolean setCurrentAccessibleValue(Number n) { | |
|             // TIGER - 4422535 | |
| if (n == null) { | |
| return false; | |
| } | |
| setLayer(new Integer(n.intValue())); | |
| return true; | |
| } | |
|         /** | |
|          * Get the minimum value of this object as a Number. | |
|          * | |
|          * @return Minimum value of the object; <code>null</code> if this object does not | |
|          * have a minimum value | |
| */ | |
| public Number getMinimumAccessibleValue() { | |
| return Integer.MIN_VALUE; | |
| } | |
|         /** | |
|          * Get the maximum value of this object as a Number. | |
|          * | |
|          * @return Maximum value of the object; <code>null</code> if this object does not | |
|          * have a maximum value | |
| */ | |
| public Number getMaximumAccessibleValue() { | |
| return Integer.MAX_VALUE; | |
| } | |
| } // AccessibleJInternalFrame | |
|     /** | |
|      * This component represents an iconified version of a | |
|      * <code>JInternalFrame</code>. | |
|      * This API should NOT BE USED by Swing applications, as it will go | |
|      * away in future versions of Swing as its functionality is moved into | |
|      * <code>JInternalFrame</code>.  This class is public only so that | |
|      * UI objects can display a desktop icon.  If an application | |
|      * wants to display a desktop icon, it should create a | |
|      * <code>JInternalFrame</code> instance and iconify it. | |
|      * <p> | |
|      * <strong>Warning:</strong> | |
|      * Serialized objects of this class will not be compatible with | |
|      * future Swing releases. The current serialization support is | |
|      * appropriate for short term storage or RMI between applications running | |
|      * the same version of Swing.  As of 1.4, support for long term storage | |
|      * of all JavaBeans™ | |
|      * has been added to the <code>java.beans</code> package. | |
|      * Please see {@link java.beans.XMLEncoder}. | |
|      * | |
|      * @author David Kloba | |
| */ | |
| static public class JDesktopIcon extends JComponent implements Accessible | |
|     { | |
| JInternalFrame internalFrame; | |
|         /** | |
|          * Creates an icon for an internal frame. | |
|          * | |
|          * @param f  the <code>JInternalFrame</code> | |
|          *              for which the icon is created | |
| */ | |
| public JDesktopIcon(JInternalFrame f) { | |
| setVisible(false); | |
| setInternalFrame(f); | |
| updateUI(); | |
| } | |
|         /** | |
|          * Returns the look-and-feel object that renders this component. | |
|          * | |
|          * @return the <code>DesktopIconUI</code> object that renders | |
|          *              this component | |
| */ | |
| public DesktopIconUI getUI() { | |
| return (DesktopIconUI)ui; | |
| } | |
|         /** | |
|          * Sets the look-and-feel object that renders this component. | |
|          * | |
|          * @param ui  the <code>DesktopIconUI</code> look-and-feel object | |
|          * @see UIDefaults#getUI | |
| */ | |
| public void setUI(DesktopIconUI ui) { | |
| super.setUI(ui); | |
| } | |
|         /** | |
|          * Returns the <code>JInternalFrame</code> that this | |
|          * <code>DesktopIcon</code> is associated with. | |
|          * | |
|          * @return the <code>JInternalFrame</code> with which this icon | |
|          *              is associated | |
| */ | |
| public JInternalFrame getInternalFrame() { | |
| return internalFrame; | |
| } | |
|         /** | |
|          * Sets the <code>JInternalFrame</code> with which this | |
|          * <code>DesktopIcon</code> is associated. | |
|          * | |
|          * @param f  the <code>JInternalFrame</code> with which this icon | |
|          *              is associated | |
| */ | |
| public void setInternalFrame(JInternalFrame f) { | |
| internalFrame = f; | |
| } | |
|         /** | |
|          * Convenience method to ask the icon for the <code>Desktop</code> | |
|          * object it belongs to. | |
|          * | |
|          * @return the <code>JDesktopPane</code> that contains this | |
|          *           icon's internal frame, or <code>null</code> if none found | |
| */ | |
| public JDesktopPane getDesktopPane() { | |
| if(getInternalFrame() != null) | |
| return getInternalFrame().getDesktopPane(); | |
| return null; | |
| } | |
|         /** | |
|          * Notification from the <code>UIManager</code> that the look and feel | |
|          * has changed. | |
|          * Replaces the current UI object with the latest version from the | |
|          * <code>UIManager</code>. | |
|          * | |
|          * @see JComponent#updateUI | |
| */ | |
|         public void updateUI() { | |
| boolean hadUI = (ui != null); | |
| setUI((DesktopIconUI)UIManager.getUI(this)); | |
| invalidate(); | |
| Dimension r = getPreferredSize(); | |
| setSize(r.width, r.height); | |
| if (internalFrame != null && internalFrame.getUI() != null) { // don't do this if UI not created yet | |
| SwingUtilities.updateComponentTreeUI(internalFrame); | |
| } | |
| } | |
|         /* This method is called if updateUI was called on the associated | |
|          * JInternalFrame.  It's necessary to avoid infinite recursion. | |
| */ | |
|         void updateUIWhenHidden() { | |
|             /* Update this UI and any associated internal frame */ | |
| setUI((DesktopIconUI)UIManager.getUI(this)); | |
| Dimension r = getPreferredSize(); | |
| setSize(r.width, r.height); | |
| invalidate(); | |
| Component[] children = getComponents(); | |
| if (children != null) { | |
| for (Component child : children) { | |
| SwingUtilities.updateComponentTreeUI(child); | |
| } | |
| } | |
| } | |
|         /** | |
|          * Returns the name of the look-and-feel | |
|          * class that renders this component. | |
|          * | |
|          * @return the string "DesktopIconUI" | |
|          * @see JComponent#getUIClassID | |
|          * @see UIDefaults#getUI | |
| */ | |
| public String getUIClassID() { | |
|             return "DesktopIconUI"; | |
| } | |
| //////////////// | |
| // Serialization support | |
|         //////////////// | |
| private void writeObject(ObjectOutputStream s) throws IOException { | |
| s.defaultWriteObject(); | |
| if (getUIClassID().equals("DesktopIconUI")) { | |
| byte count = JComponent.getWriteObjCounter(this); | |
| JComponent.setWriteObjCounter(this, --count); | |
| if (count == 0 && ui != null) { | |
| ui.installUI(this); | |
| } | |
| } | |
| } | |
| ///////////////// | |
| // Accessibility support | |
| //////////////// | |
|         /** | |
|          * Gets the AccessibleContext associated with this JDesktopIcon. | |
|          * For desktop icons, the AccessibleContext takes the form of an | |
|          * AccessibleJDesktopIcon. | |
|          * A new AccessibleJDesktopIcon instance is created if necessary. | |
|          * | |
|          * @return an AccessibleJDesktopIcon that serves as the | |
|          *         AccessibleContext of this JDesktopIcon | |
| */ | |
| public AccessibleContext getAccessibleContext() { | |
|             if (accessibleContext == null) { | |
| accessibleContext = new AccessibleJDesktopIcon(); | |
| } | |
| return accessibleContext; | |
| } | |
|         /** | |
|          * This class implements accessibility support for the | |
|          * <code>JInternalFrame.JDesktopIcon</code> class.  It provides an | |
|          * implementation of the Java Accessibility API appropriate to | |
|          * desktop icon user-interface elements. | |
|          * <p> | |
|          * <strong>Warning:</strong> | |
|          * Serialized objects of this class will not be compatible with | |
|          * future Swing releases. The current serialization support is | |
|          * appropriate for short term storage or RMI between applications running | |
|          * the same version of Swing.  As of 1.4, support for long term storage | |
|          * of all JavaBeans™ | |
|          * has been added to the <code>java.beans</code> package. | |
|          * Please see {@link java.beans.XMLEncoder}. | |
| */ | |
| protected class AccessibleJDesktopIcon extends AccessibleJComponent | |
| implements AccessibleValue { | |
|             /** | |
|              * Gets the role of this object. | |
|              * | |
|              * @return an instance of AccessibleRole describing the role of the | |
|              * object | |
|              * @see AccessibleRole | |
| */ | |
| public AccessibleRole getAccessibleRole() { | |
| return AccessibleRole.DESKTOP_ICON; | |
| } | |
|             /** | |
|              * Gets the AccessibleValue associated with this object.  In the | |
|              * implementation of the Java Accessibility API for this class, | |
|              * returns this object, which is responsible for implementing the | |
|              * <code>AccessibleValue</code> interface on behalf of itself. | |
|              * | |
|              * @return this object | |
| */ | |
| public AccessibleValue getAccessibleValue() { | |
| return this; | |
| } | |
| // | |
| // AccessibleValue methods | |
| // | |
|             /** | |
|              * Gets the value of this object as a <code>Number</code>. | |
|              * | |
|              * @return value of the object -- can be <code>null</code> if this object does not | |
|              * have a value | |
| */ | |
| public Number getCurrentAccessibleValue() { | |
| AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext(); | |
| AccessibleValue v = a.getAccessibleValue(); | |
| if (v != null) { | |
| return v.getCurrentAccessibleValue(); | |
|                 } else { | |
| return null; | |
| } | |
| } | |
|             /** | |
|              * Sets the value of this object as a <code>Number</code>. | |
|              * | |
|              * @return <code>true</code> if the value was set | |
| */ | |
| public boolean setCurrentAccessibleValue(Number n) { | |
|                 // TIGER - 4422535 | |
| if (n == null) { | |
| return false; | |
| } | |
| AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext(); | |
| AccessibleValue v = a.getAccessibleValue(); | |
| if (v != null) { | |
| return v.setCurrentAccessibleValue(n); | |
|                 } else { | |
| return false; | |
| } | |
| } | |
|             /** | |
|              * Gets the minimum value of this object as a <code>Number</code>. | |
|              * | |
|              * @return minimum value of the object; <code>null</code> if this object does not | |
|              * have a minimum value | |
| */ | |
| public Number getMinimumAccessibleValue() { | |
| AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext(); | |
| if (a instanceof AccessibleValue) { | |
| return ((AccessibleValue)a).getMinimumAccessibleValue(); | |
|                 } else { | |
| return null; | |
| } | |
| } | |
|             /** | |
|              * Gets the maximum value of this object as a <code>Number</code>. | |
|              * | |
|              * @return maximum value of the object; <code>null</code> if this object does not | |
|              * have a maximum value | |
| */ | |
| public Number getMaximumAccessibleValue() { | |
| AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext(); | |
| if (a instanceof AccessibleValue) { | |
| return ((AccessibleValue)a).getMaximumAccessibleValue(); | |
|                 } else { | |
| return null; | |
| } | |
| } | |
| } // AccessibleJDesktopIcon | |
| } | |
| } |