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 {
  1418. setRootPaneCheckingEnabled(false);
  1419. ui.installUI(this);
  1420. }
  1421. finally {
  1422. setRootPaneCheckingEnabled(old);
  1423. }
  1424. }
  1425. }
  1426. /* Called from the JComponent's EnableSerializationFocusListener to
  1427. * do any Swing-specific pre-serialization configuration.
  1428. */
  1429. void compWriteObjectNotify() {
  1430. // need to disable rootpane checking for InternalFrame: 4172083
  1431. boolean old = isRootPaneCheckingEnabled();
  1432. try {
  1433. setRootPaneCheckingEnabled(false);
  1434. super.compWriteObjectNotify();
  1435. }
  1436. finally {
  1437. setRootPaneCheckingEnabled(old);
  1438. }
  1439. }
  1440. /**
  1441. * Returns a string representation of this JInternalFrame. This method
  1442. * is intended to be used only for debugging purposes, and the
  1443. * content and format of the returned string may vary between
  1444. * implementations. The returned string may be empty but may not
  1445. * be <code>null</code>.
  1446. *
  1447. * @return a string representation of this JInternalFrame.
  1448. */
  1449. protected String paramString() {
  1450. String rootPaneString = (rootPane != null ?
  1451. rootPane.toString() : "");
  1452. String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
  1453. "true" : "false");
  1454. String closableString = (closable ? "true" : "false");
  1455. String isClosedString = (isClosed ? "true" : "false");
  1456. String maximizableString = (maximizable ? "true" : "false");
  1457. String isMaximumString = (isMaximum ? "true" : "false");
  1458. String iconableString = (iconable ? "true" : "false");
  1459. String isIconString = (isIcon ? "true" : "false");
  1460. String resizableString = (resizable ? "true" : "false");
  1461. String isSelectedString = (isSelected ? "true" : "false");
  1462. String frameIconString = (frameIcon != null ?
  1463. frameIcon.toString() : "");
  1464. String titleString = (title != null ?
  1465. title : "");
  1466. String desktopIconString = (desktopIcon != null ?
  1467. desktopIcon.toString() : "");
  1468. String openedString = (opened ? "true" : "false");
  1469. String defaultCloseOperationString;
  1470. if (defaultCloseOperation == HIDE_ON_CLOSE) {
  1471. defaultCloseOperationString = "HIDE_ON_CLOSE";
  1472. } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
  1473. defaultCloseOperationString = "DISPOSE_ON_CLOSE";
  1474. } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
  1475. defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
  1476. } else defaultCloseOperationString = "";
  1477. return super.paramString() +
  1478. ",closable=" + closableString +
  1479. ",defaultCloseOperation=" + defaultCloseOperationString +
  1480. ",desktopIcon=" + desktopIconString +
  1481. ",frameIcon=" + frameIconString +
  1482. ",iconable=" + iconableString +
  1483. ",isClosed=" + isClosedString +
  1484. ",isIcon=" + isIconString +
  1485. ",isMaximum=" + isMaximumString +
  1486. ",isSelected=" + isSelectedString +
  1487. ",maximizable=" + maximizableString +
  1488. ",opened=" + openedString +
  1489. ",resizable=" + resizableString +
  1490. ",rootPane=" + rootPaneString +
  1491. ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString +
  1492. ",title=" + titleString;
  1493. }
  1494. // ======= begin optimized frame dragging defence code ==============
  1495. boolean isDragging = false;
  1496. boolean danger = false;
  1497. protected void paintComponent(Graphics g) {
  1498. if (isDragging) {
  1499. // System.out.println("ouch");
  1500. danger = true;
  1501. }
  1502. super.paintComponent(g);
  1503. }
  1504. // ======= end optimized frame dragging defence code ==============
  1505. /////////////////
  1506. // Accessibility support
  1507. ////////////////
  1508. /**
  1509. * Gets the AccessibleContext associated with this JInternalFrame.
  1510. * For internal frames, the AccessibleContext takes the form of an
  1511. * AccessibleJInternalFrame.
  1512. * A new AccessibleJInternalFrame instance is created if necessary.
  1513. *
  1514. * @return an AccessibleJInternalFrame that serves as the
  1515. * AccessibleContext of this JInternalFrame
  1516. */
  1517. public AccessibleContext getAccessibleContext() {
  1518. if (accessibleContext == null) {
  1519. accessibleContext = new AccessibleJInternalFrame();
  1520. }
  1521. return accessibleContext;
  1522. }
  1523. /**
  1524. * This class implements accessibility support for the
  1525. * <code>JInternalFrame</code> class. It provides an implementation of the
  1526. * Java Accessibility API appropriate to internal frame user-interface
  1527. * elements.
  1528. * <p>
  1529. * <strong>Warning:</strong>
  1530. * Serialized objects of this class will not be compatible with
  1531. * future Swing releases. The current serialization support is appropriate
  1532. * for short term storage or RMI between applications running the same
  1533. * version of Swing. A future release of Swing will provide support for
  1534. * long term persistence.
  1535. */
  1536. protected class AccessibleJInternalFrame extends AccessibleJComponent
  1537. implements AccessibleValue {
  1538. /**
  1539. * Get the accessible name of this object.
  1540. *
  1541. * @return the localized name of the object -- can be null if this
  1542. * object does not have a name
  1543. * @see #setAccessibleName
  1544. */
  1545. public String getAccessibleName() {
  1546. if (accessibleName != null) {
  1547. return accessibleName;
  1548. } else {
  1549. return getTitle();
  1550. }
  1551. }
  1552. /**
  1553. * Get the role of this object.
  1554. *
  1555. * @return an instance of AccessibleRole describing the role of the
  1556. * object
  1557. * @see AccessibleRole
  1558. */
  1559. public AccessibleRole getAccessibleRole() {
  1560. return AccessibleRole.INTERNAL_FRAME;
  1561. }
  1562. /**
  1563. * Get the AccessibleValue associated with this object. In the
  1564. * implementation of the Java Accessibility API for this class,
  1565. * return this object, which is responsible for implementing the
  1566. * AccessibleValue interface on behalf of itself.
  1567. *
  1568. * @return this object
  1569. */
  1570. public AccessibleValue getAccessibleValue() {
  1571. return this;
  1572. }
  1573. //
  1574. // AccessibleValue methods
  1575. //
  1576. /**
  1577. * Get the value of this object as a Number.
  1578. *
  1579. * @return value of the object -- can be null if this object does not
  1580. * have a value
  1581. */
  1582. public Number getCurrentAccessibleValue() {
  1583. return new Integer(getLayer());
  1584. }
  1585. /**
  1586. * Set the value of this object as a Number.
  1587. *
  1588. * @return True if the value was set.
  1589. */
  1590. public boolean setCurrentAccessibleValue(Number n) {
  1591. if (n instanceof Integer) {
  1592. setLayer((Integer) n);
  1593. return true;
  1594. } else {
  1595. return false;
  1596. }
  1597. }
  1598. /**
  1599. * Get the minimum value of this object as a Number.
  1600. *
  1601. * @return Minimum value of the object; null if this object does not
  1602. * have a minimum value
  1603. */
  1604. public Number getMinimumAccessibleValue() {
  1605. return new Integer(Integer.MIN_VALUE);
  1606. }
  1607. /**
  1608. * Get the maximum value of this object as a Number.
  1609. *
  1610. * @return Maximum value of the object; null if this object does not
  1611. * have a maximum value
  1612. */
  1613. public Number getMaximumAccessibleValue() {
  1614. return new Integer(Integer.MAX_VALUE);
  1615. }
  1616. } // AccessibleJInternalFrame
  1617. /**
  1618. * This component represents an iconified version of a JInternalFrame.
  1619. * This API should NOT BE USED by Swing applications, as it will go
  1620. * away in future versions of Swing as its functionality is moved into
  1621. * JInternalFrame. This class is public only so that UI objects can
  1622. * display a desktop icon. If an application wants to display a
  1623. * desktop icon, it should create a JInternalFrame instance and
  1624. * iconify it.
  1625. * <p>
  1626. * <strong>Warning:</strong>
  1627. * Serialized objects of this class will not be compatible with
  1628. * future Swing releases. The current serialization support is appropriate
  1629. * for short term storage or RMI between applications running the same
  1630. * version of Swing. A future release of Swing will provide support for
  1631. * long term persistence.
  1632. *
  1633. * @author David Kloba
  1634. */
  1635. static public class JDesktopIcon extends JComponent implements Accessible
  1636. {
  1637. JInternalFrame internalFrame;
  1638. /** Create an icon for an internal frame
  1639. * @param f the JInternalFrame for which the icon is created
  1640. */
  1641. public JDesktopIcon(JInternalFrame f) {
  1642. setVisible(false);
  1643. setInternalFrame(f);
  1644. updateUI();
  1645. }
  1646. /**
  1647. * Returns the L&F object that renders this component.
  1648. *
  1649. * @return the DesktopIconUI object that renders this component
  1650. */
  1651. public DesktopIconUI getUI() {
  1652. return (DesktopIconUI)ui;
  1653. }
  1654. /**
  1655. * Sets the L&F object that renders this component.
  1656. *
  1657. * @param ui the DesktopIconUI L&F object
  1658. * @see UIDefaults#getUI
  1659. */
  1660. public void setUI(DesktopIconUI ui) {
  1661. super.setUI(ui);
  1662. }
  1663. /**
  1664. * Returns the JInternalFrame that this DesktopIcon is
  1665. * associated with.
  1666. * @return the JInternalFrame this icon is associated with
  1667. */
  1668. public JInternalFrame getInternalFrame() {
  1669. return internalFrame;
  1670. }
  1671. /**
  1672. * Sets the JInternalFrame that this DesktopIcon is
  1673. * associated with.
  1674. * @param f the JInternalFrame this icon is associated with
  1675. */
  1676. public void setInternalFrame(JInternalFrame f) {
  1677. internalFrame = f;
  1678. }
  1679. /** Convience method to ask the icon for the Desktop object
  1680. * it belongs to.
  1681. * @return the JDesktopPane that contains this icon's internal
  1682. * frame, or null if none found
  1683. */
  1684. public JDesktopPane getDesktopPane() {
  1685. if(getInternalFrame() != null)
  1686. return getInternalFrame().getDesktopPane();
  1687. return null;
  1688. }
  1689. /**
  1690. * Notification from the UIManager that the L&F has changed.
  1691. * Replaces the current UI object with the latest version from the
  1692. * UIManager.
  1693. *
  1694. * @see JComponent#updateUI
  1695. */
  1696. public void updateUI() {
  1697. boolean hadUI = (ui != null);
  1698. setUI((DesktopIconUI)UIManager.getUI(this));
  1699. invalidate();
  1700. Dimension r = getPreferredSize();
  1701. setSize(r.width, r.height);
  1702. if (internalFrame != null && internalFrame.getUI() != null) { // don't do this if UI not created yet
  1703. SwingUtilities.updateComponentTreeUI(internalFrame);
  1704. }
  1705. }
  1706. /* This method is called if updateUI was called on the associated
  1707. * JInternalFrame. It's necessary to avoid infinite recursion.
  1708. */
  1709. void updateUIWhenHidden() {
  1710. /* Update this UI and any associated internal frame */
  1711. setUI((DesktopIconUI)UIManager.getUI(this));
  1712. invalidate();
  1713. Component[] children = getComponents();
  1714. if (children != null) {
  1715. for(int i = 0; i < children.length; i++) {
  1716. SwingUtilities.updateComponentTreeUI(children[i]);
  1717. }
  1718. }
  1719. }
  1720. /**
  1721. * Returns the name of the L&F class that renders this component.
  1722. *
  1723. * @return "DesktopIconUI"
  1724. * @see JComponent#getUIClassID
  1725. * @see UIDefaults#getUI
  1726. */
  1727. public String getUIClassID() {
  1728. return "DesktopIconUI";
  1729. }
  1730. /**
  1731. * See <code>readObject</code> and <code>writeObject</code>
  1732. * in <code>JComponent</code> for more
  1733. * information about serialization in Swing.
  1734. */
  1735. private void writeObject(ObjectOutputStream s) throws IOException {
  1736. s.defaultWriteObject();
  1737. if ((ui != null) && (getUIClassID().equals("DesktopIconUI"))) {
  1738. ui.installUI(this);
  1739. }
  1740. }
  1741. /////////////////
  1742. // Accessibility support
  1743. ////////////////
  1744. /**
  1745. * Gets the AccessibleContext associated with this JDesktopIcon.
  1746. * For desktop icons, the AccessibleContext takes the form of an
  1747. * AccessibleJDesktopIcon.
  1748. * A new AccessibleJDesktopIcon instance is created if necessary.
  1749. *
  1750. * @return an AccessibleJDesktopIcon that serves as the
  1751. * AccessibleContext of this JDesktopIcon
  1752. */
  1753. public AccessibleContext getAccessibleContext() {
  1754. if (accessibleContext == null) {
  1755. accessibleContext = new AccessibleJDesktopIcon();
  1756. }
  1757. return accessibleContext;
  1758. }
  1759. /**
  1760. * This class implements accessibility support for the
  1761. * <code>JInternalFrame.JDesktopIcon</code> class. It provides an
  1762. * implementation of the Java Accessibility API appropriate to
  1763. * desktop icon user-interface elements.
  1764. * <p>
  1765. * <strong>Warning:</strong>
  1766. * Serialized objects of this class will not be compatible with
  1767. * future Swing releases. The current serialization support is appropriate
  1768. * for short term storage or RMI between applications running the same
  1769. * version of Swing. A future release of Swing will provide support for
  1770. * long term persistence.
  1771. */
  1772. protected class AccessibleJDesktopIcon extends AccessibleJComponent
  1773. implements AccessibleValue {
  1774. /**
  1775. * Get the role of this object.
  1776. *
  1777. * @return an instance of AccessibleRole describing the role of the
  1778. * object
  1779. * @see AccessibleRole
  1780. */
  1781. public AccessibleRole getAccessibleRole() {
  1782. return AccessibleRole.DESKTOP_ICON;
  1783. }
  1784. /**
  1785. * Get the AccessibleValue associated with this object. In the
  1786. * implementation of the Java Accessibility API for this class,
  1787. * return this object, which is responsible for implementing the
  1788. * AccessibleValue interface on behalf of itself.
  1789. *
  1790. * @return this object
  1791. */
  1792. public AccessibleValue getAccessibleValue() {
  1793. return this;
  1794. }
  1795. //
  1796. // AccessibleValue methods
  1797. //
  1798. /**
  1799. * Get the value of this object as a Number.
  1800. *
  1801. * @return value of the object -- can be null if this object does not
  1802. * have a value
  1803. */
  1804. public Number getCurrentAccessibleValue() {
  1805. AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1806. AccessibleValue v = a.getAccessibleValue();
  1807. if (v != null) {
  1808. return v.getCurrentAccessibleValue();
  1809. } else {
  1810. return null;
  1811. }
  1812. }
  1813. /**
  1814. * Set the value of this object as a Number.
  1815. *
  1816. * @return True if the value was set.
  1817. */
  1818. public boolean setCurrentAccessibleValue(Number n) {
  1819. AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1820. AccessibleValue v = a.getAccessibleValue();
  1821. if (v != null) {
  1822. return v.setCurrentAccessibleValue(n);
  1823. } else {
  1824. return false;
  1825. }
  1826. }
  1827. /**
  1828. * Get the minimum value of this object as a Number.
  1829. *
  1830. * @return Minimum value of the object; null if this object does not
  1831. * have a minimum value
  1832. */
  1833. public Number getMinimumAccessibleValue() {
  1834. AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1835. if (a instanceof AccessibleValue) {
  1836. return ((AccessibleValue)a).getMinimumAccessibleValue();
  1837. } else {
  1838. return null;
  1839. }
  1840. }
  1841. /**
  1842. * Get the maximum value of this object as a Number.
  1843. *
  1844. * @return Maximum value of the object; null if this object does not
  1845. * have a maximum value
  1846. */
  1847. public Number getMaximumAccessibleValue() {
  1848. AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
  1849. if (a instanceof AccessibleValue) {
  1850. return ((AccessibleValue)a).getMaximumAccessibleValue();
  1851. } else {
  1852. return null;
  1853. }
  1854. }
  1855. } // AccessibleJDesktopIcon
  1856. }
  1857. }