0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.swing;
0027
0028 import java.awt.*;
0029 import java.awt.event.*;
0030
0031 import java.beans.PropertyVetoException;
0032 import java.beans.PropertyChangeEvent;
0033 import java.util.EventListener;
0034
0035 import javax.swing.border.Border;
0036 import javax.swing.event.InternalFrameEvent;
0037 import javax.swing.event.InternalFrameListener;
0038 import javax.swing.plaf.*;
0039
0040 import javax.accessibility.*;
0041
0042 import java.io.ObjectOutputStream;
0043 import java.io.ObjectInputStream;
0044 import java.io.IOException;
0045 import java.lang.StringBuilder;
0046 import java.beans.PropertyChangeListener;
0047 import sun.awt.AppContext;
0048 import sun.swing.SwingUtilities2;
0049
0050 /**
0051 * A lightweight object that provides many of the features of
0052 * a native frame, including dragging, closing, becoming an icon,
0053 * resizing, title display, and support for a menu bar.
0054 * For task-oriented documentation and examples of using internal frames,
0055 * see <a
0056 href="http://java.sun.com/docs/books/tutorial/uiswing/components/internalframe.html" target="_top">How to Use Internal Frames</a>,
0057 * a section in <em>The Java Tutorial</em>.
0058 *
0059 * <p>
0060 *
0061 * Generally,
0062 * you add <code>JInternalFrame</code>s to a <code>JDesktopPane</code>. The UI
0063 * delegates the look-and-feel-specific actions to the
0064 * <code>DesktopManager</code>
0065 * object maintained by the <code>JDesktopPane</code>.
0066 * <p>
0067 * The <code>JInternalFrame</code> content pane
0068 * is where you add child components.
0069 * As a conveniance <code>add</code> and its variants, <code>remove</code> and
0070 * <code>setLayout</code> have been overridden to forward to the
0071 * <code>contentPane</code> as necessary. This means you can write:
0072 * <pre>
0073 * internalFrame.add(child);
0074 * </pre>
0075 * And the child will be added to the contentPane.
0076 * The content pane is actually managed by an instance of
0077 * <code>JRootPane</code>,
0078 * which also manages a layout pane, glass pane, and
0079 * optional menu bar for the internal frame. Please see the
0080 * <code>JRootPane</code>
0081 * documentation for a complete description of these components.
0082 * Refer to {@link javax.swing.RootPaneContainer}
0083 * for details on adding, removing and setting the <code>LayoutManager</code>
0084 * of a <code>JInternalFrame</code>.
0085 * <p>
0086 * <strong>Warning:</strong> Swing is not thread safe. For more
0087 * information see <a
0088 * href="package-summary.html#threading">Swing's Threading
0089 * Policy</a>.
0090 * <p>
0091 * <strong>Warning:</strong>
0092 * Serialized objects of this class will not be compatible with
0093 * future Swing releases. The current serialization support is
0094 * appropriate for short term storage or RMI between applications running
0095 * the same version of Swing. As of 1.4, support for long term storage
0096 * of all JavaBeans<sup><font size="-2">TM</font></sup>
0097 * has been added to the <code>java.beans</code> package.
0098 * Please see {@link java.beans.XMLEncoder}.
0099 *
0100 * @see InternalFrameEvent
0101 * @see JDesktopPane
0102 * @see DesktopManager
0103 * @see JInternalFrame.JDesktopIcon
0104 * @see JRootPane
0105 * @see javax.swing.RootPaneContainer
0106 *
0107 * @version 1.164 05/05/07
0108 * @author David Kloba
0109 * @author Rich Schiavi
0110 * @beaninfo
0111 * attribute: isContainer true
0112 * attribute: containerDelegate getContentPane
0113 * description: A frame container which is contained within
0114 * another window.
0115 */
0116 public class JInternalFrame extends JComponent implements Accessible,
0117 WindowConstants, RootPaneContainer {
0118 /**
0119 * @see #getUIClassID
0120 * @see #readObject
0121 */
0122 private static final String uiClassID = "InternalFrameUI";
0123
0124 /**
0125 * The <code>JRootPane</code> instance that manages the
0126 * content pane
0127 * and optional menu bar for this internal frame, as well as the
0128 * glass pane.
0129 *
0130 * @see JRootPane
0131 * @see RootPaneContainer
0132 */
0133 protected JRootPane rootPane;
0134
0135 /**
0136 * If true then calls to <code>add</code> and <code>setLayout</code>
0137 * will be forwarded to the <code>contentPane</code>. This is initially
0138 * false, but is set to true when the <code>JInternalFrame</code> is
0139 * constructed.
0140 *
0141 * @see #isRootPaneCheckingEnabled
0142 * @see #setRootPaneCheckingEnabled
0143 * @see javax.swing.RootPaneContainer
0144 */
0145 protected boolean rootPaneCheckingEnabled = false;
0146
0147 /** The frame can be closed. */
0148 protected boolean closable;
0149 /** The frame has been closed. */
0150 protected boolean isClosed;
0151 /** The frame can be expanded to the size of the desktop pane. */
0152 protected boolean maximizable;
0153 /**
0154 * The frame has been expanded to its maximum size.
0155 * @see #maximizable
0156 */
0157 protected boolean isMaximum;
0158 /**
0159 * The frame can "iconified" (shrunk down and displayed as
0160 * an icon-image).
0161 * @see JInternalFrame.JDesktopIcon
0162 * @see #setIconifiable
0163 */
0164 protected boolean iconable;
0165 /**
0166 * The frame has been iconified.
0167 * @see #isIcon()
0168 */
0169 protected boolean isIcon;
0170 /** The frame's size can be changed. */
0171 protected boolean resizable;
0172 /** The frame is currently selected. */
0173 protected boolean isSelected;
0174 /** The icon shown in the top-left corner of this internal frame. */
0175 protected Icon frameIcon;
0176 /** The title displayed in this internal frame's title bar. */
0177 protected String title;
0178 /**
0179 * The icon that is displayed when this internal frame is iconified.
0180 * @see #iconable
0181 */
0182 protected JDesktopIcon desktopIcon;
0183
0184 private Cursor lastCursor;
0185
0186 private boolean opened;
0187
0188 private Rectangle normalBounds = null;
0189
0190 private int defaultCloseOperation = DISPOSE_ON_CLOSE;
0191
0192 /**
0193 * Contains the Component that focus is to go when
0194 * <code>restoreSubcomponentFocus</code> is invoked, that is,
0195 * <code>restoreSubcomponentFocus</code> sets this to the value returned
0196 * from <code>getMostRecentFocusOwner</code>.
0197 */
0198 private Component lastFocusOwner;
0199
0200 /** Bound property name. */
0201 public final static String CONTENT_PANE_PROPERTY = "contentPane";
0202 /** Bound property name. */
0203 public final static String MENU_BAR_PROPERTY = "JMenuBar";
0204 /** Bound property name. */
0205 public final static String TITLE_PROPERTY = "title";
0206 /** Bound property name. */
0207 public final static String LAYERED_PANE_PROPERTY = "layeredPane";
0208 /** Bound property name. */
0209 public final static String ROOT_PANE_PROPERTY = "rootPane";
0210 /** Bound property name. */
0211 public final static String GLASS_PANE_PROPERTY = "glassPane";
0212 /** Bound property name. */
0213 public final static String FRAME_ICON_PROPERTY = "frameIcon";
0214
0215 /**
0216 * Constrained property name indicated that this frame has
0217 * selected status.
0218 */
0219 public final static String IS_SELECTED_PROPERTY = "selected";
0220 /** Constrained property name indicating that the internal frame is closed. */
0221 public final static String IS_CLOSED_PROPERTY = "closed";
0222 /** Constrained property name indicating that the internal frame is maximized. */
0223 public final static String IS_MAXIMUM_PROPERTY = "maximum";
0224 /** Constrained property name indicating that the internal frame is iconified. */
0225 public final static String IS_ICON_PROPERTY = "icon";
0226
0227 private static final Object PROPERTY_CHANGE_LISTENER_KEY = new StringBuilder(
0228 "InternalFramePropertyChangeListener");
0229
0230 private static void addPropertyChangeListenerIfNecessary() {
0231 if (AppContext.getAppContext()
0232 .get(PROPERTY_CHANGE_LISTENER_KEY) == null) {
0233 PropertyChangeListener focusListener = new FocusPropertyChangeListener();
0234
0235 AppContext.getAppContext().put(
0236 PROPERTY_CHANGE_LISTENER_KEY, focusListener);
0237
0238 KeyboardFocusManager.getCurrentKeyboardFocusManager()
0239 .addPropertyChangeListener(focusListener);
0240 }
0241 }
0242
0243 private static class FocusPropertyChangeListener implements
0244 PropertyChangeListener {
0245 public void propertyChange(PropertyChangeEvent e) {
0246 if (e.getPropertyName() == "permanentFocusOwner") {
0247 updateLastFocusOwner((Component) e.getNewValue());
0248 }
0249 }
0250 }
0251
0252 private static void updateLastFocusOwner(Component component) {
0253 if (component != null) {
0254 Component parent = component;
0255 while (parent != null && !(parent instanceof Window)) {
0256 if (parent instanceof JInternalFrame) {
0257 // Update lastFocusOwner for parent.
0258 ((JInternalFrame) parent)
0259 .setLastFocusOwner(component);
0260 }
0261 parent = parent.getParent();
0262 }
0263 }
0264 }
0265
0266 /**
0267 * Creates a non-resizable, non-closable, non-maximizable,
0268 * non-iconifiable <code>JInternalFrame</code> with no title.
0269 */
0270 public JInternalFrame() {
0271 this ("", false, false, false, false);
0272 }
0273
0274 /**
0275 * Creates a non-resizable, non-closable, non-maximizable,
0276 * non-iconifiable <code>JInternalFrame</code> with the specified title.
0277 * Note that passing in a <code>null</code> <code>title</code> results in
0278 * unspecified behavior and possibly an exception.
0279 *
0280 * @param title the non-<code>null</code> <code>String</code>
0281 * to display in the title bar
0282 */
0283 public JInternalFrame(String title) {
0284 this (title, false, false, false, false);
0285 }
0286
0287 /**
0288 * Creates a non-closable, non-maximizable, non-iconifiable
0289 * <code>JInternalFrame</code> with the specified title
0290 * and resizability.
0291 *
0292 * @param title the <code>String</code> to display in the title bar
0293 * @param resizable if <code>true</code>, the internal frame can be resized
0294 */
0295 public JInternalFrame(String title, boolean resizable) {
0296 this (title, resizable, false, false, false);
0297 }
0298
0299 /**
0300 * Creates a non-maximizable, non-iconifiable <code>JInternalFrame</code>
0301 * with the specified title, resizability, and
0302 * closability.
0303 *
0304 * @param title the <code>String</code> to display in the title bar
0305 * @param resizable if <code>true</code>, the internal frame can be resized
0306 * @param closable if <code>true</code>, the internal frame can be closed
0307 */
0308 public JInternalFrame(String title, boolean resizable,
0309 boolean closable) {
0310 this (title, resizable, closable, false, false);
0311 }
0312
0313 /**
0314 * Creates a non-iconifiable <code>JInternalFrame</code>
0315 * with the specified title,
0316 * resizability, closability, and maximizability.
0317 *
0318 * @param title the <code>String</code> to display in the title bar
0319 * @param resizable if <code>true</code>, the internal frame can be resized
0320 * @param closable if <code>true</code>, the internal frame can be closed
0321 * @param maximizable if <code>true</code>, the internal frame can be maximized
0322 */
0323 public JInternalFrame(String title, boolean resizable,
0324 boolean closable, boolean maximizable) {
0325 this (title, resizable, closable, maximizable, false);
0326 }
0327
0328 /**
0329 * Creates a <code>JInternalFrame</code> with the specified title,
0330 * resizability, closability, maximizability, and iconifiability.
0331 * All <code>JInternalFrame</code> constructors use this one.
0332 *
0333 * @param title the <code>String</code> to display in the title bar
0334 * @param resizable if <code>true</code>, the internal frame can be resized
0335 * @param closable if <code>true</code>, the internal frame can be closed
0336 * @param maximizable if <code>true</code>, the internal frame can be maximized
0337 * @param iconifiable if <code>true</code>, the internal frame can be iconified
0338 */
0339 public JInternalFrame(String title, boolean resizable,
0340 boolean closable, boolean maximizable, boolean iconifiable) {
0341
0342 setRootPane(createRootPane());
0343 setLayout(new BorderLayout());
0344 this .title = title;
0345 this .resizable = resizable;
0346 this .closable = closable;
0347 this .maximizable = maximizable;
0348 isMaximum = false;
0349 this .iconable = iconifiable;
0350 isIcon = false;
0351 setVisible(false);
0352 setRootPaneCheckingEnabled(true);
0353 desktopIcon = new JDesktopIcon(this );
0354 updateUI();
0355 sun.awt.SunToolkit.checkAndSetPolicy(this , true);
0356 addPropertyChangeListenerIfNecessary();
0357 }
0358
0359 /**
0360 * Called by the constructor to set up the <code>JRootPane</code>.
0361 * @return a new <code>JRootPane</code>
0362 * @see JRootPane
0363 */
0364 protected JRootPane createRootPane() {
0365 return new JRootPane();
0366 }
0367
0368 /**
0369 * Returns the look-and-feel object that renders this component.
0370 *
0371 * @return the <code>InternalFrameUI</code> object that renders
0372 * this component
0373 */
0374 public InternalFrameUI getUI() {
0375 return (InternalFrameUI) ui;
0376 }
0377
0378 /**
0379 * Sets the UI delegate for this <code>JInternalFrame</code>.
0380 * @param ui the UI delegate
0381 * @beaninfo
0382 * bound: true
0383 * hidden: true
0384 * attribute: visualUpdate true
0385 * description: The UI object that implements the Component's LookAndFeel.
0386 */
0387 public void setUI(InternalFrameUI ui) {
0388 boolean checkingEnabled = isRootPaneCheckingEnabled();
0389 try {
0390 setRootPaneCheckingEnabled(false);
0391 super .setUI(ui);
0392 } finally {
0393 setRootPaneCheckingEnabled(checkingEnabled);
0394 }
0395 }
0396
0397 /**
0398 * Notification from the <code>UIManager</code> that the look and feel
0399 * has changed.
0400 * Replaces the current UI object with the latest version from the
0401 * <code>UIManager</code>.
0402 *
0403 * @see JComponent#updateUI
0404 */
0405 public void updateUI() {
0406 setUI((InternalFrameUI) UIManager.getUI(this ));
0407 invalidate();
0408 if (desktopIcon != null) {
0409 desktopIcon.updateUIWhenHidden();
0410 }
0411 }
0412
0413 /* This method is called if <code>updateUI</code> was called
0414 * on the associated
0415 * JDesktopIcon. It's necessary to avoid infinite recursion.
0416 */
0417 void updateUIWhenHidden() {
0418 setUI((InternalFrameUI) UIManager.getUI(this ));
0419 invalidate();
0420 Component[] children = getComponents();
0421 if (children != null) {
0422 for (int i = 0; i < children.length; i++) {
0423 SwingUtilities.updateComponentTreeUI(children[i]);
0424 }
0425 }
0426 }
0427
0428 /**
0429 * Returns the name of the look-and-feel
0430 * class that renders this component.
0431 *
0432 * @return the string "InternalFrameUI"
0433 *
0434 * @see JComponent#getUIClassID
0435 * @see UIDefaults#getUI
0436 *
0437 * @beaninfo
0438 * description: UIClassID
0439 */
0440 public String getUIClassID() {
0441 return uiClassID;
0442 }
0443
0444 /**
0445 * Returns whether calls to <code>add</code> and
0446 * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
0447 *
0448 * @return true if <code>add</code> and <code>setLayout</code>
0449 * are fowarded; false otherwise
0450 *
0451 * @see #addImpl
0452 * @see #setLayout
0453 * @see #setRootPaneCheckingEnabled
0454 * @see javax.swing.RootPaneContainer
0455 */
0456 protected boolean isRootPaneCheckingEnabled() {
0457 return rootPaneCheckingEnabled;
0458 }
0459
0460 /**
0461 * Sets whether calls to <code>add</code> and
0462 * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
0463 *
0464 * @param enabled true if <code>add</code> and <code>setLayout</code>
0465 * are forwarded, false if they should operate directly on the
0466 * <code>JInternalFrame</code>.
0467 *
0468 * @see #addImpl
0469 * @see #setLayout
0470 * @see #isRootPaneCheckingEnabled
0471 * @see javax.swing.RootPaneContainer
0472 * @beaninfo
0473 * hidden: true
0474 * description: Whether the add and setLayout methods are forwarded
0475 */
0476 protected void setRootPaneCheckingEnabled(boolean enabled) {
0477 rootPaneCheckingEnabled = enabled;
0478 }
0479
0480 /**
0481 * Adds the specified child <code>Component</code>.
0482 * This method is overridden to conditionally forward calls to the
0483 * <code>contentPane</code>.
0484 * By default, children are added to the <code>contentPane</code> instead
0485 * of the frame, refer to {@link javax.swing.RootPaneContainer} for
0486 * details.
0487 *
0488 * @param comp the component to be enhanced
0489 * @param constraints the constraints to be respected
0490 * @param index the index
0491 * @exception IllegalArgumentException if <code>index</code> is invalid
0492 * @exception IllegalArgumentException if adding the container's parent
0493 * to itself
0494 * @exception IllegalArgumentException if adding a window to a container
0495 *
0496 * @see #setRootPaneCheckingEnabled
0497 * @see javax.swing.RootPaneContainer
0498 */
0499 protected void addImpl(Component comp, Object constraints, int index) {
0500 if (isRootPaneCheckingEnabled()) {
0501 getContentPane().add(comp, constraints, index);
0502 } else {
0503 super .addImpl(comp, constraints, index);
0504 }
0505 }
0506
0507 /**
0508 * Removes the specified component from the container. If
0509 * <code>comp</code> is not a child of the <code>JInternalFrame</code>
0510 * this will forward the call to the <code>contentPane</code>.
0511 *
0512 * @param comp the component to be removed
0513 * @throws NullPointerException if <code>comp</code> is null
0514 * @see #add
0515 * @see javax.swing.RootPaneContainer
0516 */
0517 public void remove(Component comp) {
0518 int oldCount = getComponentCount();
0519 super .remove(comp);
0520 if (oldCount == getComponentCount()) {
0521 getContentPane().remove(comp);
0522 }
0523 }
0524
0525 /**
0526 * Ensures that, by default, the layout of this component cannot be set.
0527 * Overridden to conditionally forward the call to the
0528 * <code>contentPane</code>.
0529 * Refer to {@link javax.swing.RootPaneContainer} for
0530 * more information.
0531 *
0532 * @param manager the <code>LayoutManager</code>
0533 * @see #setRootPaneCheckingEnabled
0534 */
0535 public void setLayout(LayoutManager manager) {
0536 if (isRootPaneCheckingEnabled()) {
0537 getContentPane().setLayout(manager);
0538 } else {
0539 super .setLayout(manager);
0540 }
0541 }
0542
0543 //////////////////////////////////////////////////////////////////////////
0544 /// Property Methods
0545 //////////////////////////////////////////////////////////////////////////
0546
0547 /**
0548 * Returns the current <code>JMenuBar</code> for this
0549 * <code>JInternalFrame</code>, or <code>null</code>
0550 * if no menu bar has been set.
0551 * @return the current menu bar, or <code>null</code> if none has been set
0552 *
0553 * @deprecated As of Swing version 1.0.3,
0554 * replaced by <code>getJMenuBar()</code>.
0555 */
0556 @Deprecated
0557 public JMenuBar getMenuBar() {
0558 return getRootPane().getMenuBar();
0559 }
0560
0561 /**
0562 * Returns the current <code>JMenuBar</code> for this
0563 * <code>JInternalFrame</code>, or <code>null</code>
0564 * if no menu bar has been set.
0565 *
0566 * @return the <code>JMenuBar</code> used by this internal frame
0567 * @see #setJMenuBar
0568 */
0569 public JMenuBar getJMenuBar() {
0570 return getRootPane().getJMenuBar();
0571 }
0572
0573 /**
0574 * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
0575 *
0576 * @param m the <code>JMenuBar</code> to use in this internal frame
0577 * @see #getJMenuBar
0578 * @deprecated As of Swing version 1.0.3
0579 * replaced by <code>setJMenuBar(JMenuBar m)</code>.
0580 */
0581 @Deprecated
0582 public void setMenuBar(JMenuBar m) {
0583 JMenuBar oldValue = getMenuBar();
0584 getRootPane().setJMenuBar(m);
0585 firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
0586 }
0587
0588 /**
0589 * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
0590 *
0591 * @param m the <code>JMenuBar</code> to use in this internal frame
0592 * @see #getJMenuBar
0593 * @beaninfo
0594 * bound: true
0595 * preferred: true
0596 * description: The menu bar for accessing pulldown menus
0597 * from this internal frame.
0598 */
0599 public void setJMenuBar(JMenuBar m) {
0600 JMenuBar oldValue = getMenuBar();
0601 getRootPane().setJMenuBar(m);
0602 firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
0603 }
0604
0605 // implements javax.swing.RootPaneContainer
0606 /**
0607 * Returns the content pane for this internal frame.
0608 * @return the content pane
0609 */
0610 public Container getContentPane() {
0611 return getRootPane().getContentPane();
0612 }
0613
0614 /**
0615 * Sets this <code>JInternalFrame</code>'s <code>contentPane</code>
0616 * property.
0617 *
0618 * @param c the content pane for this internal frame
0619 *
0620 * @exception java.awt.IllegalComponentStateException (a runtime
0621 * exception) if the content pane parameter is <code>null</code>
0622 * @see RootPaneContainer#getContentPane
0623 * @beaninfo
0624 * bound: true
0625 * hidden: true
0626 * description: The client area of the internal frame where child
0627 * components are normally inserted.
0628 */
0629 public void setContentPane(Container c) {
0630 Container oldValue = getContentPane();
0631 getRootPane().setContentPane(c);
0632 firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c);
0633 }
0634
0635 /**
0636 * Returns the layered pane for this internal frame.
0637 *
0638 * @return a <code>JLayeredPane</code> object
0639 * @see RootPaneContainer#setLayeredPane
0640 * @see RootPaneContainer#getLayeredPane
0641 */
0642 public JLayeredPane getLayeredPane() {
0643 return getRootPane().getLayeredPane();
0644 }
0645
0646 /**
0647 * Sets this <code>JInternalFrame</code>'s
0648 * <code>layeredPane</code> property.
0649 *
0650 * @param layered the <code>JLayeredPane</code> for this internal frame
0651 *
0652 * @exception java.awt.IllegalComponentStateException (a runtime
0653 * exception) if the layered pane parameter is <code>null</code>
0654 * @see RootPaneContainer#setLayeredPane
0655 * @beaninfo
0656 * hidden: true
0657 * bound: true
0658 * description: The pane which holds the various desktop layers.
0659 */
0660 public void setLayeredPane(JLayeredPane layered) {
0661 JLayeredPane oldValue = getLayeredPane();
0662 getRootPane().setLayeredPane(layered);
0663 firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered);
0664 }
0665
0666 /**
0667 * Returns the glass pane for this internal frame.
0668 *
0669 * @return the glass pane
0670 * @see RootPaneContainer#setGlassPane
0671 */
0672 public Component getGlassPane() {
0673 return getRootPane().getGlassPane();
0674 }
0675
0676 /**
0677 * Sets this <code>JInternalFrame</code>'s
0678 * <code>glassPane</code> property.
0679 *
0680 * @param glass the glass pane for this internal frame
0681 * @see RootPaneContainer#getGlassPane
0682 * @beaninfo
0683 * bound: true
0684 * hidden: true
0685 * description: A transparent pane used for menu rendering.
0686 */
0687 public void setGlassPane(Component glass) {
0688 Component oldValue = getGlassPane();
0689 getRootPane().setGlassPane(glass);
0690 firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass);
0691 }
0692
0693 /**
0694 * Returns the <code>rootPane</code> object for this internal frame.
0695 *
0696 * @return the <code>rootPane</code> property
0697 * @see RootPaneContainer#getRootPane
0698 */
0699 public JRootPane getRootPane() {
0700 return rootPane;
0701 }
0702
0703 /**
0704 * Sets the <code>rootPane</code> property
0705 * for this <code>JInternalFrame</code>.
0706 * This method is called by the constructor.
0707 *
0708 * @param root the new <code>JRootPane</code> object
0709 * @beaninfo
0710 * bound: true
0711 * hidden: true
0712 * description: The root pane used by this internal frame.
0713 */
0714 protected void setRootPane(JRootPane root) {
0715 if (rootPane != null) {
0716 remove(rootPane);
0717 }
0718 JRootPane oldValue = getRootPane();
0719 rootPane = root;
0720 if (rootPane != null) {
0721 boolean checkingEnabled = isRootPaneCheckingEnabled();
0722 try {
0723 setRootPaneCheckingEnabled(false);
0724 add(rootPane, BorderLayout.CENTER);
0725 } finally {
0726 setRootPaneCheckingEnabled(checkingEnabled);
0727 }
0728 }
0729 firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root);
0730 }
0731
0732 /**
0733 * Sets whether this <code>JInternalFrame</code> can be closed by
0734 * some user action.
0735 * @param b a boolean value, where <code>true</code> means this internal frame can be closed
0736 * @beaninfo
0737 * preferred: true
0738 * bound: true
0739 * description: Indicates whether this internal frame can be closed.
0740 */
0741 public void setClosable(boolean b) {
0742 Boolean oldValue = closable ? Boolean.TRUE : Boolean.FALSE;
0743 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0744 closable = b;
0745 firePropertyChange("closable", oldValue, newValue);
0746 }
0747
0748 /**
0749 * Returns whether this <code>JInternalFrame</code> can be closed by
0750 * some user action.
0751 * @return <code>true</code> if this internal frame can be closed
0752 */
0753 public boolean isClosable() {
0754 return closable;
0755 }
0756
0757 /**
0758 * Returns whether this <code>JInternalFrame</code> is currently closed.
0759 * @return <code>true</code> if this internal frame is closed, <code>false</code> otherwise
0760 */
0761 public boolean isClosed() {
0762 return isClosed;
0763 }
0764
0765 /**
0766 * Closes this internal frame if the argument is <code>true</code>.
0767 * Do not invoke this method with a <code>false</code> argument;
0768 * the result of invoking <code>setClosed(false)</code>
0769 * is unspecified.
0770 *
0771 * <p>
0772 *
0773 * If the internal frame is already closed,
0774 * this method does nothing and returns immediately.
0775 * Otherwise,
0776 * this method begins by firing
0777 * an <code>INTERNAL_FRAME_CLOSING</code> event.
0778 * Then this method sets the <code>closed</code> property to <code>true</code>
0779 * unless a listener vetoes the property change.
0780 * This method finishes by making the internal frame
0781 * invisible and unselected,
0782 * and then firing an <code>INTERNAL_FRAME_CLOSED</code> event.
0783 *
0784 * <p>
0785 *
0786 * <b>Note:</b>
0787 * To reuse an internal frame that has been closed,
0788 * you must add it to a container
0789 * (even if you never removed it from its previous container).
0790 * Typically, this container will be the <code>JDesktopPane</code>
0791 * that previously contained the internal frame.
0792 *
0793 * @param b must be <code>true</code>
0794 *
0795 * @exception PropertyVetoException when the attempt to set the
0796 * property is vetoed by the <code>JInternalFrame</code>
0797 *
0798 * @see #isClosed()
0799 * @see #setDefaultCloseOperation
0800 * @see #dispose
0801 * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
0802 *
0803 * @beaninfo
0804 * bound: true
0805 * constrained: true
0806 * description: Indicates whether this internal frame has been closed.
0807 */
0808 public void setClosed(boolean b) throws PropertyVetoException {
0809 if (isClosed == b) {
0810 return;
0811 }
0812
0813 Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE;
0814 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0815 if (b) {
0816 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
0817 }
0818 fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue);
0819 isClosed = b;
0820 if (isClosed) {
0821 setVisible(false);
0822 }
0823 firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue);
0824 if (isClosed) {
0825 dispose();
0826 } else if (!opened) {
0827 /* this bogus -- we haven't defined what
0828 setClosed(false) means. */
0829 // fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
0830 // opened = true;
0831 }
0832 }
0833
0834 /**
0835 * Sets whether the <code>JInternalFrame</code> can be resized by some
0836 * user action.
0837 *
0838 * @param b a boolean, where <code>true</code> means this internal frame can be resized
0839 * @beaninfo
0840 * preferred: true
0841 * bound: true
0842 * description: Determines whether this internal frame can be resized
0843 * by the user.
0844 */
0845 public void setResizable(boolean b) {
0846 Boolean oldValue = resizable ? Boolean.TRUE : Boolean.FALSE;
0847 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0848 resizable = b;
0849 firePropertyChange("resizable", oldValue, newValue);
0850 }
0851
0852 /**
0853 * Returns whether the <code>JInternalFrame</code> can be resized
0854 * by some user action.
0855 *
0856 * @return <code>true</code> if this internal frame can be resized, <code>false</code> otherwise
0857 */
0858 public boolean isResizable() {
0859 // don't allow resizing when maximized.
0860 return isMaximum ? false : resizable;
0861 }
0862
0863 /**
0864 * Sets the <code>iconable</code> property,
0865 * which must be <code>true</code>
0866 * for the user to be able to
0867 * make the <code>JInternalFrame</code> an icon.
0868 * Some look and feels might not implement iconification;
0869 * they will ignore this property.
0870 *
0871 * @param b a boolean, where <code>true</code> means this internal frame can be iconified
0872 * @beaninfo
0873 * preferred: true
0874 bound: true
0875 * description: Determines whether this internal frame can be iconified.
0876 */
0877 public void setIconifiable(boolean b) {
0878 Boolean oldValue = iconable ? Boolean.TRUE : Boolean.FALSE;
0879 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0880 iconable = b;
0881 firePropertyChange("iconable", oldValue, newValue);
0882 }
0883
0884 /**
0885 * Gets the <code>iconable</code> property,
0886 * which by default is <code>false</code>.
0887 *
0888 * @return the value of the <code>iconable</code> property.
0889 *
0890 * @see #setIconifiable
0891 */
0892 public boolean isIconifiable() {
0893 return iconable;
0894 }
0895
0896 /**
0897 * Returns whether the <code>JInternalFrame</code> is currently iconified.
0898 *
0899 * @return <code>true</code> if this internal frame is iconified
0900 */
0901 public boolean isIcon() {
0902 return isIcon;
0903 }
0904
0905 /**
0906 * Iconifies or de-iconifies this internal frame,
0907 * if the look and feel supports iconification.
0908 * If the internal frame's state changes to iconified,
0909 * this method fires an <code>INTERNAL_FRAME_ICONIFIED</code> event.
0910 * If the state changes to de-iconified,
0911 * an <code>INTERNAL_FRAME_DEICONIFIED</code> event is fired.
0912 *
0913 * @param b a boolean, where <code>true</code> means to iconify this internal frame and
0914 * <code>false</code> means to de-iconify it
0915 * @exception PropertyVetoException when the attempt to set the
0916 * property is vetoed by the <code>JInternalFrame</code>
0917 *
0918 * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED
0919 * @see InternalFrameEvent#INTERNAL_FRAME_DEICONIFIED
0920 *
0921 * @beaninfo
0922 * bound: true
0923 * constrained: true
0924 * description: The image displayed when this internal frame is minimized.
0925 */
0926 public void setIcon(boolean b) throws PropertyVetoException {
0927 if (isIcon == b) {
0928 return;
0929 }
0930
0931 /* If an internal frame is being iconified before it has a
0932 parent, (e.g., client wants it to start iconic), create the
0933 parent if possible so that we can place the icon in its
0934 proper place on the desktop. I am not sure the call to
0935 validate() is necessary, since we are not going to display
0936 this frame yet */
0937 firePropertyChange("ancestor", null, getParent());
0938
0939 Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE;
0940 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0941 fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue);
0942 isIcon = b;
0943 firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue);
0944 if (b)
0945 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED);
0946 else
0947 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
0948 }
0949
0950 /**
0951 * Sets the <code>maximizable</code> property,
0952 * which determines whether the <code>JInternalFrame</code>
0953 * can be maximized by
0954 * some user action.
0955 * Some look and feels might not support maximizing internal frames;
0956 * they will ignore this property.
0957 *
0958 * @param b <code>true</code> to specify that this internal frame should be maximizable; <code>false</code> to specify that it should not be
0959 * @beaninfo
0960 * bound: true
0961 * preferred: true
0962 * description: Determines whether this internal frame can be maximized.
0963 */
0964 public void setMaximizable(boolean b) {
0965 Boolean oldValue = maximizable ? Boolean.TRUE : Boolean.FALSE;
0966 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
0967 maximizable = b;
0968 firePropertyChange("maximizable", oldValue, newValue);
0969 }
0970
0971 /**
0972 * Gets the value of the <code>maximizable</code> property.
0973 *
0974 * @return the value of the <code>maximizable</code> property
0975 * @see #setMaximizable
0976 */
0977 public boolean isMaximizable() {
0978 return maximizable;
0979 }
0980
0981 /**
0982 * Returns whether the <code>JInternalFrame</code> is currently maximized.
0983 *
0984 * @return <code>true</code> if this internal frame is maximized, <code>false</code> otherwise
0985 */
0986 public boolean isMaximum() {
0987 return isMaximum;
0988 }
0989
0990 /**
0991 * Maximizes and restores this internal frame. A maximized frame is resized to
0992 * fully fit the <code>JDesktopPane</code> area associated with the
0993 * <code>JInternalFrame</code>.
0994 * A restored frame's size is set to the <code>JInternalFrame</code>'s
0995 * actual size.
0996 *
0997 * @param b a boolean, where <code>true</code> maximizes this internal frame and <code>false</code>
0998 * restores it
0999 * @exception PropertyVetoException when the attempt to set the
1000 * property is vetoed by the <code>JInternalFrame</code>
1001 * @beaninfo
1002 * bound: true
1003 * constrained: true
1004 * description: Indicates whether this internal frame is maximized.
1005 */
1006 public void setMaximum(boolean b) throws PropertyVetoException {
1007 if (isMaximum == b) {
1008 return;
1009 }
1010
1011 Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE;
1012 Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
1013 fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
1014 /* setting isMaximum above the event firing means that
1015 property listeners that, for some reason, test it will
1016 get it wrong... See, for example, getNormalBounds() */
1017 isMaximum = b;
1018 firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
1019 }
1020
1021 /**
1022 * Returns the title of the <code>JInternalFrame</code>.
1023 *
1024 * @return a <code>String</code> containing this internal frame's title
1025 * @see #setTitle
1026 */
1027 public String getTitle() {
1028 return title;
1029 }
1030
1031 /**
1032 * Sets the <code>JInternalFrame</code> title. <code>title</code>
1033 * may have a <code>null</code> value.
1034 * @see #getTitle
1035 *
1036 * @param title the <code>String</code> to display in the title bar
1037 * @beaninfo
1038 * preferred: true
1039 * bound: true
1040 * description: The text displayed in the title bar.
1041 */
1042 public void setTitle(String title) {
1043 String oldValue = this .title;
1044 this .title = title;
1045 firePropertyChange(TITLE_PROPERTY, oldValue, title);
1046 }
1047
1048 /**
1049 * Selects or deselects the internal frame
1050 * if it's showing.
1051 * A <code>JInternalFrame</code> normally draws its title bar
1052 * differently if it is
1053 * the selected frame, which indicates to the user that this
1054 * internal frame has the focus.
1055 * When this method changes the state of the internal frame
1056 * from deselected to selected, it fires an
1057 * <code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> event.
1058 * If the change is from selected to deselected,
1059 * an <code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> event
1060 * is fired.
1061 *
1062 * @param selected a boolean, where <code>true</code> means this internal frame
1063 * should become selected (currently active)
1064 * and <code>false</code> means it should become deselected
1065 * @exception PropertyVetoException when the attempt to set the
1066 * property is vetoed by the <code>JInternalFrame</code>
1067 *
1068 * @see #isShowing
1069 * @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED
1070 * @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED
1071 *
1072 * @beaninfo
1073 * constrained: true
1074 * bound: true
1075 * description: Indicates whether this internal frame is currently
1076 * the active frame.
1077 */
1078 public void setSelected(boolean selected)
1079 throws PropertyVetoException {
1080 // The InternalFrame may already be selected, but the focus
1081 // may be outside it, so restore the focus to the subcomponent
1082 // which previously had it. See Bug 4302764.
1083 if (selected && isSelected) {
1084 restoreSubcomponentFocus();
1085 return;
1086 }
1087 // The internal frame or the desktop icon must be showing to allow
1088 // selection. We may deselect even if neither is showing.
1089 if ((isSelected == selected)
1090 || (selected && (isIcon ? !desktopIcon.isShowing()
1091 : !isShowing()))) {
1092 return;
1093 }
1094
1095 Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE;
1096 Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE;
1097 fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1098
1099 /* We don't want to leave focus in the previously selected
1100 frame, so we have to set it to *something* in case it
1101 doesn't get set in some other way (as if a user clicked on
1102 a component that doesn't request focus). If this call is
1103 happening because the user clicked on a component that will
1104 want focus, then it will get transfered there later.
1105
1106 We test for parent.isShowing() above, because AWT throws a
1107 NPE if you try to request focus on a lightweight before its
1108 parent has been made visible */
1109
1110 if (selected) {
1111 restoreSubcomponentFocus();
1112 }
1113
1114 isSelected = selected;
1115 firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1116 if (isSelected)
1117 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED);
1118 else
1119 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
1120 repaint();
1121 }
1122
1123 /**
1124 * Returns whether the <code>JInternalFrame</code> is the
1125 * currently "selected" or active frame.
1126 *
1127 * @return <code>true</code> if this internal frame is currently selected (active)
1128 * @see #setSelected
1129 */
1130 public boolean isSelected() {
1131 return isSelected;
1132 }
1133
1134 /**
1135 * Sets an image to be displayed in the titlebar of this internal frame (usually
1136 * in the top-left corner).
1137 * This image is not the <code>desktopIcon</code> object, which
1138 * is the image displayed in the <code>JDesktop</code> when
1139 * this internal frame is iconified.
1140 *
1141 * Passing <code>null</code> to this function is valid,
1142 * but the look and feel
1143 * can choose the
1144 * appropriate behavior for that situation, such as displaying no icon
1145 * or a default icon for the look and feel.
1146 *
1147 * @param icon the <code>Icon</code> to display in the title bar
1148 * @see #getFrameIcon
1149 * @beaninfo
1150 * bound: true
1151 * description: The icon shown in the top-left corner of this internal frame.
1152 */
1153 public void setFrameIcon(Icon icon) {
1154 Icon oldIcon = frameIcon;
1155 frameIcon = icon;
1156 firePropertyChange(FRAME_ICON_PROPERTY, oldIcon, icon);
1157 }
1158
1159 /**
1160 * Returns the image displayed in the title bar of this internal frame (usually
1161 * in the top-left corner).
1162 *
1163 * @return the <code>Icon</code> displayed in the title bar
1164 * @see #setFrameIcon
1165 */
1166 public Icon getFrameIcon() {
1167 return frameIcon;
1168 }
1169
1170 /**
1171 * Convenience method that moves this component to position 0 if its
1172 * parent is a <code>JLayeredPane</code>.
1173 */
1174 public void moveToFront() {
1175 if (isIcon()) {
1176 if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1177 ((JLayeredPane) getDesktopIcon().getParent())
1178 .moveToFront(getDesktopIcon());
1179 }
1180 } else if (getParent() instanceof JLayeredPane) {
1181 ((JLayeredPane) getParent()).moveToFront(this );
1182 }
1183 }
1184
1185 /**
1186 * Convenience method that moves this component to position -1 if its
1187 * parent is a <code>JLayeredPane</code>.
1188 */
1189 public void moveToBack() {
1190 if (isIcon()) {
1191 if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1192 ((JLayeredPane) getDesktopIcon().getParent())
1193 .moveToBack(getDesktopIcon());
1194 }
1195 } else if (getParent() instanceof JLayeredPane) {
1196 ((JLayeredPane) getParent()).moveToBack(this );
1197 }
1198 }
1199
1200 /**
1201 * Returns the last <code>Cursor</code> that was set by the
1202 * <code>setCursor</code> method that is not a resizable
1203 * <code>Cursor</code>.
1204 *
1205 * @return the last non-resizable <code>Cursor</code>
1206 * @since 1.6
1207 */
1208 public Cursor getLastCursor() {
1209 return lastCursor;
1210 }
1211
1212 /**
1213 * {@inheritDoc}
1214 * @since 1.6
1215 */
1216 public void setCursor(Cursor cursor) {
1217 if (cursor == null) {
1218 lastCursor = null;
1219 super .setCursor(cursor);
1220 return;
1221 }
1222 int type = cursor.getType();
1223 if (!(type == Cursor.SW_RESIZE_CURSOR
1224 || type == Cursor.SE_RESIZE_CURSOR
1225 || type == Cursor.NW_RESIZE_CURSOR
1226 || type == Cursor.NE_RESIZE_CURSOR
1227 || type == Cursor.N_RESIZE_CURSOR
1228 || type == Cursor.S_RESIZE_CURSOR
1229 || type == Cursor.W_RESIZE_CURSOR || type == Cursor.E_RESIZE_CURSOR)) {
1230 lastCursor = cursor;
1231 }
1232 super .setCursor(cursor);
1233 }
1234
1235 /**
1236 * Convenience method for setting the layer attribute of this component.
1237 *
1238 * @param layer an <code>Integer</code> object specifying this
1239 * frame's desktop layer
1240 * @see JLayeredPane
1241 * @beaninfo
1242 * expert: true
1243 * description: Specifies what desktop layer is used.
1244 */
1245 public void setLayer(Integer layer) {
1246 if (getParent() != null && getParent() instanceof JLayeredPane) {
1247 // Normally we want to do this, as it causes the LayeredPane
1248 // to draw properly.
1249 JLayeredPane p = (JLayeredPane) getParent();
1250 p.setLayer(this , layer.intValue(), p.getPosition(this ));
1251 } else {
1252 // Try to do the right thing
1253 JLayeredPane.putLayer(this , layer.intValue());
1254 if (getParent() != null)
1255 getParent().repaint(getX(), getY(), getWidth(),
1256 getHeight());
1257 }
1258 }
1259
1260 /**
1261 * Convenience method for setting the layer attribute of this component.
1262 * The method <code>setLayer(Integer)</code> should be used for
1263 * layer values predefined in <code>JLayeredPane</code>.
1264 * When using <code>setLayer(int)</code>, care must be taken not to
1265 * accidentally clash with those values.
1266 *
1267 * @param layer an integer specifying this internal frame's desktop layer
1268 *
1269 * @since 1.3
1270 *
1271 * @see #setLayer(Integer)
1272 * @see JLayeredPane
1273 * @beaninfo
1274 * expert: true
1275 * description: Specifies what desktop layer is used.
1276 */
1277 public void setLayer(int layer) {
1278 this .setLayer(new Integer(layer));
1279 }
1280
1281 /**
1282 * Convenience method for getting the layer attribute of this component.
1283 *
1284 * @return an <code>Integer</code> object specifying this
1285 * frame's desktop layer
1286 * @see JLayeredPane
1287 */
1288 public int getLayer() {
1289 return JLayeredPane.getLayer(this );
1290 }
1291
1292 /**
1293 * Convenience method that searches the ancestor hierarchy for a
1294 * <code>JDesktop</code> instance. If <code>JInternalFrame</code>
1295 * finds none, the <code>desktopIcon</code> tree is searched.
1296 *
1297 * @return the <code>JDesktopPane</code> this internal frame belongs to,
1298 * or <code>null</code> if none is found
1299 */
1300 public JDesktopPane getDesktopPane() {
1301 Container p;
1302
1303 // Search upward for desktop
1304 p = getParent();
1305 while (p != null && !(p instanceof JDesktopPane))
1306 p = p.getParent();
1307
1308 if (p == null) {
1309 // search its icon parent for desktop
1310 p = getDesktopIcon().getParent();
1311 while (p != null && !(p instanceof JDesktopPane))
1312 p = p.getParent();
1313 }
1314
1315 return (JDesktopPane) p;
1316 }
1317
1318 /**
1319 * Sets the <code>JDesktopIcon</code> associated with this
1320 * <code>JInternalFrame</code>.
1321 *
1322 * @param d the <code>JDesktopIcon</code> to display on the desktop
1323 * @see #getDesktopIcon
1324 * @beaninfo
1325 * bound: true
1326 * description: The icon shown when this internal frame is minimized.
1327 */
1328 public void setDesktopIcon(JDesktopIcon d) {
1329 JDesktopIcon oldValue = getDesktopIcon();
1330 desktopIcon = d;
1331 firePropertyChange("desktopIcon", oldValue, d);
1332 }
1333
1334 /**
1335 * Returns the <code>JDesktopIcon</code> used when this
1336 * <code>JInternalFrame</code> is iconified.
1337 *
1338 * @return the <code>JDesktopIcon</code> displayed on the desktop
1339 * @see #setDesktopIcon
1340 */
1341 public JDesktopIcon getDesktopIcon() {
1342 return desktopIcon;
1343 }
1344
1345 /**
1346 * If the <code>JInternalFrame</code> is not in maximized state, returns
1347 * <code>getBounds()</code>; otherwise, returns the bounds that the
1348 * <code>JInternalFrame</code> would be restored to.
1349 *
1350 * @return a <code>Rectangle</code> containing the bounds of this
1351 * frame when in the normal state
1352 * @since 1.3
1353 */
1354 public Rectangle getNormalBounds() {
1355
1356 /* we used to test (!isMaximum) here, but since this
1357 method is used by the property listener for the
1358 IS_MAXIMUM_PROPERTY, it ended up getting the wrong
1359 answer... Since normalBounds get set to null when the
1360 frame is restored, this should work better */
1361
1362 if (normalBounds != null) {
1363 return normalBounds;
1364 } else {
1365 return getBounds();
1366 }
1367 }
1368
1369 /**
1370 * Sets the normal bounds for this internal frame, the bounds that
1371 * this internal frame would be restored to from its maximized state.
1372 * This method is intended for use only by desktop managers.
1373 *
1374 * @param r the bounds that this internal frame should be restored to
1375 * @since 1.3
1376 */
1377 public void setNormalBounds(Rectangle r) {
1378 normalBounds = r;
1379 }
1380
1381 /**
1382 * If this <code>JInternalFrame</code> is active,
1383 * returns the child that has focus.
1384 * Otherwise, returns <code>null</code>.
1385 *
1386 * @return the component with focus, or <code>null</code> if no children have focus
1387 * @since 1.3
1388 */
1389 public Component getFocusOwner() {
1390 if (isSelected()) {
1391 return lastFocusOwner;
1392 }
1393 return null;
1394 }
1395
1396 /**
1397 * Returns the child component of this <code>JInternalFrame</code>
1398 * that will receive the
1399 * focus when this <code>JInternalFrame</code> is selected.
1400 * If this <code>JInternalFrame</code> is
1401 * currently selected, this method returns the same component as
1402 * the <code>getFocusOwner</code> method.
1403 * If this <code>JInternalFrame</code> is not selected,
1404 * then the child component that most recently requested focus will be
1405 * returned. If no child component has ever requested focus, then this
1406 * <code>JInternalFrame</code>'s initial focusable component is returned.
1407 * If no such
1408 * child exists, then this <code>JInternalFrame</code>'s default component
1409 * to focus is returned.
1410 *
1411 * @return the child component that will receive focus when this
1412 * <code>JInternalFrame</code> is selected
1413 * @see #getFocusOwner
1414 * @see #isSelected
1415 * @since 1.4
1416 */
1417 public Component getMostRecentFocusOwner() {
1418 if (isSelected()) {
1419 return getFocusOwner();
1420 }
1421
1422 if (lastFocusOwner != null) {
1423 return lastFocusOwner;
1424 }
1425
1426 FocusTraversalPolicy policy = getFocusTraversalPolicy();
1427 if (policy instanceof InternalFrameFocusTraversalPolicy) {
1428 return ((InternalFrameFocusTraversalPolicy) policy)
1429 .getInitialComponent(this );
1430 }
1431
1432 Component toFocus = policy.getDefaultComponent(this );
1433 if (toFocus != null) {
1434 return toFocus;
1435 }
1436 return getContentPane();
1437 }
1438
1439 /**
1440 * Requests the internal frame to restore focus to the
1441 * last subcomponent that had focus. This is used by the UI when
1442 * the user selected this internal frame --
1443 * for example, by clicking on the title bar.
1444 *
1445 * @since 1.3
1446 */
1447 public void restoreSubcomponentFocus() {
1448 if (isIcon()) {
1449 SwingUtilities2.compositeRequestFocus(getDesktopIcon());
1450 } else {
1451 // FocusPropertyChangeListener will eventually update
1452 // lastFocusOwner. As focus requests are asynchronous
1453 // lastFocusOwner may be accessed before it has been correctly
1454 // updated. To avoid any problems, lastFocusOwner is immediately
1455 // set, assuming the request will succeed.
1456 lastFocusOwner = getMostRecentFocusOwner();
1457 if (lastFocusOwner == null) {
1458 // Make sure focus is restored somewhere, so that
1459 // we don't leave a focused component in another frame while
1460 // this frame is selected.
1461 lastFocusOwner = getContentPane();
1462 }
1463 lastFocusOwner.requestFocus();
1464 }
1465 }
1466
1467 private void setLastFocusOwner(Component component) {
1468 lastFocusOwner = component;
1469 }
1470
1471 /**
1472 * Moves and resizes this component. Unlike other components,
1473 * this implementation also forces re-layout, so that frame
1474 * decorations such as the title bar are always redisplayed.
1475 *
1476 * @param x an integer giving the component's new horizontal position
1477 * measured in pixels from the left of its container
1478 * @param y an integer giving the component's new vertical position,
1479 * measured in pixels from the bottom of its container
1480 * @param width an integer giving the component's new width in pixels
1481 * @param height an integer giving the component's new height in pixels
1482 */
1483 public void reshape(int x, int y, int width, int height) {
1484 super .reshape(x, y, width, height);
1485 validate();
1486 repaint();
1487 }
1488
1489 ///////////////////////////
1490 // Frame/Window equivalents
1491 ///////////////////////////
1492
1493 /**
1494 * Adds the specified listener to receive internal
1495 * frame events from this internal frame.
1496 *
1497 * @param l the internal frame listener
1498 */
1499 public void addInternalFrameListener(InternalFrameListener l) { // remind: sync ??
1500 listenerList.add(InternalFrameListener.class, l);
1501 // remind: needed?
1502 enableEvents(0); // turn on the newEventsOnly flag in Component.
1503 }
1504
1505 /**
1506 * Removes the specified internal frame listener so that it no longer
1507 * receives internal frame events from this internal frame.
1508 *
1509 * @param l the internal frame listener
1510 */
1511 public void removeInternalFrameListener(InternalFrameListener l) { // remind: sync??
1512 listenerList.remove(InternalFrameListener.class, l);
1513 }
1514
1515 /**
1516 * Returns an array of all the <code>InternalFrameListener</code>s added
1517 * to this <code>JInternalFrame</code> with
1518 * <code>addInternalFrameListener</code>.
1519 *
1520 * @return all of the <code>InternalFrameListener</code>s added or an empty
1521 * array if no listeners have been added
1522 * @since 1.4
1523 *
1524 * @see #addInternalFrameListener
1525 */
1526 public InternalFrameListener[] getInternalFrameListeners() {
1527 return (InternalFrameListener[]) listenerList
1528 .getListeners(InternalFrameListener.class);
1529 }
1530
1531 // remind: name ok? all one method ok? need to be synchronized?
1532 /**
1533 * Fires an internal frame event.
1534 *
1535 * @param id the type of the event being fired; one of the following:
1536 * <ul>
1537 * <li><code>InternalFrameEvent.INTERNAL_FRAME_OPENED</code>
1538 * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSING</code>
1539 * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSED</code>
1540 * <li><code>InternalFrameEvent.INTERNAL_FRAME_ICONIFIED</code>
1541 * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED</code>
1542 * <li><code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code>
1543 * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code>
1544 * </ul>
1545 * If the event type is not one of the above, nothing happens.
1546 */
1547 protected void fireInternalFrameEvent(int id) {
1548 Object[] listeners = listenerList.getListenerList();
1549 InternalFrameEvent e = null;
1550 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1551 if (listeners[i] == InternalFrameListener.class) {
1552 if (e == null) {
1553 e = new InternalFrameEvent(this , id);
1554 // System.out.println("InternalFrameEvent: " + e.paramString());
1555 }
1556 switch (e.getID()) {
1557 case InternalFrameEvent.INTERNAL_FRAME_OPENED:
1558 ((InternalFrameListener) listeners[i + 1])
1559 .internalFrameOpened(e);
1560 break;
1561 case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
1562 ((InternalFrameListener) listeners[i + 1])
1563 .internalFrameClosing(e);
1564 break;
1565 case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
1566 ((InternalFrameListener) listeners[i + 1])
1567 .internalFrameClosed(e);
1568 break;
1569 case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
1570 ((InternalFrameListener) listeners[i + 1])
1571 .internalFrameIconified(e);
1572 break;
1573 case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
1574 ((InternalFrameListener) listeners[i + 1])
1575 .internalFrameDeiconified(e);
1576 break;
1577 case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
1578 ((InternalFrameListener) listeners[i + 1])
1579 .internalFrameActivated(e);
1580 break;
1581 case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
1582 ((InternalFrameListener) listeners[i + 1])
1583 .internalFrameDeactivated(e);
1584 break;
1585 default:
1586 break;
1587 }
1588 }
1589 }
1590 /* we could do it off the event, but at the moment, that's not how
1591 I'm implementing it */
1592 // if (id == InternalFrameEvent.INTERNAL_FRAME_CLOSING) {
1593 // doDefaultCloseAction();
1594 // }
1595 }
1596
1597 /**
1598 * Fires an
1599 * <code>INTERNAL_FRAME_CLOSING</code> event
1600 * and then performs the action specified by
1601 * the internal frame's default close operation.
1602 * This method is typically invoked by the
1603 * look-and-feel-implemented action handler
1604 * for the internal frame's close button.
1605 *
1606 * @since 1.3
1607 * @see #setDefaultCloseOperation
1608 * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
1609 */
1610 public void doDefaultCloseAction() {
1611 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
1612 switch (defaultCloseOperation) {
1613 case DO_NOTHING_ON_CLOSE:
1614 break;
1615 case HIDE_ON_CLOSE:
1616 setVisible(false);
1617 if (isSelected())
1618 try {
1619 setSelected(false);
1620 } catch (PropertyVetoException pve) {
1621 }
1622
1623 /* should this activate the next frame? that's really
1624 desktopmanager's policy... */
1625 break;
1626 case DISPOSE_ON_CLOSE:
1627 try {
1628 fireVetoableChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1629 Boolean.TRUE);
1630 isClosed = true;
1631 setVisible(false);
1632 firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1633 Boolean.TRUE);
1634 dispose();
1635 } catch (PropertyVetoException pve) {
1636 }
1637 break;
1638 default:
1639 break;
1640 }
1641 }
1642
1643 /**
1644 * Sets the operation that will happen by default when
1645 * the user initiates a "close" on this internal frame.
1646 * The possible choices are:
1647 * <p>
1648 * <dl>
1649 * <dt><code>DO_NOTHING_ON_CLOSE</code>
1650 * <dd> Do nothing.
1651 * This requires the program to handle the operation
1652 * in the <code>windowClosing</code> method
1653 * of a registered <code>InternalFrameListener</code> object.
1654 * <dt><code>HIDE_ON_CLOSE</code>
1655 * <dd> Automatically make the internal frame invisible.
1656 * <dt><code>DISPOSE_ON_CLOSE</code>
1657 * <dd> Automatically dispose of the internal frame.
1658 * </dl>
1659 * <p>
1660 * The default value is <code>DISPOSE_ON_CLOSE</code>.
1661 * Before performing the specified close operation,
1662 * the internal frame fires
1663 * an <code>INTERNAL_FRAME_CLOSING</code> event.
1664 *
1665 * @param operation one of the following constants defined in
1666 * <code>javax.swing.WindowConstants</code>
1667 * (an interface implemented by
1668 * <code>JInternalFrame</code>):
1669 * <code>DO_NOTHING_ON_CLOSE</code>,
1670 * <code>HIDE_ON_CLOSE</code>, or
1671 * <code>DISPOSE_ON_CLOSE</code>
1672 *
1673 * @see #addInternalFrameListener
1674 * @see #getDefaultCloseOperation
1675 * @see #setVisible
1676 * @see #dispose
1677 * @see InternalFrameEvent#INTERNAL_FRAME_CLOSING
1678 */
1679 public void setDefaultCloseOperation(int operation) {
1680 this .defaultCloseOperation = operation;
1681 }
1682
1683 /**
1684 * Returns the default operation that occurs when the user
1685 * initiates a "close" on this internal frame.
1686 * @return the operation that will occur when the user closes the internal
1687 * frame
1688 * @see #setDefaultCloseOperation
1689 */
1690 public int getDefaultCloseOperation() {
1691 return defaultCloseOperation;
1692 }
1693
1694 /**
1695 * Causes subcomponents of this <code>JInternalFrame</code>
1696 * to be laid out at their preferred size. Internal frames that are
1697 * iconized or maximized are first restored and then packed. If the
1698 * internal frame is unable to be restored its state is not changed
1699 * and will not be packed.
1700 *
1701 * @see java.awt.Window#pack
1702 */
1703 public void pack() {
1704 try {
1705 if (isIcon()) {
1706 setIcon(false);
1707 } else if (isMaximum()) {
1708 setMaximum(false);
1709 }
1710 } catch (PropertyVetoException e) {
1711 return;
1712 }
1713 setSize(getPreferredSize());
1714 validate();
1715 }
1716
1717 /**
1718 * If the internal frame is not visible,
1719 * brings the internal frame to the front,
1720 * makes it visible,
1721 * and attempts to select it.
1722 * The first time the internal frame is made visible,
1723 * this method also fires an <code>INTERNAL_FRAME_OPENED</code> event.
1724 * This method does nothing if the internal frame is already visible.
1725 * Invoking this method
1726 * has the same result as invoking
1727 * <code>setVisible(true)</code>.
1728 *
1729 * @see #moveToFront
1730 * @see #setSelected
1731 * @see InternalFrameEvent#INTERNAL_FRAME_OPENED
1732 * @see #setVisible
1733 */
1734 public void show() {
1735 // bug 4312922
1736 if (isVisible()) {
1737 //match the behavior of setVisible(true): do nothing
1738 return;
1739 }
1740
1741 // bug 4149505
1742 if (!opened) {
1743 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
1744 opened = true;
1745 }
1746
1747 /* icon default visibility is false; set it to true so that it shows
1748 up when user iconifies frame */
1749 getDesktopIcon().setVisible(true);
1750
1751 toFront();
1752 super .show();
1753
1754 if (isIcon) {
1755 return;
1756 }
1757
1758 if (!isSelected()) {
1759 try {
1760 setSelected(true);
1761 } catch (PropertyVetoException pve) {
1762 }
1763 }
1764 }
1765
1766 public void hide() {
1767 if (isIcon()) {
1768 getDesktopIcon().setVisible(false);
1769 }
1770 super .hide();
1771 }
1772
1773 /**
1774 * Makes this internal frame
1775 * invisible, unselected, and closed.
1776 * If the frame is not already closed,
1777 * this method fires an
1778 * <code>INTERNAL_FRAME_CLOSED</code> event.
1779 * The results of invoking this method are similar to
1780 * <code>setClosed(true)</code>,
1781 * but <code>dispose</code> always succeeds in closing
1782 * the internal frame and does not fire
1783 * an <code>INTERNAL_FRAME_CLOSING</code> event.
1784 *
1785 * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSED
1786 * @see #setVisible
1787 * @see #setSelected
1788 * @see #setClosed
1789 */
1790 public void dispose() {
1791 if (isVisible()) {
1792 setVisible(false);
1793 }
1794 if (isSelected()) {
1795 try {
1796 setSelected(false);
1797 } catch (PropertyVetoException pve) {
1798 }
1799 }
1800 if (!isClosed) {
1801 firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1802 Boolean.TRUE);
1803 isClosed = true;
1804 }
1805 fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
1806 }
1807
1808 /**
1809 * Brings this internal frame to the front.
1810 * Places this internal frame at the top of the stacking order
1811 * and makes the corresponding adjustment to other visible internal
1812 * frames.
1813 *
1814 * @see java.awt.Window#toFront
1815 * @see #moveToFront
1816 */
1817 public void toFront() {
1818 moveToFront();
1819 }
1820
1821 /**
1822 * Sends this internal frame to the back.
1823 * Places this internal frame at the bottom of the stacking order
1824 * and makes the corresponding adjustment to other visible
1825 * internal frames.
1826 *
1827 * @see java.awt.Window#toBack
1828 * @see #moveToBack
1829 */
1830 public void toBack() {
1831 moveToBack();
1832 }
1833
1834 /**
1835 * Does nothing because <code>JInternalFrame</code>s must always be roots of a focus
1836 * traversal cycle.
1837 *
1838 * @param focusCycleRoot this value is ignored
1839 * @see #isFocusCycleRoot
1840 * @see java.awt.Container#setFocusTraversalPolicy
1841 * @see java.awt.Container#getFocusTraversalPolicy
1842 * @since 1.4
1843 */
1844 public final void setFocusCycleRoot(boolean focusCycleRoot) {
1845 }
1846
1847 /**
1848 * Always returns <code>true</code> because all <code>JInternalFrame</code>s must be
1849 * roots of a focus traversal cycle.
1850 *
1851 * @return <code>true</code>
1852 * @see #setFocusCycleRoot
1853 * @see java.awt.Container#setFocusTraversalPolicy
1854 * @see java.awt.Container#getFocusTraversalPolicy
1855 * @since 1.4
1856 */
1857 public final boolean isFocusCycleRoot() {
1858 return true;
1859 }
1860
1861 /**
1862 * Always returns <code>null</code> because <code>JInternalFrame</code>s
1863 * must always be roots of a focus
1864 * traversal cycle.
1865 *
1866 * @return <code>null</code>
1867 * @see java.awt.Container#isFocusCycleRoot()
1868 * @since 1.4
1869 */
1870 public final Container getFocusCycleRootAncestor() {
1871 return null;
1872 }
1873
1874 /**
1875 * Gets the warning string that is displayed with this internal frame.
1876 * Since an internal frame is always secure (since it's fully
1877 * contained within a window that might need a warning string)
1878 * this method always returns <code>null</code>.
1879 * @return <code>null</code>
1880 * @see java.awt.Window#getWarningString
1881 */
1882 public final String getWarningString() {
1883 return null;
1884 }
1885
1886 /**
1887 * See <code>readObject</code> and <code>writeObject</code>
1888 * in <code>JComponent</code> for more
1889 * information about serialization in Swing.
1890 */
1891 private void writeObject(ObjectOutputStream s) throws IOException {
1892 s.defaultWriteObject();
1893 if (getUIClassID().equals(uiClassID)) {
1894 byte count = JComponent.getWriteObjCounter(this );
1895 JComponent.setWriteObjCounter(this , --count);
1896 if (count == 0 && ui != null) {
1897 boolean old = isRootPaneCheckingEnabled();
1898 try {
1899 setRootPaneCheckingEnabled(false);
1900 ui.installUI(this );
1901 } finally {
1902 setRootPaneCheckingEnabled(old);
1903 }
1904 }
1905 }
1906 }
1907
1908 /* Called from the JComponent's EnableSerializationFocusListener to
1909 * do any Swing-specific pre-serialization configuration.
1910 */
1911 void compWriteObjectNotify() {
1912 // need to disable rootpane checking for InternalFrame: 4172083
1913 boolean old = isRootPaneCheckingEnabled();
1914 try {
1915 setRootPaneCheckingEnabled(false);
1916 super .compWriteObjectNotify();
1917 } finally {
1918 setRootPaneCheckingEnabled(old);
1919 }
1920 }
1921
1922 /**
1923 * Returns a string representation of this <code>JInternalFrame</code>.
1924 * This method
1925 * is intended to be used only for debugging purposes, and the
1926 * content and format of the returned string may vary between
1927 * implementations. The returned string may be empty but may not
1928 * be <code>null</code>.
1929 *
1930 * @return a string representation of this <code>JInternalFrame</code>
1931 */
1932 protected String paramString() {
1933 String rootPaneString = (rootPane != null ? rootPane.toString()
1934 : "");
1935 String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ? "true"
1936 : "false");
1937 String closableString = (closable ? "true" : "false");
1938 String isClosedString = (isClosed ? "true" : "false");
1939 String maximizableString = (maximizable ? "true" : "false");
1940 String isMaximumString = (isMaximum ? "true" : "false");
1941 String iconableString = (iconable ? "true" : "false");
1942 String isIconString = (isIcon ? "true" : "false");
1943 String resizableString = (resizable ? "true" : "false");
1944 String isSelectedString = (isSelected ? "true" : "false");
1945 String frameIconString = (frameIcon != null ? frameIcon
1946 .toString() : "");
1947 String titleString = (title != null ? title : "");
1948 String desktopIconString = (desktopIcon != null ? desktopIcon
1949 .toString() : "");
1950 String openedString = (opened ? "true" : "false");
1951 String defaultCloseOperationString;
1952 if (defaultCloseOperation == HIDE_ON_CLOSE) {
1953 defaultCloseOperationString = "HIDE_ON_CLOSE";
1954 } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
1955 defaultCloseOperationString = "DISPOSE_ON_CLOSE";
1956 } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
1957 defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
1958 } else
1959 defaultCloseOperationString = "";
1960
1961 return super .paramString() + ",closable=" + closableString
1962 + ",defaultCloseOperation="
1963 + defaultCloseOperationString + ",desktopIcon="
1964 + desktopIconString + ",frameIcon=" + frameIconString
1965 + ",iconable=" + iconableString + ",isClosed="
1966 + isClosedString + ",isIcon=" + isIconString
1967 + ",isMaximum=" + isMaximumString + ",isSelected="
1968 + isSelectedString + ",maximizable="
1969 + maximizableString + ",opened=" + openedString
1970 + ",resizable=" + resizableString + ",rootPane="
1971 + rootPaneString + ",rootPaneCheckingEnabled="
1972 + rootPaneCheckingEnabledString + ",title="
1973 + titleString;
1974 }
1975
1976 // ======= begin optimized frame dragging defence code ==============
1977
1978 boolean isDragging = false;
1979 boolean danger = false;
1980
1981 /**
1982 * Overridden to allow optimized painting when the
1983 * internal frame is being dragged.
1984 */
1985 protected void paintComponent(Graphics g) {
1986 if (isDragging) {
1987 // System.out.println("ouch");
1988 danger = true;
1989 }
1990
1991 super .paintComponent(g);
1992 }
1993
1994 // ======= end optimized frame dragging defence code ==============
1995
1996 /////////////////
1997 // Accessibility support
1998 ////////////////
1999
2000 /**
2001 * Gets the <code>AccessibleContext</code> associated with this
2002 * <code>JInternalFrame</code>.
2003 * For internal frames, the <code>AccessibleContext</code>
2004 * takes the form of an
2005 * <code>AccessibleJInternalFrame</code> object.
2006 * A new <code>AccessibleJInternalFrame</code> instance is created if necessary.
2007 *
2008 * @return an <code>AccessibleJInternalFrame</code> that serves as the
2009 * <code>AccessibleContext</code> of this
2010 * <code>JInternalFrame</code>
2011 * @see AccessibleJInternalFrame
2012 */
2013 public AccessibleContext getAccessibleContext() {
2014 if (accessibleContext == null) {
2015 accessibleContext = new AccessibleJInternalFrame();
2016 }
2017 return accessibleContext;
2018 }
2019
2020 /**
2021 * This class implements accessibility support for the
2022 * <code>JInternalFrame</code> class. It provides an implementation of the
2023 * Java Accessibility API appropriate to internal frame user-interface
2024 * elements.
2025 * <p>
2026 * <strong>Warning:</strong>
2027 * Serialized objects of this class will not be compatible with
2028 * future Swing releases. The current serialization support is
2029 * appropriate for short term storage or RMI between applications running
2030 * the same version of Swing. As of 1.4, support for long term storage
2031 * of all JavaBeans<sup><font size="-2">TM</font></sup>
2032 * has been added to the <code>java.beans</code> package.
2033 * Please see {@link java.beans.XMLEncoder}.
2034 */
2035 protected class AccessibleJInternalFrame extends
2036 AccessibleJComponent implements AccessibleValue {
2037
2038 /**
2039 * Get the accessible name of this object.
2040 *
2041 * @return the localized name of the object -- can be <code>null</code> if this
2042 * object does not have a name
2043 * @see #setAccessibleName
2044 */
2045 public String getAccessibleName() {
2046 String name = accessibleName;
2047
2048 if (name == null) {
2049 name = (String) getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
2050 }
2051 if (name == null) {
2052 name = getTitle();
2053 }
2054 return name;
2055 }
2056
2057 /**
2058 * Get the role of this object.
2059 *
2060 * @return an instance of AccessibleRole describing the role of the
2061 * object
2062 * @see AccessibleRole
2063 */
2064 public AccessibleRole getAccessibleRole() {
2065 return AccessibleRole.INTERNAL_FRAME;
2066 }
2067
2068 /**
2069 * Gets the AccessibleValue associated with this object. In the
2070 * implementation of the Java Accessibility API for this class,
2071 * returns this object, which is responsible for implementing the
2072 * <code>AccessibleValue</code> interface on behalf of itself.
2073 *
2074 * @return this object
2075 */
2076 public AccessibleValue getAccessibleValue() {
2077 return this ;
2078 }
2079
2080 //
2081 // AccessibleValue methods
2082 //
2083
2084 /**
2085 * Get the value of this object as a Number.
2086 *
2087 * @return value of the object -- can be <code>null</code> if this object does not
2088 * have a value
2089 */
2090 public Number getCurrentAccessibleValue() {
2091 return new Integer(getLayer());
2092 }
2093
2094 /**
2095 * Set the value of this object as a Number.
2096 *
2097 * @return <code>true</code> if the value was set
2098 */
2099 public boolean setCurrentAccessibleValue(Number n) {
2100 // TIGER - 4422535
2101 if (n == null) {
2102 return false;
2103 }
2104 setLayer(new Integer(n.intValue()));
2105 return true;
2106 }
2107
2108 /**
2109 * Get the minimum value of this object as a Number.
2110 *
2111 * @return Minimum value of the object; <code>null</code> if this object does not
2112 * have a minimum value
2113 */
2114 public Number getMinimumAccessibleValue() {
2115 return new Integer(Integer.MIN_VALUE);
2116 }
2117
2118 /**
2119 * Get the maximum value of this object as a Number.
2120 *
2121 * @return Maximum value of the object; <code>null</code> if this object does not
2122 * have a maximum value
2123 */
2124 public Number getMaximumAccessibleValue() {
2125 return new Integer(Integer.MAX_VALUE);
2126 }
2127
2128 } // AccessibleJInternalFrame
2129
2130 /**
2131 * This component represents an iconified version of a
2132 * <code>JInternalFrame</code>.
2133 * This API should NOT BE USED by Swing applications, as it will go
2134 * away in future versions of Swing as its functionality is moved into
2135 * <code>JInternalFrame</code>. This class is public only so that
2136 * UI objects can display a desktop icon. If an application
2137 * wants to display a desktop icon, it should create a
2138 * <code>JInternalFrame</code> instance and iconify it.
2139 * <p>
2140 * <strong>Warning:</strong>
2141 * Serialized objects of this class will not be compatible with
2142 * future Swing releases. The current serialization support is
2143 * appropriate for short term storage or RMI between applications running
2144 * the same version of Swing. As of 1.4, support for long term storage
2145 * of all JavaBeans<sup><font size="-2">TM</font></sup>
2146 * has been added to the <code>java.beans</code> package.
2147 * Please see {@link java.beans.XMLEncoder}.
2148 *
2149 * @author David Kloba
2150 */
2151 static public class JDesktopIcon extends JComponent implements
2152 Accessible {
2153 JInternalFrame internalFrame;
2154
2155 /**
2156 * Creates an icon for an internal frame.
2157 *
2158 * @param f the <code>JInternalFrame</code>
2159 * for which the icon is created
2160 */
2161 public JDesktopIcon(JInternalFrame f) {
2162 setVisible(false);
2163 setInternalFrame(f);
2164 updateUI();
2165 }
2166
2167 /**
2168 * Returns the look-and-feel object that renders this component.
2169 *
2170 * @return the <code>DesktopIconUI</code> object that renders
2171 * this component
2172 */
2173 public DesktopIconUI getUI() {
2174 return (DesktopIconUI) ui;
2175 }
2176
2177 /**
2178 * Sets the look-and-feel object that renders this component.
2179 *
2180 * @param ui the <code>DesktopIconUI</code> look-and-feel object
2181 * @see UIDefaults#getUI
2182 */
2183 public void setUI(DesktopIconUI ui) {
2184 super .setUI(ui);
2185 }
2186
2187 /**
2188 * Returns the <code>JInternalFrame</code> that this
2189 * <code>DesktopIcon</code> is associated with.
2190 *
2191 * @return the <code>JInternalFrame</code> with which this icon
2192 * is associated
2193 */
2194 public JInternalFrame getInternalFrame() {
2195 return internalFrame;
2196 }
2197
2198 /**
2199 * Sets the <code>JInternalFrame</code> with which this
2200 * <code>DesktopIcon</code> is associated.
2201 *
2202 * @param f the <code>JInternalFrame</code> with which this icon
2203 * is associated
2204 */
2205 public void setInternalFrame(JInternalFrame f) {
2206 internalFrame = f;
2207 }
2208
2209 /**
2210 * Convenience method to ask the icon for the <code>Desktop</code>
2211 * object it belongs to.
2212 *
2213 * @return the <code>JDesktopPane</code> that contains this
2214 * icon's internal frame, or <code>null</code> if none found
2215 */
2216 public JDesktopPane getDesktopPane() {
2217 if (getInternalFrame() != null)
2218 return getInternalFrame().getDesktopPane();
2219 return null;
2220 }
2221
2222 /**
2223 * Notification from the <code>UIManager</code> that the look and feel
2224 * has changed.
2225 * Replaces the current UI object with the latest version from the
2226 * <code>UIManager</code>.
2227 *
2228 * @see JComponent#updateUI
2229 */
2230 public void updateUI() {
2231 boolean hadUI = (ui != null);
2232 setUI((DesktopIconUI) UIManager.getUI(this ));
2233 invalidate();
2234
2235 Dimension r = getPreferredSize();
2236 setSize(r.width, r.height);
2237
2238 if (internalFrame != null && internalFrame.getUI() != null) { // don't do this if UI not created yet
2239 SwingUtilities.updateComponentTreeUI(internalFrame);
2240 }
2241 }
2242
2243 /* This method is called if updateUI was called on the associated
2244 * JInternalFrame. It's necessary to avoid infinite recursion.
2245 */
2246 void updateUIWhenHidden() {
2247 /* Update this UI and any associated internal frame */
2248 setUI((DesktopIconUI) UIManager.getUI(this ));
2249
2250 Dimension r = getPreferredSize();
2251 setSize(r.width, r.height);
2252
2253 invalidate();
2254 Component[] children = getComponents();
2255 if (children != null) {
2256 for (int i = 0; i < children.length; i++) {
2257 SwingUtilities.updateComponentTreeUI(children[i]);
2258 }
2259 }
2260 }
2261
2262 /**
2263 * Returns the name of the look-and-feel
2264 * class that renders this component.
2265 *
2266 * @return the string "DesktopIconUI"
2267 * @see JComponent#getUIClassID
2268 * @see UIDefaults#getUI
2269 */
2270 public String getUIClassID() {
2271 return "DesktopIconUI";
2272 }
2273
2274 ////////////////
2275 // Serialization support
2276 ////////////////
2277 private void writeObject(ObjectOutputStream s)
2278 throws IOException {
2279 s.defaultWriteObject();
2280 if (getUIClassID().equals("DesktopIconUI")) {
2281 byte count = JComponent.getWriteObjCounter(this );
2282 JComponent.setWriteObjCounter(this , --count);
2283 if (count == 0 && ui != null) {
2284 ui.installUI(this );
2285 }
2286 }
2287 }
2288
2289 /////////////////
2290 // Accessibility support
2291 ////////////////
2292
2293 /**
2294 * Gets the AccessibleContext associated with this JDesktopIcon.
2295 * For desktop icons, the AccessibleContext takes the form of an
2296 * AccessibleJDesktopIcon.
2297 * A new AccessibleJDesktopIcon instance is created if necessary.
2298 *
2299 * @return an AccessibleJDesktopIcon that serves as the
2300 * AccessibleContext of this JDesktopIcon
2301 */
2302 public AccessibleContext getAccessibleContext() {
2303 if (accessibleContext == null) {
2304 accessibleContext = new AccessibleJDesktopIcon();
2305 }
2306 return accessibleContext;
2307 }
2308
2309 /**
2310 * This class implements accessibility support for the
2311 * <code>JInternalFrame.JDesktopIcon</code> class. It provides an
2312 * implementation of the Java Accessibility API appropriate to
2313 * desktop icon user-interface elements.
2314 * <p>
2315 * <strong>Warning:</strong>
2316 * Serialized objects of this class will not be compatible with
2317 * future Swing releases. The current serialization support is
2318 * appropriate for short term storage or RMI between applications running
2319 * the same version of Swing. As of 1.4, support for long term storage
2320 * of all JavaBeans<sup><font size="-2">TM</font></sup>
2321 * has been added to the <code>java.beans</code> package.
2322 * Please see {@link java.beans.XMLEncoder}.
2323 */
2324 protected class AccessibleJDesktopIcon extends
2325 AccessibleJComponent implements AccessibleValue {
2326
2327 /**
2328 * Gets the role of this object.
2329 *
2330 * @return an instance of AccessibleRole describing the role of the
2331 * object
2332 * @see AccessibleRole
2333 */
2334 public AccessibleRole getAccessibleRole() {
2335 return AccessibleRole.DESKTOP_ICON;
2336 }
2337
2338 /**
2339 * Gets the AccessibleValue associated with this object. In the
2340 * implementation of the Java Accessibility API for this class,
2341 * returns this object, which is responsible for implementing the
2342 * <code>AccessibleValue</code> interface on behalf of itself.
2343 *
2344 * @return this object
2345 */
2346 public AccessibleValue getAccessibleValue() {
2347 return this ;
2348 }
2349
2350 //
2351 // AccessibleValue methods
2352 //
2353
2354 /**
2355 * Gets the value of this object as a <code>Number</code>.
2356 *
2357 * @return value of the object -- can be <code>null</code> if this object does not
2358 * have a value
2359 */
2360 public Number getCurrentAccessibleValue() {
2361 AccessibleContext a = JDesktopIcon.this
2362 .getInternalFrame().getAccessibleContext();
2363 AccessibleValue v = a.getAccessibleValue();
2364 if (v != null) {
2365 return v.getCurrentAccessibleValue();
2366 } else {
2367 return null;
2368 }
2369 }
2370
2371 /**
2372 * Sets the value of this object as a <code>Number</code>.
2373 *
2374 * @return <code>true</code> if the value was set
2375 */
2376 public boolean setCurrentAccessibleValue(Number n) {
2377 // TIGER - 4422535
2378 if (n == null) {
2379 return false;
2380 }
2381 AccessibleContext a = JDesktopIcon.this
2382 .getInternalFrame().getAccessibleContext();
2383 AccessibleValue v = a.getAccessibleValue();
2384 if (v != null) {
2385 return v.setCurrentAccessibleValue(n);
2386 } else {
2387 return false;
2388 }
2389 }
2390
2391 /**
2392 * Gets the minimum value of this object as a <code>Number</code>.
2393 *
2394 * @return minimum value of the object; <code>null</code> if this object does not
2395 * have a minimum value
2396 */
2397 public Number getMinimumAccessibleValue() {
2398 AccessibleContext a = JDesktopIcon.this
2399 .getInternalFrame().getAccessibleContext();
2400 if (a instanceof AccessibleValue) {
2401 return ((AccessibleValue) a)
2402 .getMinimumAccessibleValue();
2403 } else {
2404 return null;
2405 }
2406 }
2407
2408 /**
2409 * Gets the maximum value of this object as a <code>Number</code>.
2410 *
2411 * @return maximum value of the object; <code>null</code> if this object does not
2412 * have a maximum value
2413 */
2414 public Number getMaximumAccessibleValue() {
2415 AccessibleContext a = JDesktopIcon.this
2416 .getInternalFrame().getAccessibleContext();
2417 if (a instanceof AccessibleValue) {
2418 return ((AccessibleValue) a)
2419 .getMaximumAccessibleValue();
2420 } else {
2421 return null;
2422 }
2423 }
2424
2425 } // AccessibleJDesktopIcon
2426 }
2427 }
|