/* * Copyright (c) 1997, 2014, 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.JavaBean; import java.beans.BeanProperty; import java.beans.PropertyVetoException; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; 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.lang.StringBuilder; 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 How to Use Internal Frames, * a section in The Java Tutorial. * *

* * Generally, * you add JInternalFrames to a JDesktopPane. The UI * delegates the look-and-feel-specific actions to the * DesktopManager * object maintained by the JDesktopPane. *

* The JInternalFrame 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: *

 *       internalFrame.add(child);
 * 
* And the child will be added to the contentPane. * The content pane is actually managed by an instance of * JRootPane, * which also manages a layout pane, glass pane, and * optional menu bar for the internal frame. Please see the * JRootPane * documentation for a complete description of these components. * Refer to {@link javax.swing.RootPaneContainer} * for details on adding, removing and setting the LayoutManager * of a JInternalFrame. *

* Warning: Swing is not thread safe. For more * information see Swing's Threading * Policy. *

* Warning: * 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 java.beans 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 * @since 1.2 */ @JavaBean(defaultProperty = "JMenuBar", description = "A frame container which is contained within another window.") @SwingContainer(delegate = "getContentPane") @SuppressWarnings("serial") // Same-version serialization only public class JInternalFrame extends JComponent implements Accessible, WindowConstants, RootPaneContainer { /** * @see #getUIClassID * @see #readObject */ private static final String uiClassID = "InternalFrameUI"; /** * The JRootPane 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 add and setLayout * will be forwarded to the contentPane. This is initially * false, but is set to true when the JInternalFrame 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 * restoreSubcomponentFocus is invoked, that is, * restoreSubcomponentFocus sets this to the value returned * from getMostRecentFocusOwner. */ 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 JInternalFrame with no title. */ public JInternalFrame() { this("", false, false, false, false); } /** * Creates a non-resizable, non-closable, non-maximizable, * non-iconifiable JInternalFrame with the specified title. * Note that passing in a null title results in * unspecified behavior and possibly an exception. * * @param title the non-null String * to display in the title bar */ public JInternalFrame(String title) { this(title, false, false, false, false); } /** * Creates a non-closable, non-maximizable, non-iconifiable * JInternalFrame with the specified title * and resizability. * * @param title the String to display in the title bar * @param resizable if true, the internal frame can be resized */ public JInternalFrame(String title, boolean resizable) { this(title, resizable, false, false, false); } /** * Creates a non-maximizable, non-iconifiable JInternalFrame * with the specified title, resizability, and * closability. * * @param title the String to display in the title bar * @param resizable if true, the internal frame can be resized * @param closable if true, the internal frame can be closed */ public JInternalFrame(String title, boolean resizable, boolean closable) { this(title, resizable, closable, false, false); } /** * Creates a non-iconifiable JInternalFrame * with the specified title, * resizability, closability, and maximizability. * * @param title the String to display in the title bar * @param resizable if true, the internal frame can be resized * @param closable if true, the internal frame can be closed * @param maximizable if true, the internal frame can be maximized */ public JInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable) { this(title, resizable, closable, maximizable, false); } /** * Creates a JInternalFrame with the specified title, * resizability, closability, maximizability, and iconifiability. * All JInternalFrame constructors use this one. * * @param title the String to display in the title bar * @param resizable if true, the internal frame can be resized * @param closable if true, the internal frame can be closed * @param maximizable if true, the internal frame can be maximized * @param iconifiable if true, 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 JRootPane. * @return a new JRootPane * @see JRootPane */ protected JRootPane createRootPane() { return new JRootPane(); } /** * Returns the look-and-feel object that renders this component. * * @return the InternalFrameUI object that renders * this component */ public InternalFrameUI getUI() { return (InternalFrameUI)ui; } /** * Sets the UI delegate for this JInternalFrame. * @param ui the UI delegate */ @BeanProperty(hidden = true, 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 UIManager that the look and feel * has changed. * Replaces the current UI object with the latest version from the * UIManager. * * @see JComponent#updateUI */ public void updateUI() { setUI((InternalFrameUI)UIManager.getUI(this)); invalidate(); if (desktopIcon != null) { desktopIcon.updateUIWhenHidden(); } } /* This method is called if updateUI 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 */ @BeanProperty(bound = false, description = "UIClassID") public String getUIClassID() { return uiClassID; } /** * Returns whether calls to add and * setLayout are forwarded to the contentPane. * * @return true if add and setLayout * are forwarded; false otherwise * * @see #addImpl * @see #setLayout * @see #setRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer */ protected boolean isRootPaneCheckingEnabled() { return rootPaneCheckingEnabled; } /** * Sets whether calls to add and * setLayout are forwarded to the contentPane. * * @param enabled true if add and setLayout * are forwarded, false if they should operate directly on the * JInternalFrame. * * @see #addImpl * @see #setLayout * @see #isRootPaneCheckingEnabled * @see javax.swing.RootPaneContainer */ @BeanProperty(hidden = true, description = "Whether the add and setLayout methods are forwarded") protected void setRootPaneCheckingEnabled(boolean enabled) { rootPaneCheckingEnabled = enabled; } /** * Adds the specified child Component. * This method is overridden to conditionally forward calls to the * contentPane. * By default, children are added to the contentPane 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 index 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 * comp is not a child of the JInternalFrame * this will forward the call to the contentPane. * * @param comp the component to be removed * @throws NullPointerException if comp 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 * contentPane. * Refer to {@link javax.swing.RootPaneContainer} for * more information. * * @param manager the LayoutManager * @see #setRootPaneCheckingEnabled */ public void setLayout(LayoutManager manager) { if(isRootPaneCheckingEnabled()) { getContentPane().setLayout(manager); } else { super.setLayout(manager); } } ////////////////////////////////////////////////////////////////////////// /// Property Methods ////////////////////////////////////////////////////////////////////////// /** * Returns the current JMenuBar for this * JInternalFrame, or null * if no menu bar has been set. * @return the current menu bar, or null if none has been set * * @deprecated As of Swing version 1.0.3, * replaced by getJMenuBar(). */ @Deprecated public JMenuBar getMenuBar() { return getRootPane().getMenuBar(); } /** * Returns the current JMenuBar for this * JInternalFrame, or null * if no menu bar has been set. * * @return the JMenuBar used by this internal frame * @see #setJMenuBar */ public JMenuBar getJMenuBar() { return getRootPane().getJMenuBar(); } /** * Sets the menuBar property for this JInternalFrame. * * @param m the JMenuBar to use in this internal frame * @see #getJMenuBar * @deprecated As of Swing version 1.0.3 * replaced by setJMenuBar(JMenuBar m). */ @Deprecated public void setMenuBar(JMenuBar m) { JMenuBar oldValue = getMenuBar(); getRootPane().setJMenuBar(m); firePropertyChange(MENU_BAR_PROPERTY, oldValue, m); } /** * Sets the menuBar property for this JInternalFrame. * * @param m the JMenuBar to use in this internal frame * @see #getJMenuBar */ @BeanProperty(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 JInternalFrame's contentPane * property. * * @param c the content pane for this internal frame * * @exception java.awt.IllegalComponentStateException (a runtime * exception) if the content pane parameter is null * @see RootPaneContainer#getContentPane */ @BeanProperty(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 JLayeredPane object * @see RootPaneContainer#setLayeredPane * @see RootPaneContainer#getLayeredPane */ public JLayeredPane getLayeredPane() { return getRootPane().getLayeredPane(); } /** * Sets this JInternalFrame's * layeredPane property. * * @param layered the JLayeredPane for this internal frame * * @exception java.awt.IllegalComponentStateException (a runtime * exception) if the layered pane parameter is null * @see RootPaneContainer#setLayeredPane */ @BeanProperty(hidden = 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 JInternalFrame's * glassPane property. * * @param glass the glass pane for this internal frame * @see RootPaneContainer#getGlassPane */ @BeanProperty(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 rootPane object for this internal frame. * * @return the rootPane property * @see RootPaneContainer#getRootPane */ @BeanProperty(hidden = true, description = "The root pane used by this internal frame.") public JRootPane getRootPane() { return rootPane; } /** * Sets the rootPane property * for this JInternalFrame. * This method is called by the constructor. * * @param root the new JRootPane object */ 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 JInternalFrame can be closed by * some user action. * @param b a boolean value, where true means this internal frame can be closed */ @BeanProperty(preferred = 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 JInternalFrame can be closed by * some user action. * @return true if this internal frame can be closed */ public boolean isClosable() { return closable; } /** * Returns whether this JInternalFrame is currently closed. * @return true if this internal frame is closed, false otherwise */ public boolean isClosed() { return isClosed; } /** * Closes this internal frame if the argument is true. * Do not invoke this method with a false argument; * the result of invoking setClosed(false) * is unspecified. * *

