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