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