* * If the internal frame is already closed, * this method does nothing and returns immediately. * Otherwise, * this method begins by firing * an INTERNAL_FRAME_CLOSING event. * Then this method sets the closed property to true * unless a listener vetoes the property change. * This method finishes by making the internal frame * invisible and unselected, * and then firing an INTERNAL_FRAME_CLOSED event. * *

* * Note: * 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 JDesktopPane * that previously contained the internal frame. * * @param b must be true * * @exception PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see #isClosed() * @see #setDefaultCloseOperation * @see #dispose * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING */ @BeanProperty(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 JInternalFrame can be resized by some * user action. * * @param b a boolean, where true means this internal frame can be resized */ @BeanProperty(preferred = 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 JInternalFrame can be resized * by some user action. * * @return true if this internal frame can be resized, false otherwise */ public boolean isResizable() { // don't allow resizing when maximized. return isMaximum ? false : resizable; } /** * Sets the iconable property, * which must be true * for the user to be able to * make the JInternalFrame an icon. * Some look and feels might not implement iconification; * they will ignore this property. * * @param b a boolean, where true means this internal frame can be iconified */ @BeanProperty(preferred = 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 iconable property, * which by default is false. * * @return the value of the iconable property. * * @see #setIconifiable */ public boolean isIconifiable() { return iconable; } /** * Returns whether the JInternalFrame is currently iconified. * * @return true 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 INTERNAL_FRAME_ICONIFIED event. * If the state changes to de-iconified, * an INTERNAL_FRAME_DEICONIFIED event is fired. * * @param b a boolean, where true means to iconify this internal frame and * false means to de-iconify it * @exception PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED * @see InternalFrameEvent#INTERNAL_FRAME_DEICONIFIED */ @BeanProperty(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 maximizable property, * which determines whether the JInternalFrame * can be maximized by * some user action. * Some look and feels might not support maximizing internal frames; * they will ignore this property. * * @param b true to specify that this internal frame should be maximizable; false to specify that it should not be */ @BeanProperty(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 maximizable property. * * @return the value of the maximizable property * @see #setMaximizable */ public boolean isMaximizable() { return maximizable; } /** * Returns whether the JInternalFrame is currently maximized. * * @return true if this internal frame is maximized, false otherwise */ public boolean isMaximum() { return isMaximum; } /** * Maximizes and restores this internal frame. A maximized frame is resized to * fully fit the JDesktopPane area associated with the * JInternalFrame. * A restored frame's size is set to the JInternalFrame's * actual size. * * @param b a boolean, where true maximizes this internal frame and false * restores it * @exception PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame */ @BeanProperty(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 JInternalFrame. * * @return a String containing this internal frame's title * @see #setTitle */ public String getTitle() { return title; } /** * Sets the JInternalFrame title. title * may have a null value. * @see #getTitle * * @param title the String to display in the title bar */ @BeanProperty(preferred = 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 JInternalFrame 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 * InternalFrameEvent.INTERNAL_FRAME_ACTIVATED event. * If the change is from selected to deselected, * an InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED event * is fired. * * @param selected a boolean, where true means this internal frame * should become selected (currently active) * and false means it should become deselected * @exception PropertyVetoException when the attempt to set the * property is vetoed by the JInternalFrame * * @see #isShowing * @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED * @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED */ @BeanProperty(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 JInternalFrame is the * currently "selected" or active frame. * * @return true 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 desktopIcon object, which * is the image displayed in the JDesktop when * this internal frame is iconified. * * Passing null 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 Icon to display in the title bar * @see #getFrameIcon */ @BeanProperty(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 Icon 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 JLayeredPane. */ 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 JLayeredPane. */ 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 Cursor that was set by the * setCursor method that is not a resizable * Cursor. * * @return the last non-resizable Cursor * @since 1.6 */ @BeanProperty(bound = false) 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 Integer object specifying this * frame's desktop layer * @see JLayeredPane */ @BeanProperty(bound = false, 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 setLayer(Integer) should be used for * layer values predefined in JLayeredPane. * When using setLayer(int), 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 */ @BeanProperty(bound = false, 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 Integer 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 * JDesktop instance. If JInternalFrame * finds none, the desktopIcon tree is searched. * * @return the JDesktopPane this internal frame belongs to, * or null if none is found */ @BeanProperty(bound = false) 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 JDesktopIcon associated with this * JInternalFrame. * * @param d the JDesktopIcon to display on the desktop * @see #getDesktopIcon */ @BeanProperty(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 JDesktopIcon used when this * JInternalFrame is iconified. * * @return the JDesktopIcon displayed on the desktop * @see #setDesktopIcon */ public JDesktopIcon getDesktopIcon() { return desktopIcon; } /** * If the JInternalFrame is not in maximized state, returns * getBounds(); otherwise, returns the bounds that the * JInternalFrame would be restored to. * * @return a Rectangle 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 JInternalFrame is active, * returns the child that has focus. * Otherwise, returns null. * * @return the component with focus, or null if no children have focus * @since 1.3 */ public Component getFocusOwner() { if (isSelected()) { return lastFocusOwner; } return null; } /** * Returns the child component of this JInternalFrame * that will receive the * focus when this JInternalFrame is selected. * If this JInternalFrame is * currently selected, this method returns the same component as * the getFocusOwner method. * If this JInternalFrame 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 * JInternalFrame's initial focusable component is returned. * If no such * child exists, then this JInternalFrame's default component * to focus is returned. * * @return the child component that will receive focus when this * JInternalFrame is selected * @see #getFocusOwner * @see #isSelected * @since 1.4 */ @BeanProperty(bound = false) 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 InternalFrameListeners added * to this JInternalFrame with * addInternalFrameListener. * * @return all of the InternalFrameListeners added or an empty * array if no listeners have been added * @since 1.4 * * @see #addInternalFrameListener */ @BeanProperty(bound = false) 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: *

