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