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