* 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 * INTERNAL_FRAME_CLOSING 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: *

*
*
DO_NOTHING_ON_CLOSE *
Do nothing. * This requires the program to handle the operation * in the windowClosing method * of a registered InternalFrameListener object. *
HIDE_ON_CLOSE *
Automatically make the internal frame invisible. *
DISPOSE_ON_CLOSE *
Automatically dispose of the internal frame. *
*

* The default value is DISPOSE_ON_CLOSE. * Before performing the specified close operation, * the internal frame fires * an INTERNAL_FRAME_CLOSING event. * * @param operation one of the following constants defined in * javax.swing.WindowConstants * (an interface implemented by * JInternalFrame): * DO_NOTHING_ON_CLOSE, * HIDE_ON_CLOSE, or * DISPOSE_ON_CLOSE * * @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 JInternalFrame * 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 INTERNAL_FRAME_OPENED event. * This method does nothing if the internal frame is already visible. * Invoking this method * has the same result as invoking * setVisible(true). * * @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 * INTERNAL_FRAME_CLOSED event. * The results of invoking this method are similar to * setClosed(true), * but dispose always succeeds in closing * the internal frame and does not fire * an INTERNAL_FRAME_CLOSING 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 JInternalFrames 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 true because all JInternalFrames must be * roots of a focus traversal cycle. * * @return true * @see #setFocusCycleRoot * @see java.awt.Container#setFocusTraversalPolicy * @see java.awt.Container#getFocusTraversalPolicy * @since 1.4 */ public final boolean isFocusCycleRoot() { return true; } /** * Always returns null because JInternalFrames * must always be roots of a focus * traversal cycle. * * @return null * @see java.awt.Container#isFocusCycleRoot() * @since 1.4 */ @BeanProperty(bound = false) 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 null. * @return null * @see java.awt.Window#getWarningString */ @BeanProperty(bound = false) public final String getWarningString() { return null; } /** * See readObject and writeObject * in JComponent 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 JInternalFrame. * 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 null. * * @return a string representation of this JInternalFrame */ 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 AccessibleContext associated with this * JInternalFrame. * For internal frames, the AccessibleContext * takes the form of an * AccessibleJInternalFrame object. * A new AccessibleJInternalFrame instance is created if necessary. * * @return an AccessibleJInternalFrame that serves as the * AccessibleContext of this * JInternalFrame * @see AccessibleJInternalFrame */ @BeanProperty(bound = false) public AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new AccessibleJInternalFrame(); } return accessibleContext; } /** * This class implements accessibility support for the * JInternalFrame class. It provides an implementation of the * Java Accessibility API appropriate to internal frame user-interface * elements. *

