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