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