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