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