* Warning: * 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 java.beans package. * Please see {@link java.beans.XMLEncoder}. */ @SuppressWarnings("serial") // Same-version serialization only protected class AccessibleJInternalFrame extends AccessibleJComponent implements AccessibleValue { /** * Get the accessible name of this object. * * @return the localized name of the object -- can be null 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 * AccessibleValue 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 null 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 true if the value was set */ public boolean setCurrentAccessibleValue(Number n) { // TIGER - 4422535 if (n == null) { return false; } setLayer(Integer.valueOf(n.intValue())); return true; } /** * Get the minimum value of this object as a Number. * * @return Minimum value of the object; null 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; null 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 * JInternalFrame. * 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 * JInternalFrame. 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 * JInternalFrame instance and iconify it. *

* Warning: * 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 java.beans package. * Please see {@link java.beans.XMLEncoder}. * * @author David Kloba */ @SuppressWarnings("serial") // Same-version serialization only static public class JDesktopIcon extends JComponent implements Accessible { JInternalFrame internalFrame; /** * Creates an icon for an internal frame. * * @param f the JInternalFrame * 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 DesktopIconUI object that renders * this component */ public DesktopIconUI getUI() { return (DesktopIconUI)ui; } /** * Sets the look-and-feel object that renders this component. * * @param ui the DesktopIconUI look-and-feel object * @see UIDefaults#getUI */ public void setUI(DesktopIconUI ui) { super.setUI(ui); } /** * Returns the JInternalFrame that this * DesktopIcon is associated with. * * @return the JInternalFrame with which this icon * is associated */ public JInternalFrame getInternalFrame() { return internalFrame; } /** * Sets the JInternalFrame with which this * DesktopIcon is associated. * * @param f the JInternalFrame with which this icon * is associated */ public void setInternalFrame(JInternalFrame f) { internalFrame = f; } /** * Convenience method to ask the icon for the Desktop * object it belongs to. * * @return the JDesktopPane that contains this * icon's internal frame, or null if none found */ public JDesktopPane getDesktopPane() { if(getInternalFrame() != null) return getInternalFrame().getDesktopPane(); return null; } /** * Notification from the UIManager that the look and feel * has changed. * Replaces the current UI object with the latest version from the * UIManager. * * @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 * JInternalFrame.JDesktopIcon class. It provides an * implementation of the Java Accessibility API appropriate to * desktop icon user-interface elements. *

* Warning: * 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 java.beans package. * Please see {@link java.beans.XMLEncoder}. */ @SuppressWarnings("serial") // Same-version serialization only 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 * AccessibleValue interface on behalf of itself. * * @return this object */ public AccessibleValue getAccessibleValue() { return this; } // // AccessibleValue methods // /** * Gets the value of this object as a Number. * * @return value of the object -- can be null 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 Number. * * @return true 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 Number. * * @return minimum value of the object; null 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 Number. * * @return maximum value of the object; null 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 } }