1. /*
  2. * @(#)JInternalFrame.java 1.116 01/02/09
  3. *
  4. * Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing;
  11. import java.awt.*;
  12. import java.awt.event.*;
  13. import java.beans.PropertyVetoException;
  14. import java.beans.PropertyChangeEvent;
  15. import java.util.EventListener;
  16. import javax.swing.border.Border;
  17. import javax.swing.event.InternalFrameEvent;
  18. import javax.swing.event.InternalFrameListener;
  19. import javax.swing.plaf.*;
  20. import javax.accessibility.*;
  21. import java.io.ObjectOutputStream;
  22. import java.io.ObjectInputStream;
  23. import java.io.IOException;
  24. /**
  25. * A lightweight object that provides many of the features of
  26. * a native frame, including dragging, closing, becoming an icon,
  27. * resizing, title display, and support for a menu bar.
  28. * For task-oriented documentation and examples of using internal frames,
  29. * see <a
  30. href="http://java.sun.com/docs/books/tutorial/uiswing/components/internalframe.html">How to Use Internal Frames</a>,
  31. * a section in <em>The Java Tutorial</em>.
  32. *
  33. * <p>
  34. *
  35. * Generally,
  36. * you add <code>JInternalFrame</code>s to a <code>JDesktopPane</code>. The UI
  37. * delegates the look-and-feel-specific actions to the
  38. * <code>DesktopManager</code>
  39. * object maintained by the <code>JDesktopPane</code>.
  40. * <p>
  41. * The <code>JInternalFrame</code> <code>contentPane</code>
  42. * is where you add child components.
  43. * So, to create a <code>JInternalFrame</code> that has a number of
  44. * buttons arranged
  45. * with a <code>BorderLayout</code> object, you might do something like this:
  46. * <pre>
  47. * JComponent c = (JComponent) frame.getContentPane();
  48. * c.setLayout(new BorderLayout());
  49. * c.add(new JButton(), BorderLayout.NORTH);
  50. * c.add(new JButton(), BorderLayout.CENTER);
  51. * </pre>
  52. * The <code>contentPane</code> is actually managed by an instance of
  53. * <code>JRootPane</code>,
  54. * which also manages a <code>layoutPane</code>, <code>glassPane</code>, and
  55. * optional <code>menuBar</code> for the frame. Please see the
  56. * <code>JRootPane</code>
  57. * documentation for a complete description of these components.
  58. * <p>
  59. * For the keyboard keys used by this component in the standard Look and
  60. * Feel (L&F) renditions, see the
  61. * <a href="doc-files/Key-Index.html#JInternalFrame">JInternalFrame</a> key assignments.
  62. * <p>
  63. * <strong>Warning:</strong>
  64. * Serialized objects of this class will not be compatible with
  65. * future Swing releases. The current serialization support is appropriate
  66. * for short term storage or RMI between applications running the same
  67. * version of Swing. A future release of Swing will provide support for
  68. * long term persistence.
  69. *
  70. * @see JDesktopPane
  71. * @see DesktopManager
  72. * @see JInternalFrame.JDesktopIcon
  73. * @see JRootPane
  74. *
  75. * @version 1.116 02/09/01
  76. * @author David Kloba
  77. * @author Rich Schiavi
  78. * @beaninfo
  79. * attribute: isContainer true
  80. * attribute: containerDelegate getContentPane
  81. * description: A frame container which is contained within
  82. * another window.
  83. */
  84. public class JInternalFrame extends JComponent implements
  85. Accessible, WindowConstants,
  86. RootPaneContainer
  87. {
  88. /**
  89. * @see #getUIClassID
  90. * @see #readObject
  91. */
  92. private static final String uiClassID = "InternalFrameUI";
  93. /**
  94. * The <code>JRootPane</code> instance that manages the
  95. * <code>contentPane</code>
  96. * and optional <code>menuBar</code> for this frame, as well as the
  97. * <code>glassPane</code>.
  98. *
  99. * @see JRootPane
  100. * @see RootPaneContainer
  101. */
  102. protected JRootPane rootPane;
  103. /**
  104. * If true then calls to <code>add</code> and <code>setLayout</code>
  105. * cause an exception to be thrown.
  106. */
  107. protected boolean rootPaneCheckingEnabled = false;
  108. /** The frame can be closed. */
  109. protected boolean closable;
  110. /** The frame has been closed. */
  111. protected boolean isClosed;
  112. /** The frame can be expanded to the size of the desktop pane. */
  113. protected boolean maximizable;
  114. /**
  115. * The frame has been expanded to its maximum size.
  116. * @see #maximizable
  117. */
  118. protected boolean isMaximum;
  119. /**
  120. * The frame can "iconized" (shrunk down and displayed as
  121. * an icon-image).
  122. * @see JInternalFrame.JDesktopIcon
  123. */
  124. protected boolean iconable;
  125. /**
  126. * The frame has been iconized.
  127. * @see #iconable
  128. */
  129. protected boolean isIcon;
  130. /** The frame's size can be changed. */
  131. protected boolean resizable;
  132. /** The frame is currently selected. */
  133. protected boolean isSelected;
  134. /** The icon shown in the top-left corner of the frame. */
  135. protected Icon frameIcon;
  136. /** The title displayed in the frame's title bar. */
  137. protected String title;
  138. /**
  139. * The icon that is displayed when the frame is iconized.
  140. * @see #iconable
  141. */
  142. protected JDesktopIcon desktopIcon;
  143. private boolean opened;
  144. private Rectangle normalBounds = null;
  145. private int defaultCloseOperation = DISPOSE_ON_CLOSE;
  146. private Component lastFocusOwner;
  147. /** Bound property name. */
  148. public final static String CONTENT_PANE_PROPERTY = "contentPane";
  149. /** Bound property name. */
  150. public final static String MENU_BAR_PROPERTY = "menuBar";
  151. /** Bound property name. */
  152. public final static String TITLE_PROPERTY = "title";
  153. /** Bound property name. */
  154. public final static String LAYERED_PANE_PROPERTY = "layeredPane";
  155. /** Bound property name. */
  156. public final static String ROOT_PANE_PROPERTY = "rootPane";
  157. /** Bound property name. */
  158. public final static String GLASS_PANE_PROPERTY = "glassPane";
  159. /** Bound property name. */
  160. public final static String FRAME_ICON_PROPERTY = "frameIcon";
  161. /**
  162. * Constrained property name indicated that this frame has
  163. * selected status.
  164. */
  165. public final static String IS_SELECTED_PROPERTY = "selected";
  166. /** Constrained property name indicating that the frame is closed. */
  167. public final static String IS_CLOSED_PROPERTY = "closed";
  168. /** Constrained property name indicating that the frame is maximized. */
  169. public final static String IS_MAXIMUM_PROPERTY = "maximum";
  170. /** Constrained property name indicating that the frame is iconified. */
  171. public final static String IS_ICON_PROPERTY = "icon";
  172. /**
  173. * Creates a non-resizable, non-closable, non-maximizable,
  174. * non-iconifiable <code>JInternalFrame</code> with no title.
  175. */
  176. public JInternalFrame() {
  177. this("", false, false, false, false);
  178. }
  179. /**
  180. * Creates a non-resizable, non-closable, non-maximizable,
  181. * non-iconifiable <code>JInternalFrame</code> with the specified title.
  182. *
  183. * @param title the <code>String</code> to display in the title bar
  184. */
  185. public JInternalFrame(String title) {
  186. this(title, false, false, false, false);
  187. }
  188. /**
  189. * Creates a non-closable, non-maximizable, non-iconifiable
  190. * <code>JInternalFrame</code> with the specified title
  191. * and with resizability specified.
  192. *
  193. * @param title the <code>String</code> to display in the title bar
  194. * @param resizable if true, the frame can be resized
  195. */
  196. public JInternalFrame(String title, boolean resizable) {
  197. this(title, resizable, false, false, false);
  198. }
  199. /**
  200. * Creates a non-maximizable, non-iconifiable <code>JInternalFrame</code>
  201. * with the specified title and with resizability and
  202. * closability specified.
  203. *
  204. * @param title the <code>String</code> to display in the title bar
  205. * @param resizable if true, the frame can be resized
  206. * @param closable if true, the frame can be closed
  207. */
  208. public JInternalFrame(String title, boolean resizable, boolean closable) {
  209. this(title, resizable, closable, false, false);
  210. }
  211. /**
  212. * Creates a non-iconifiable <code>JInternalFrame</code>
  213. * with the specified title
  214. * and with resizability, closability, and maximizability specified.
  215. *
  216. * @param title the <code>String</code> to display in the title bar
  217. * @param resizable if true, the frame can be resized
  218. * @param closable if true, the frame can be closed
  219. * @param maximizable if true, the frame can be maximized
  220. */
  221. public JInternalFrame(String title, boolean resizable, boolean closable,
  222. boolean maximizable) {
  223. this(title, resizable, closable, maximizable, false);
  224. }
  225. /**
  226. * Creates a <code>JInternalFrame</code> with the specified title and
  227. * with resizability, closability, maximizability, and iconifiability
  228. * specified. All constructors defer to this one.
  229. *
  230. * @param title the <code>String</code> to display in the title bar
  231. * @param resizable if true, the frame can be resized
  232. * @param closable if true, the frame can be closed
  233. * @param maximizable if true, the frame can be maximized
  234. * @param iconifiable if true, the frame can be iconified
  235. */
  236. public JInternalFrame(String title, boolean resizable, boolean closable,
  237. boolean maximizable, boolean iconifiable) {
  238. setRootPane(createRootPane());
  239. setLayout(new BorderLayout());
  240. this.title = title;
  241. this.resizable = resizable;
  242. this.closable = closable;
  243. this.maximizable = maximizable;
  244. isMaximum = false;
  245. this.iconable = iconifiable;
  246. isIcon = false;
  247. setVisible(false);
  248. setRootPaneCheckingEnabled(true);
  249. desktopIcon = new JDesktopIcon(this);
  250. updateUI();
  251. }
  252. /**
  253. * Called by the constructor to set up the <code>JRootPane</code>.
  254. * @return a new <code>JRootPane</code>
  255. * @see JRootPane
  256. */
  257. protected JRootPane createRootPane() {
  258. return new JRootPane();
  259. }
  260. /**
  261. * Returns the L&F object that renders this component.
  262. *
  263. * @return the <code>InternalFrameUI</code> object that renders
  264. * this component
  265. */
  266. public InternalFrameUI getUI() {
  267. return (InternalFrameUI)ui;
  268. }
  269. /**
  270. * Sets the UI delegate for this <code>JInternalFrame</code>.
  271. * @beaninfo
  272. * expert: true
  273. * description: The InternalFrameUI implementation that
  274. * defines the labels look and feel.
  275. */
  276. public void setUI(InternalFrameUI ui) {
  277. boolean checkingEnabled = isRootPaneCheckingEnabled();
  278. try {
  279. setRootPaneCheckingEnabled(false);
  280. super.setUI(ui);
  281. }
  282. finally {
  283. setRootPaneCheckingEnabled(checkingEnabled);
  284. }
  285. }
  286. /**
  287. * Notification from the <code>UIManager</code> that the L&F has changed.
  288. * Replaces the current UI object with the latest version from the
  289. * <code>UIManager</code>.
  290. *
  291. * @see JComponent#updateUI
  292. */
  293. public void updateUI() {
  294. setUI((InternalFrameUI)UIManager.getUI(this));
  295. invalidate();
  296. if (desktopIcon != null) {
  297. desktopIcon.updateUIWhenHidden();
  298. }
  299. }
  300. /* This method is called if updateUI was called on the associated
  301. * JDesktopIcon. It's necessary to avoid infinite recursion.
  302. */
  303. void updateUIWhenHidden() {
  304. setUI((InternalFrameUI)UIManager.getUI(this));
  305. invalidate();
  306. Component[] children = getComponents();
  307. if (children != null) {
  308. for(int i = 0; i < children.length; i++) {
  309. SwingUtilities.updateComponentTreeUI(children[i]);
  310. }
  311. }
  312. }
  313. /**
  314. * Returns the name of the L&F class which renders this component.
  315. *
  316. * @return the string "InternalFrameUI"
  317. * @see JComponent#getUIClassID
  318. * @see UIDefaults#getUI
  319. * @beaninfo
  320. * description: UIClassID
  321. */
  322. public String getUIClassID() {
  323. return uiClassID;
  324. }
  325. /**
  326. * Returns whether calls to <code>add</code> and
  327. * <code>setLayout</code> cause an exception to be thrown.
  328. *
  329. * @return true if <code>add</code> and <code>setLayout</code>
  330. * are checked
  331. * @see #addImpl
  332. * @see #setLayout
  333. * @see #setRootPaneCheckingEnabled
  334. */
  335. protected boolean isRootPaneCheckingEnabled() {
  336. return rootPaneCheckingEnabled;
  337. }
  338. /**
  339. * Determines whether calls to <code>add</code> and
  340. * <code>setLayout</code> cause an exception to be thrown.
  341. *
  342. * @param enabled a boolean value, true if checking is to be
  343. * enabled, which cause the exceptions to be thrown
  344. *
  345. * @see #addImpl
  346. * @see #setLayout
  347. * @see #isRootPaneCheckingEnabled
  348. */
  349. protected void setRootPaneCheckingEnabled(boolean enabled) {
  350. rootPaneCheckingEnabled = enabled;
  351. }
  352. /**
  353. * Creates a runtime exception with a message like:
  354. * <pre>
  355. * "Do not use JFrame.add() use JFrame.getContentPane().add() instead"
  356. * </pre>
  357. *
  358. * @param op a <code>String</code> indicating the attempted operation;
  359. * in the example above, the operation string is "add"
  360. */
  361. private Error createRootPaneException(String op) {
  362. String type = getClass().getName();
  363. return new Error(
  364. "Do not use " + type + "." + op + "() use "
  365. + type + ".getContentPane()." + op + "() instead");
  366. }
  367. /**
  368. * By default, children may not be added directly to a this component,
  369. * they must be added to its <code>contentPane</code> instead.
  370. * For example:
  371. * <pre>
  372. * thisComponent.getContentPane().add(child)
  373. * </pre>
  374. * An attempt to add to directly to this component will cause an
  375. * runtime exception to be thrown. Subclasses can disable this
  376. * behavior.
  377. *
  378. * @see #setRootPaneCheckingEnabled
  379. * @exception Error if called with <code>isRootPaneChecking</code> true
  380. */
  381. protected void addImpl(Component comp, Object constraints, int index)
  382. {
  383. if(isRootPaneCheckingEnabled()) {
  384. throw createRootPaneException("add");
  385. }
  386. else {
  387. super.addImpl(comp, constraints, index);
  388. }
  389. }
  390. /**
  391. * Removes the specified component from this container.
  392. * @param comp the component to be removed
  393. * @see #add
  394. */
  395. public void remove(Component comp) {
  396. int oldCount = getComponentCount();
  397. super.remove(comp);
  398. if (oldCount == getComponentCount()) {
  399. // Client mistake, but we need to handle it to avoid a
  400. // common object leak in client applications.
  401. getContentPane().remove(comp);
  402. }
  403. }
  404. /**
  405. * By default the layout of this component may not be set,
  406. * the layout of its <code>contentPane</code> should be set instead.
  407. * For example:
  408. * <pre>
  409. * thisComponent.getContentPane().setLayout(new BorderLayout())
  410. * </pre>
  411. * An attempt to set the layout of this component will cause an
  412. * runtime exception to be thrown. Subclasses can disable this
  413. * behavior.
  414. *
  415. * @param manager the <code>LayoutManager</code>
  416. * @see #setRootPaneCheckingEnabled
  417. * @exception Error if called with <code>isRootPaneChecking</code> true
  418. */
  419. public void setLayout(LayoutManager manager) {
  420. if(isRootPaneCheckingEnabled()) {
  421. throw createRootPaneException("setLayout");
  422. }
  423. else {
  424. super.setLayout(manager);
  425. }
  426. }
  427. //////////////////////////////////////////////////////////////////////////
  428. /// Property Methods
  429. //////////////////////////////////////////////////////////////////////////
  430. /**
  431. * Returns the current <code>JMenuBar</code> for this
  432. * <code>JInternalFrame</code>, or <code>null</code>
  433. * if no menu bar has been set.
  434. * @return the current menubar or <code>null</code> if none has been set
  435. *
  436. * @deprecated As of Swing version 1.0.3,
  437. * replaced by <code>getJMenuBar()</code>.
  438. */
  439. public JMenuBar getMenuBar() {
  440. return getRootPane().getMenuBar();
  441. }
  442. /**
  443. * Returns the current <code>JMenuBar</code> for this
  444. * <code>JInternalFrame</code>, or <code>null</code>
  445. * if no menu bar has been set.
  446. *
  447. * @return the <code>JMenuBar</code> used by this frame
  448. * @see #setJMenuBar
  449. */
  450. public JMenuBar getJMenuBar() {
  451. return getRootPane().getJMenuBar();
  452. }
  453. /**
  454. * Sets the <code>JMenuBar</code> for this <code>JInternalFrame</code>.
  455. *
  456. * @param m the <code>JMenuBar</code> to use in this frame
  457. * @see #getJMenuBar
  458. * @deprecated As of Swing version 1.0.3
  459. * replaced by <code>setJMenuBar(JMenuBar m)</code>.
  460. */
  461. public void setMenuBar(JMenuBar m) {
  462. JMenuBar oldValue = getMenuBar();
  463. getRootPane().setJMenuBar(m);
  464. firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
  465. }
  466. /**
  467. * Sets the <code>JMenuBar</code> for this <code>JInternalFrame</code>.
  468. *
  469. * @param m the <code>JMenuBar</code> to use in this frame
  470. * @see #getJMenuBar
  471. * @beaninfo
  472. * bound: true
  473. * preferred: true
  474. * description: The menubar for accessing pulldown menus
  475. * from this frame.
  476. */
  477. public void setJMenuBar(JMenuBar m){
  478. JMenuBar oldValue = getMenuBar();
  479. getRootPane().setJMenuBar(m);
  480. firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
  481. }
  482. // implements javax.swing.RootPaneContainer
  483. public Container getContentPane() {
  484. return getRootPane().getContentPane();
  485. }
  486. /**
  487. * Sets this <code>JInternalFrame</code>'s content pane.
  488. *
  489. * @param c the <code>contentPane</code> object for this frame
  490. *
  491. * @exception java.awt.IllegalComponentStateException (a runtime
  492. * exception) if the content pane parameter is <code>null</code>
  493. * @see RootPaneContainer#getContentPane
  494. * @beaninfo
  495. * bound: true
  496. * hidden: true
  497. * description: The client area of the frame where child
  498. * components are normally inserted.
  499. */
  500. public void setContentPane(Container c) {
  501. Container oldValue = getContentPane();
  502. getRootPane().setContentPane(c);
  503. firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c);
  504. }
  505. /**
  506. * Returns the <code>layeredPane</code> object for this frame.
  507. *
  508. * @return the <code>layeredPane</code> object
  509. * @see RootPaneContainer#setLayeredPane
  510. * @see RootPaneContainer#getLayeredPane
  511. */
  512. public JLayeredPane getLayeredPane() {
  513. return getRootPane().getLayeredPane();
  514. }
  515. /**
  516. * Sets this <code>JInternalFrame</code>'s <code>layeredPane</code>
  517. * property.
  518. * @param layered the <code>layeredPane</code> object for this frame
  519. *
  520. * @exception java.awt.IllegalComponentStateException (a runtime
  521. * exception) if the layered pane parameter is <code>null</code>
  522. * @see RootPaneContainer#setLayeredPane
  523. * @beaninfo
  524. * hidden: true
  525. * bound: true
  526. * description: The pane which holds the various desktop layers.
  527. */
  528. public void setLayeredPane(JLayeredPane layered) {
  529. JLayeredPane oldValue = getLayeredPane();
  530. getRootPane().setLayeredPane(layered);
  531. firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered);
  532. }
  533. /**
  534. * Returns the <code>glassPane</code> object for this frame.
  535. *
  536. * @return the <code>glassPane</code> object
  537. * @see RootPaneContainer#setGlassPane
  538. */
  539. public Component getGlassPane() {
  540. return getRootPane().getGlassPane();
  541. }
  542. /**
  543. * Sets this <code>JInternalFrame</code>'s <code>glassPane</code>
  544. * property.
  545. * @param glassPane the <code>glassPane</code> object for this frame
  546. * @see RootPaneContainer#getGlassPane
  547. * @beaninfo
  548. * bound: true
  549. * hidden: true
  550. * description: A transparent pane used for menu rendering.
  551. */
  552. public void setGlassPane(Component glass) {
  553. Component oldValue = getGlassPane();
  554. getRootPane().setGlassPane(glass);
  555. firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass);
  556. }
  557. /**
  558. * Returns the <code>rootPane</code> object for this frame.
  559. *
  560. * @return the <code>rootPane</code> property
  561. * @see RootPaneContainer#getRootPane
  562. */
  563. public JRootPane getRootPane() {
  564. return rootPane;
  565. }
  566. /**
  567. * Sets the <code>rootPane</code> property.
  568. * This method is called by the constructor.
  569. *
  570. * @param root the new <code>rootPane</code> object
  571. * @beaninfo
  572. * bound: true
  573. * hidden: true
  574. * description: The rootPane used by this frame.
  575. */
  576. protected void setRootPane(JRootPane root) {
  577. if(rootPane != null) {
  578. remove(rootPane);
  579. }
  580. JRootPane oldValue = getRootPane();
  581. rootPane = root;
  582. if(rootPane != null) {
  583. boolean checkingEnabled = isRootPaneCheckingEnabled();
  584. try {
  585. setRootPaneCheckingEnabled(false);
  586. add(rootPane, BorderLayout.CENTER);
  587. }
  588. finally {
  589. setRootPaneCheckingEnabled(checkingEnabled);
  590. }
  591. }
  592. firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root);
  593. }
  594. /**
  595. * Sets that this <code>JInternalFrame</code> can be closed by
  596. * some user action.
  597. * @param b a boolean value, where true means the frame can be closed
  598. * @beaninfo
  599. * preferred: true
  600. * bound: true
  601. * description: Indicates whether this frame can be closed.
  602. */
  603. public void setClosable(boolean b) {
  604. Boolean oldValue = closable ? Boolean.TRUE : Boolean.FALSE;
  605. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  606. closable = b;
  607. firePropertyChange("closable", oldValue, newValue);
  608. }
  609. /**
  610. * Returns whether this <code>JInternalFrame</code> be closed by
  611. * some user action.
  612. * @return true if the frame can be closed
  613. */
  614. public boolean isClosable() {
  615. return closable;
  616. }
  617. /**
  618. * Returns whether this <code>JInternalFrame</code> is currently closed.
  619. * @return true if the frame is closed
  620. */
  621. public boolean isClosed() {
  622. return isClosed;
  623. }
  624. /**
  625. * Calling this method with a value of <code>true</code> to close
  626. * the frame.
  627. *
  628. * @param b a boolean, where true means "close the frame"
  629. * @exception PropertyVetoException when the attempt to set the
  630. * property is vetoed by the <code>JInternalFrame</code>
  631. * @beaninfo
  632. * bound: true
  633. * constrained: true
  634. * description: Indicates that the frame has been closed.
  635. */
  636. public void setClosed(boolean b) throws PropertyVetoException {
  637. if (isClosed == b) {
  638. return;
  639. }
  640. Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE;
  641. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  642. if (b) {
  643. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
  644. }
  645. fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue);
  646. isClosed = b;
  647. firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue);
  648. if (isClosed) {
  649. dispose();
  650. } else if (!opened) {
  651. /* this bogus -- we haven't defined what
  652. setClosed(true) means. */
  653. // fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
  654. // opened = true;
  655. }
  656. }
  657. /**
  658. * Sets that the <code>JInternalFrame</code> can be resized by some
  659. * user action.
  660. *
  661. * @param b a boolean, where true means the frame can be resized
  662. * @beaninfo
  663. * preferred: true
  664. * bound: true
  665. * description: Determines whether the frame can be resized
  666. * by the user.
  667. */
  668. public void setResizable(boolean b) {
  669. Boolean oldValue = resizable ? Boolean.TRUE : Boolean.FALSE;
  670. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  671. resizable = b;
  672. firePropertyChange("resizable", oldValue, newValue);
  673. }
  674. /**
  675. * Returns whether the <code>JInternalFrame</code> can be resized
  676. * by some user action.
  677. *
  678. * @return true if the frame can be resized
  679. */
  680. public boolean isResizable() {
  681. // don't allow resizing when maximized.
  682. return isMaximum ? false : resizable;
  683. }
  684. /**
  685. * Sets that the <code>JInternalFrame</code> can be made an
  686. * icon by some user action.
  687. *
  688. * @param b a boolean, where true means the frame can be iconified
  689. * @beaninfo
  690. * preferred: true
  691. * description: Determines whether this frame can be iconified.
  692. */
  693. public void setIconifiable(boolean b) {
  694. iconable = b;
  695. }
  696. /**
  697. * Returns whether the <code>JInternalFrame</code> can be
  698. * iconified by some user action.
  699. *
  700. * @return true if the frame can be iconified
  701. */
  702. public boolean isIconifiable() {
  703. return iconable;
  704. }
  705. /**
  706. * Returns whether the <code>JInternalFrame</code> is currently iconified.
  707. *
  708. * @return true if the frame is iconified
  709. */
  710. public boolean isIcon() {
  711. return isIcon;
  712. }
  713. /**
  714. * Iconizes and de-iconizes the frame.
  715. *
  716. * @param b a boolean, where true means to iconify the frame and
  717. * false means to de-iconify it
  718. * @exception PropertyVetoException when the attempt to set the
  719. * property is vetoed by the <code>JInternalFrame</code>
  720. * @beaninfo
  721. * bound: true
  722. * constrained: true
  723. * description: The image displayed when this frame is minimized.
  724. */
  725. public void setIcon(boolean b) throws PropertyVetoException {
  726. if (isIcon == b) {
  727. return;
  728. }
  729. /* If an internal frame is being iconified before it has a
  730. parent, (e.g., client wants it to start iconic), create the
  731. parent if possible so that we can place the icon in its
  732. proper place on the desktop. I am not sure the call to
  733. validate() is necessary, since we are not going to display
  734. this frame yet */
  735. Container c = getParent();
  736. if (c != null && c.getPeer() == null) {
  737. c.addNotify();
  738. addNotify();
  739. }
  740. validate();
  741. Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE;
  742. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  743. fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue);
  744. isIcon = b;
  745. firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue);
  746. if (b)
  747. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED);
  748. else
  749. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
  750. }
  751. /**
  752. * Sets that the <code>JInternalFrame</code> can be maximized by
  753. * some user action.
  754. *
  755. * @param b a boolean where true means the frame can be maximized
  756. * @beaninfo
  757. * bound: true
  758. * preferred: true
  759. * description: Determines whether this frame can be maximized.
  760. */
  761. public void setMaximizable(boolean b) {
  762. Boolean oldValue = maximizable ? Boolean.TRUE : Boolean.FALSE;
  763. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  764. maximizable = b;
  765. firePropertyChange("maximizable", oldValue, newValue);
  766. }
  767. /**
  768. * Returns whether the <code>JInternalFrame</code> can be maximized
  769. * by some user action.
  770. *
  771. * @return true if the frame can be maximized
  772. */
  773. public boolean isMaximizable() {
  774. return maximizable;
  775. }
  776. /**
  777. * Returns whether the <code>JInternalFrame</code> is currently maximized.
  778. *
  779. * @return true if the frame is maximized
  780. */
  781. public boolean isMaximum() {
  782. return isMaximum;
  783. }
  784. /**
  785. * Maximizes and restores the frame. A maximized frame is resized to
  786. * fully fit the <code>JDesktopPane</code> area associated with the
  787. * <code>JInternalFrame</code>.
  788. * A restored frame's size is set to the <code>JInternalFrame</code>'s
  789. * actual size.
  790. *
  791. * @param b a boolean, where true maximizes the frame and false
  792. * restores it
  793. * @exception PropertyVetoException when the attempt to set the
  794. * property is vetoed by the <code>JInternalFrame</code>
  795. * @beaninfo
  796. * bound: true
  797. * constrained: true
  798. * description: Indicates whether the frame is maximized.
  799. */
  800. public void setMaximum(boolean b) throws PropertyVetoException {
  801. if (isMaximum == b) {
  802. return;
  803. }
  804. Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE;
  805. Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
  806. fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
  807. /* setting isMaximum above the event firing means that
  808. property listeners that, for some reason, test it will
  809. get it wrong... See, for example, getNormalBounds() */
  810. isMaximum = b;
  811. firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
  812. }
  813. /**
  814. * Returns the title of the <code>JInternalFrame</code>.
  815. *
  816. * @return a <code>String</code> containing the frame's title
  817. * @see #setTitle
  818. */
  819. public String getTitle() {
  820. return title;
  821. }
  822. /**
  823. * Sets the <code>JInternalFrame</code> title. <code>title</code>
  824. * may have a <code>null</code> value.
  825. * @see #getTitle
  826. *
  827. * @param title the <code>String</code> to display in the title bar
  828. * @beaninfo
  829. * preferred: true
  830. * bound: true
  831. * description: The text displayed in the title bar.
  832. */
  833. public void setTitle(String title) {
  834. String oldValue = this.title;
  835. this.title = title;
  836. firePropertyChange(TITLE_PROPERTY, oldValue, title);
  837. }
  838. /**
  839. * Selects and deselects the JInternalFrame.
  840. * A JInternalFrame normally draws its title bar differently if it is
  841. * the selected frame, which indicates to the user that this
  842. * internalFrame has the focus.
  843. *
  844. * @param selected a boolean, where true means the frame is selected
  845. * (currently active) and false means it is not
  846. * @exception PropertyVetoException when the attempt to set the
  847. * property is vetoed by the receiver.
  848. * @beaninfo
  849. * constrained: true
  850. * bound: true
  851. * description: Indicates whether this frame is currently
  852. * the active frame.
  853. */
  854. public void setSelected(boolean selected) throws PropertyVetoException {
  855. if ((isSelected == selected) || (selected && !isShowing())) {
  856. return;
  857. }
  858. Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE;
  859. Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE;
  860. fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue);
  861. /* We don't want to leave focus in the previously selected
  862. frame, so we have to set it to *something* in case it
  863. doesn't get set in some other way (as if a user clicked on
  864. a component that doesn't request focus). If this call is
  865. happening because the user clicked on a component that will
  866. want focus, then it will get transfered there later.
  867. We test for parent.isShowing() above, because AWT throws a
  868. NPE if you try to request focus on a lightweight before its
  869. parent has been made visible */
  870. if(selected) {
  871. JRootPane r = getRootPane();
  872. if (r.getCurrentFocusOwner() != null) {/* do nothing */
  873. } else if (r.getPreviousFocusOwner() != null) {
  874. r.getPreviousFocusOwner().requestFocus();
  875. } else {
  876. getContentPane().requestFocus();
  877. }
  878. }
  879. isSelected = selected;
  880. firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue);
  881. if (isSelected)
  882. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED);
  883. else
  884. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
  885. repaint();
  886. }
  887. /**
  888. * Returns whether the JInternalFrame is the currently "selected" or
  889. * active frame.
  890. *
  891. * @return true if the frame is currently selected (active)
  892. * @see #setSelected
  893. */
  894. public boolean isSelected() {
  895. return isSelected;
  896. }
  897. /**
  898. * Sets an image to be displayed in the titlebar of the frame (usually
  899. * in the top-left corner).
  900. * This image is not the <code>desktopIcon</code> object, which
  901. * is the image displayed in the JDesktop when the frame is iconified.
  902. *
  903. * Passing null to this function is valid, but the L&F can choose the
  904. * appropriate behavior for that situation, such as displaying no icon
  905. * or a default icon for the L&F.
  906. *
  907. * @param icon the Icon to display in the title bar
  908. * @see #getFrameIcon
  909. * @beaninfo
  910. * bound: true
  911. * description: The icon shown in the top-left corner of the frame.
  912. */
  913. public void setFrameIcon(Icon icon) {
  914. Icon oldIcon = frameIcon;
  915. frameIcon = icon;
  916. firePropertyChange(FRAME_ICON_PROPERTY, oldIcon, icon);
  917. }
  918. /**
  919. * Returns the image displayed in the title bar of the frame (usually
  920. * in the top-left corner).
  921. *
  922. * @return the Icon displayed in the title bar
  923. * @see #setFrameIcon
  924. */
  925. public Icon getFrameIcon() {
  926. return frameIcon;
  927. }
  928. /** Convenience method that moves this component to position 0 if its
  929. * parent is a JLayeredPane.
  930. */
  931. public void moveToFront() {
  932. if(getParent() != null && getParent() instanceof JLayeredPane) {
  933. JLayeredPane l = (JLayeredPane)getParent();
  934. JRootPane root = getRootPane();
  935. Component focusOwner = (root != null) ?
  936. root.getCurrentFocusOwner() : null;
  937. if (focusOwner != null) {
  938. // Temporarily request focus on the JInternalFrame as a
  939. // workaround for the focus owner not being nulled out
  940. // during Component.removeNotify.
  941. requestFocus();
  942. }
  943. l.moveToFront(this);
  944. // Moving to front often times results in removing the
  945. // JInternalFrame from the containment hierarchy, and adding again.
  946. // As such, the focus will often times be reset, and we therefore
  947. // need to request focus again here.
  948. if (focusOwner != null) {
  949. focusOwner.requestFocus();
  950. }
  951. }
  952. }
  953. /** Convenience method that moves this component to position -1 if its
  954. * parent is a JLayeredPane.
  955. */
  956. public void moveToBack() {
  957. if(getParent() != null && getParent() instanceof JLayeredPane) {
  958. JLayeredPane l = (JLayeredPane)getParent();
  959. l.moveToBack(this);
  960. }
  961. }
  962. /**
  963. * Convenience method for setting the layer attribute of this component.
  964. *
  965. * @param layer an Integer object specifying this frame's desktop layer
  966. * @see JLayeredPane
  967. * @beaninfo
  968. * expert: true
  969. * description: Specifies what desktop layer is used.
  970. */
  971. public void setLayer(Integer layer) {
  972. if(getParent() != null && getParent() instanceof JLayeredPane) {
  973. // Normally we want to do this, as it causes the LayeredPane
  974. // to draw properly.
  975. JLayeredPane p = (JLayeredPane)getParent();
  976. p.setLayer(this, layer.intValue(), p.getPosition(this));
  977. } else {
  978. // Try to do the right thing
  979. JLayeredPane.putLayer(this, layer.intValue());
  980. if(getParent() != null)
  981. getParent().repaint(_bounds.x, _bounds.y,
  982. _bounds.width, _bounds.height);
  983. }
  984. }
  985. /**
  986. * Convenience method for setting the layer attribute of this component.
  987. * The method setLayer(Integer) should be used for layer values predefined
  988. * in JLayeredPane. When using setLayer(int), care must be taken not to
  989. * accidentally clash with those values.
  990. *
  991. * @param layer an int specifying this frame's desktop layer
  992. * @see #setLayer(Integer)
  993. * @see JLayeredPane
  994. * @beaninfo
  995. * expert: true
  996. * description: Specifies what desktop layer is used.
  997. */
  998. public void setLayer(int layer) {
  999. this.setLayer(new Integer(layer));
  1000. }
  1001. /** Convenience method for getting the layer attribute of this component.
  1002. *
  1003. * @return an Integer object specifying this frame's desktop layer
  1004. * @see JLayeredPane
  1005. */
  1006. public int getLayer() {
  1007. return JLayeredPane.getLayer(this);
  1008. }
  1009. /** Convenience method that searchs the anscestor heirarchy for a
  1010. * JDesktop instance. If JInternalFrame finds none, the desktopIcon
  1011. * tree is searched.
  1012. *
  1013. * @return the JDesktopPane this frame belongs to, or null if none
  1014. * is found
  1015. */
  1016. public JDesktopPane getDesktopPane() {
  1017. Container p;
  1018. // Search upward for desktop
  1019. p = getParent();
  1020. while(p != null && !(p instanceof JDesktopPane))
  1021. p = p.getParent();
  1022. if(p == null) {
  1023. // search its icon parent for desktop
  1024. p = getDesktopIcon().getParent();
  1025. while(p != null && !(p instanceof JDesktopPane))
  1026. p = p.getParent();
  1027. }
  1028. return (JDesktopPane)p;
  1029. }
  1030. /**
  1031. * Sets the JDesktopIcon associated with this JInternalFrame.
  1032. *
  1033. * @param d the JDesktopIcon to display on the desktop
  1034. * @see #getDesktopIcon
  1035. * @beaninfo
  1036. * bound: true
  1037. * description: The icon shown when this frame is minimized.
  1038. */
  1039. public void setDesktopIcon(JDesktopIcon d) {
  1040. JDesktopIcon oldValue = getDesktopIcon();
  1041. desktopIcon = d;
  1042. firePropertyChange("desktopIcon", oldValue, d);
  1043. }
  1044. /**
  1045. * Returns the JDesktopIcon used when this JInternalFrame is iconified.
  1046. *
  1047. * @return the JDesktopIcon displayed on the desktop
  1048. * @see #setDesktopIcon
  1049. */
  1050. public JDesktopIcon getDesktopIcon() {
  1051. return desktopIcon;
  1052. }
  1053. /**
  1054. * If the JInternalFrame is not in maximized state, return
  1055. * getBounds(); otherwise, return the bounds that the
  1056. * JInternalFrame would be restored to.
  1057. *
  1058. * @return the bounds of this frame when in the normal state
  1059. * @since 1.3
  1060. */
  1061. public Rectangle getNormalBounds() {
  1062. /* we used to test (!isMaximum) here, but since this
  1063. method is used by the property listener for the
  1064. IS_MAXIMUM_PROPERTY, it ended up getting the wrong
  1065. answer... Since normalBounds get set to null when the
  1066. frame is restored, this should work better */
  1067. if (normalBounds != null) {
  1068. return normalBounds;
  1069. } else {
  1070. return getBounds();
  1071. }
  1072. }
  1073. /**
  1074. * Sets the normal bounds for this frame, the bounds that
  1075. * the frame would be restored to from its maximized state.
  1076. * This method is intended for use only by desktop managers.
  1077. *
  1078. * @param r the bounds that the frame should be restored to
  1079. * @since 1.3
  1080. */
  1081. public void setNormalBounds(Rectangle r) {
  1082. normalBounds = r;
  1083. }
  1084. /**
  1085. * If this JInternalFrame is active, return the child which has focus.
  1086. * Otherwise, return null.
  1087. *<p>
  1088. * At present, this method works only for JComponent
  1089. * children.
  1090. *
  1091. * @return the component with focus, or null if no children have focus
  1092. * assigned to them.
  1093. * @since 1.3
  1094. */
  1095. public Component getFocusOwner() {
  1096. JRootPane r = getRootPane();
  1097. if (r != null) return r.getCurrentFocusOwner();
  1098. else return null;
  1099. }
  1100. /**
  1101. * This method directs the internal frame to restore focus to the
  1102. * last subcomponent that had focus. This is used by the UI when
  1103. * the user selected the frame, e.g., by clicking on the title bar.
  1104. *
  1105. * @since 1.3
  1106. */
  1107. public void restoreSubcomponentFocus() {
  1108. if (getRootPane() != null &&
  1109. getRootPane().getPreviousFocusOwner() != null) {
  1110. getRootPane().getPreviousFocusOwner().requestFocus();
  1111. } else {
  1112. /* make sure this frame ends up with is somewhere, so that
  1113. we don't leave a focused component in another frame while
  1114. this frame is selected. */
  1115. this.getContentPane().requestFocus();
  1116. }
  1117. }
  1118. /*
  1119. * Creates a new EventDispatchThread to dispatch events from. This
  1120. * method returns when stopModal is invoked.
  1121. */
  1122. synchronized void startModal() {
  1123. /* Since all input will be blocked until this dialog is dismissed,
  1124. * make sure its parent containers are visible first (this component
  1125. * is tested below). This is necessary for JApplets, because
  1126. * because an applet normally isn't made visible until after its
  1127. * start() method returns -- if this method is called from start(),
  1128. * the applet will appear to hang while an invisible modal frame
  1129. * waits for input.
  1130. */
  1131. if (isVisible() && !isShowing()) {
  1132. Container parent = this.getParent();
  1133. while (parent != null) {
  1134. if (parent.isVisible() == false) {
  1135. parent.setVisible(true);
  1136. }
  1137. parent = parent.getParent();
  1138. }
  1139. }
  1140. try {
  1141. if (SwingUtilities.isEventDispatchThread()) {
  1142. EventQueue theQueue = getToolkit().getSystemEventQueue();
  1143. while (isVisible()) {
  1144. // This is essentially the body of EventDispatchThread
  1145. AWTEvent event = theQueue.getNextEvent();
  1146. Object src = event.getSource();
  1147. // can't call theQueue.dispatchEvent, so I pasted its body here
  1148. if (event instanceof ActiveEvent) {
  1149. ((ActiveEvent) event).dispatch();
  1150. } else if (src instanceof Component) {
  1151. ((Component) src).dispatchEvent(event);
  1152. } else if (src instanceof MenuComponent) {
  1153. ((MenuComponent) src).dispatchEvent(event);
  1154. } else {
  1155. System.err.println("unable to dispatch event: " + event);
  1156. }
  1157. }
  1158. } else
  1159. while (isVisible())
  1160. wait();
  1161. } catch(InterruptedException e){}
  1162. }
  1163. /*
  1164. * Stops the event dispatching loop created by a previous call to
  1165. * <code>startModal</code>.
  1166. */
  1167. synchronized void stopModal() {
  1168. notifyAll();
  1169. }
  1170. /**
  1171. * Moves and resizes this component. Unlike other components,
  1172. * this implementation also forces re-layout, so that frame
  1173. * decorations such as the title bar are always redisplayed.
  1174. *
  1175. * @param x an int giving the component's new horizontal position
  1176. * measured in pixels from the left of its container
  1177. * @param y an int giving the component's new vertical position,
  1178. * measured in pixels from the bottom of its container
  1179. * @param width an int giving the component's new width in pixels
  1180. * @param height an int giving the component's new height in pixels
  1181. */
  1182. public void reshape(int x, int y, int width, int height) {
  1183. super.reshape(x, y, width, height);
  1184. validate();
  1185. repaint();
  1186. }
  1187. ///////////////////////////
  1188. // Frame/Window equivalents
  1189. ///////////////////////////
  1190. /**
  1191. * Adds the specified internal frame listener to receive internal frame events from
  1192. * this internal frame.
  1193. * @param l the internal frame listener
  1194. */
  1195. public void addInternalFrameListener(InternalFrameListener l) { // remind: sync ??
  1196. listenerList.add(InternalFrameListener.class, l);
  1197. // remind: needed?
  1198. enableEvents(0); // turn on the newEventsOnly flag in Component.
  1199. }
  1200. /**
  1201. * Removes the specified internal frame listener so that it no longer
  1202. * receives internal frame events from this internal frame.
  1203. * @param l the internal frame listener
  1204. */
  1205. public void removeInternalFrameListener(InternalFrameListener l) { // remind: sync??
  1206. listenerList.remove(InternalFrameListener.class, l);
  1207. }
  1208. // remind: name ok? all one method ok? need to be synchronized?
  1209. protected void fireInternalFrameEvent(int id){
  1210. Object[] listeners = listenerList.getListenerList();
  1211. InternalFrameEvent e = null;
  1212. for (int i = listeners.length -2; i >=0; i -= 2){
  1213. if (listeners[i] == InternalFrameListener.class){
  1214. if (e == null){
  1215. e = new InternalFrameEvent(this, id);
  1216. // System.out.println("InternalFrameEvent: " + e.paramString());
  1217. }
  1218. switch(e.getID()) {
  1219. case InternalFrameEvent.INTERNAL_FRAME_OPENED:
  1220. ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e);
  1221. break;
  1222. case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
  1223. ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e);
  1224. break;
  1225. case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
  1226. ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e);
  1227. break;
  1228. case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
  1229. ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e);
  1230. break;
  1231. case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
  1232. ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e);
  1233. break;
  1234. case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
  1235. ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e);
  1236. break;
  1237. case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
  1238. ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e);
  1239. break;
  1240. default:
  1241. break;
  1242. }
  1243. }
  1244. }
  1245. /* we could do it off the event, but at the moment, that's not how
  1246. I'm implementing it */
  1247. // if (id == InternalFrameEvent.INTERNAL_FRAME_CLOSING) {
  1248. // doDefaultCloseAction();
  1249. // }
  1250. }
  1251. public void doDefaultCloseAction() {
  1252. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
  1253. switch(defaultCloseOperation) {
  1254. case DO_NOTHING_ON_CLOSE:
  1255. break;
  1256. case HIDE_ON_CLOSE:
  1257. setVisible(false);
  1258. if (isSelected())
  1259. try {
  1260. setSelected(false);
  1261. } catch (PropertyVetoException pve) {}
  1262. /* should this activate the next frame? that's really
  1263. desktopmanager's policy... */
  1264. break;
  1265. case DISPOSE_ON_CLOSE:
  1266. try {
  1267. fireVetoableChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
  1268. Boolean.TRUE);
  1269. isClosed = true;
  1270. firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
  1271. Boolean.TRUE);
  1272. dispose();
  1273. } catch (PropertyVetoException pve) {}
  1274. break;
  1275. default:
  1276. break;
  1277. }
  1278. }
  1279. /**
  1280. * Sets the operation which will happen by default when
  1281. * the user initiates a "close" on this window.
  1282. * The possible choices are:
  1283. * <p>
  1284. * <ul>
  1285. * <li>DO_NOTHING_ON_CLOSE - do not do anything - require the
  1286. * program to handle the operation in the windowClosing
  1287. * method of a registered InternalFrameListener object.
  1288. * <li>HIDE_ON_CLOSE - automatically hide the window after
  1289. * invoking any registered InternalFrameListener objects
  1290. * <li>DISPOSE_ON_CLOSE - automatically hide and dispose the
  1291. * window after invoking any registered InternalFrameListener objects
  1292. * </ul>
  1293. * <p>
  1294. * The value is set to DISPOSE_ON_CLOSE by default.
  1295. * @see #addInternalFrameListener
  1296. * @see #getDefaultCloseOperation
  1297. */
  1298. public void setDefaultCloseOperation(int operation) {
  1299. this.defaultCloseOperation = operation;
  1300. }
  1301. /**
  1302. * Returns the default operation which occurs when the user
  1303. * initiates a "close" on this window.
  1304. * @see #setDefaultCloseOperation
  1305. */
  1306. public int getDefaultCloseOperation() {
  1307. return defaultCloseOperation;
  1308. }
  1309. /**
  1310. * Causes subcomponents of this JInternalFrame to be laid out at their
  1311. * preferred size.
  1312. * @see java.awt.Window#pack
  1313. */
  1314. public void pack() {
  1315. Container parent = getParent();
  1316. if (parent != null && parent.getPeer() == null) {
  1317. parent.addNotify();
  1318. addNotify();
  1319. }
  1320. setSize(getPreferredSize());
  1321. validate();
  1322. }
  1323. /**
  1324. * Shows this internal frame, and brings it to the front.
  1325. * <p>
  1326. * If this window is not yet visible, <code>show</code>
  1327. * makes it visible. If this window is already visible,
  1328. * then this method brings it to the front.
  1329. * @see java.awt.Window#show
  1330. * @see java.awt.Window#toFront
  1331. * @see java.awt.Component#setVisible
  1332. */
  1333. public void show() {
  1334. Container parent = getParent();
  1335. if (parent != null && parent.getPeer() == null) {
  1336. parent.addNotify();
  1337. addNotify();
  1338. }
  1339. validate();
  1340. // bug 4149505
  1341. if (!opened) {
  1342. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
  1343. opened = true;
  1344. }
  1345. /* icon defualt visibility is false; set it to true so that it shows
  1346. up when user iconifies frame */
  1347. getDesktopIcon().setVisible(true);
  1348. toFront();
  1349. if (!isVisible()) { super.show(); }
  1350. if (isIcon) {
  1351. return;
  1352. }
  1353. if (!isSelected()) {
  1354. try {
  1355. setSelected(true);
  1356. } catch (PropertyVetoException pve) {}
  1357. }
  1358. }
  1359. /**
  1360. * Disposes of this internal frame. If the frame is not already
  1361. * closed, a frame-closed event is posted.
  1362. */
  1363. public void dispose() {
  1364. if (isVisible()) {
  1365. setVisible(false);
  1366. }
  1367. if (isSelected()) {
  1368. try {
  1369. setSelected(false);
  1370. } catch (PropertyVetoException pve) {}
  1371. }
  1372. if (!isClosed) {
  1373. firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE);
  1374. isClosed = true;
  1375. }
  1376. fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
  1377. }
  1378. /**
  1379. * Brings this internal frame to the front.
  1380. * Places this internal frame at the top of the stacking order
  1381. * and makes the corresponding adjustment to other visible windows.
  1382. * @see java.awt.Window#toFront
  1383. * @see #moveToFront
  1384. */
  1385. public void toFront() {
  1386. moveToFront();
  1387. }
  1388. /**
  1389. * Sends this internal frame to the back.
  1390. * Places this internal frame at the bottom of the stacking order
  1391. * and makes the corresponding adjustment to other visible windows.
  1392. * @see java.awt.Window#toBack
  1393. * @see #moveToBack
  1394. */
  1395. public void toBack() {
  1396. moveToBack();
  1397. }
  1398. /**
  1399. * Gets the warning string that is displayed with this window.
  1400. * Since an internal frame is always secure (since it's fully
  1401. * contained within a window which might need a warning string)
  1402. * this method always returns null.
  1403. * @return null
  1404. * @see java.awt.Window#getWarningString
  1405. */
  1406. public final String getWarningString() {
  1407. return null;
  1408. }
  1409. /**
  1410. * See readObject() and writeObject() in JComponent for more
  1411. * information about serialization in Swing.
  1412. */
  1413. private void writeObject(ObjectOutputStream s) throws IOException {
  1414. s.defaultWriteObject();
  1415. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  1416. boolean old = isRootPaneCheckingEnabled();
  1417. try