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