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