1. /*
  2. * @(#)JFrame.java 1.79 00/08/05
  3. *
  4. * Copyright 1997-2000 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.PropertyChangeListener;
  14. import java.util.Locale;
  15. import java.util.Vector;
  16. import java.io.Serializable;
  17. import javax.accessibility.*;
  18. /**
  19. * An extended version of <code>java.awt.Frame</code> that adds support for
  20. * the JFC/Swing component architecture.
  21. * You can find task-oriented documentation about using <code>JFrame</code>
  22. * in <em>The Java Tutorial</em>, in the section
  23. * <a
  24. href="http://java.sun.com/docs/books/tutorial/uiswing/components/frame.html">How to Make Frames</a>.
  25. *
  26. * <p>
  27. * The <code>JFrame</code> class is slightly incompatible with <code>Frame</code>.
  28. * Like all other JFC/Swing top-level containers,
  29. * a <code>JFrame</code> contains a <code>JRootPane</code> as its only child.
  30. * The <b>content pane</b> provided by the root pane should,
  31. * as a rule, contain
  32. * all the non-menu components displayed by the <code>JFrame</code>.
  33. * This is different from the AWT <code>Frame</code> case.
  34. * For example, to add a child to
  35. * an AWT frame you'd write:
  36. * <pre>
  37. * frame.add(child);
  38. * </pre>
  39. * However using <code>JFrame</code> you need to add the child
  40. * to the <code>JFrame's</code> content pane
  41. * instead:
  42. * <pre>
  43. * frame.getContentPane().add(child);
  44. * </pre>
  45. * The same is true for setting layout managers, removing components,
  46. * listing children, and so on. All these methods should normally be sent to
  47. * the content pane instead of the JFrame itself. The content pane will
  48. * always be non-null. Attempting to set it to null will cause the JFrame
  49. * to throw an exception. The default content pane will have a BorderLayout
  50. * manager set on it.
  51. * <p>
  52. * Unlike a <code>Frame</code>, a <code>JFrame</code> has some notion of how to
  53. * respond when the user attempts to close the window. The default behavior
  54. * is to simply hide the JFrame when the user closes the window. To change the
  55. * default behavior, you invoke the method
  56. * {@link #setDefaultCloseOperation}.
  57. * To make the <code>JFrame</code> behave the same as a <code>Frame</code>
  58. * instance, use
  59. * <code>setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE)</code>.
  60. * <p>
  61. * For more information on content panes
  62. * and other features that root panes provide,
  63. * see <a
  64. href="http://java.sun.com/docs/books/tutorial/uiswing/components/toplevel.html">Using Top-Level Containers</a> in <em>The Java Tutorial</em>.
  65. * <p>
  66. * In a multi-screen environment, you can create a <code>JFrame</code>
  67. * on a different screen device. See {@link java.awt.Frame} for more
  68. * information.
  69. * <p>
  70. * For the keyboard keys used by this component in the standard Look and
  71. * Feel (L&F) renditions, see the
  72. * <a href="doc-files/Key-Index.html#JFrame">JFrame</a> key assignments.
  73. * <p>
  74. * <strong>Warning:</strong>
  75. * Serialized objects of this class will not be compatible with
  76. * future Swing releases. The current serialization support is appropriate
  77. * for short term storage or RMI between applications running the same
  78. * version of Swing. A future release of Swing will provide support for
  79. * long term persistence.
  80. *
  81. * @see JRootPane
  82. * @see #setDefaultCloseOperation
  83. * @see java.awt.event.WindowListener#windowClosing
  84. *
  85. * @beaninfo
  86. * attribute: isContainer true
  87. * attribute: containerDelegate getContentPane
  88. * description: A toplevel window which can be minimized to an icon.
  89. *
  90. * @version 1.79 08/05/00
  91. * @author Jeff Dinkins
  92. * @author Georges Saab
  93. * @author David Kloba
  94. */
  95. public class JFrame extends Frame implements WindowConstants, Accessible, RootPaneContainer
  96. {
  97. /**
  98. * The exit application default window close operation. If a window
  99. * has this set as the close operation and is closed in an applet,
  100. * a <code>SecurityException</code> may be thrown.
  101. * It is recommended you only use this in an application.
  102. * <p>
  103. * @since 1.3
  104. */
  105. public static final int EXIT_ON_CLOSE = 3;
  106. private int defaultCloseOperation = HIDE_ON_CLOSE;
  107. /**
  108. * The <code>JRootPane</code> instance that manages the
  109. * <code>contentPane</code>
  110. * and optional <code>menuBar</code> for this frame, as well as the
  111. * <code>glassPane</code>.
  112. *
  113. * @see JRootPane
  114. * @see RootPaneContainer
  115. */
  116. protected JRootPane rootPane;
  117. /**
  118. * If true then calls to <code>add</code> and <code>setLayout</code>
  119. * will cause an exception to be thrown. The default is false.
  120. *
  121. * @see #isRootPaneCheckingEnabled
  122. * @see #setRootPaneCheckingEnabled
  123. */
  124. protected boolean rootPaneCheckingEnabled = false;
  125. /**
  126. * Constructs a new frame that is initially invisible.
  127. *
  128. * @see Component#setSize
  129. * @see Component#setVisible
  130. */
  131. public JFrame() {
  132. super();
  133. frameInit();
  134. }
  135. /**
  136. * Creates a <code>Frame</code> in the specified
  137. * <code>GraphicsConfiguration</code> of
  138. * a screen device and a blank title.
  139. *
  140. * @param gc the <code>GraphicsConfiguration</code> that is used
  141. * to construct the new <code>Frame</code>
  142. * if <code>gc</code> is <code>null</code>, the system
  143. * default <code>GraphicsConfiguration</code> is assumed
  144. * @exception IllegalArgumentException if <code>gc</code> is not from
  145. * a screen device
  146. * @since 1.3
  147. */
  148. public JFrame(GraphicsConfiguration gc) {
  149. super(gc);
  150. frameInit();
  151. }
  152. /**
  153. * Creates a new, initially invisible <code>Frame</code> with the
  154. * specified title.
  155. *
  156. * @param title the title for the frame
  157. * @see Component#setSize
  158. * @see Component#setVisible
  159. */
  160. public JFrame(String title) {
  161. super(title);
  162. frameInit();
  163. }
  164. /**
  165. * Creates a <code>JFrame</code> with the specified title and the
  166. * specified <code>GraphicsConfiguration</code> of a screen device.
  167. *
  168. * @param title the title to be displayed in the
  169. * frame's border. A <code>null</code> value is treated as
  170. * an empty string, "".
  171. * @param gc the <code>GraphicsConfiguration</code> that is used
  172. * to construct the new <code>JFrame</code> with;
  173. * if <code>gc</code> is <code>null</code>, the system
  174. * default <code>GraphicsConfiguration</code> is assumed
  175. * @exception IllegalArgumentException if <code>gc</code> is not from
  176. * a screen device
  177. * @since 1.3
  178. */
  179. public JFrame(String title, GraphicsConfiguration gc) {
  180. super(title, gc);
  181. frameInit();
  182. }
  183. /** Called by the constructors to init the <code>JFrame</code> properly. */
  184. protected void frameInit() {
  185. enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
  186. setRootPane(createRootPane());
  187. setBackground(UIManager.getColor("control"));
  188. setRootPaneCheckingEnabled(true);
  189. }
  190. /**
  191. * Called by the constructor methods to create the default
  192. * <code>rootPane</code>.
  193. */
  194. protected JRootPane createRootPane() {
  195. return new JRootPane();
  196. }
  197. /**
  198. * Processes key events occurring on this component and, if appropriate,
  199. * passes them on to components in the frame which have registered
  200. * interest in them.
  201. *
  202. * @param e the key event
  203. * @see java.awt.Component#processKeyEvent
  204. */
  205. protected void processKeyEvent(KeyEvent e) {
  206. super.processKeyEvent(e);
  207. if(!e.isConsumed()) {
  208. JComponent.processKeyBindingsForAllComponents(e,this,e.getID() == KeyEvent.KEY_PRESSED);
  209. }
  210. }
  211. /**
  212. * Processes window events occurring on this component.
  213. * Hides the window or disposes of it, as specified by the setting
  214. * of the <code>defaultCloseOperation</code> property.
  215. *
  216. * @param e the window event
  217. * @see #setDefaultCloseOperation
  218. * @see java.awt.Window#processWindowEvent
  219. */
  220. protected void processWindowEvent(WindowEvent e) {
  221. super.processWindowEvent(e);
  222. if (e.getID() == WindowEvent.WINDOW_CLOSING) {
  223. switch(defaultCloseOperation) {
  224. case HIDE_ON_CLOSE:
  225. setVisible(false);
  226. break;
  227. case DISPOSE_ON_CLOSE:
  228. setVisible(false);
  229. dispose();
  230. break;
  231. case DO_NOTHING_ON_CLOSE:
  232. default:
  233. break;
  234. case EXIT_ON_CLOSE:
  235. System.exit(0);
  236. break;
  237. }
  238. }
  239. }
  240. // public void setMenuBar(MenuBar menu) {
  241. // throw new IllegalComponentStateException("Please use setJMenuBar() with JFrame.");
  242. // }
  243. /**
  244. * Sets the operation that will happen by default when
  245. * the user initiates a "close" on this frame.
  246. * You must specify one of the following choices:
  247. * <p>
  248. * <ul>
  249. * <li><code>DO_NOTHING_ON_CLOSE</code>
  250. * (defined in <code>WindowConstants</code>):
  251. * Don't do anything; require the
  252. * program to handle the operation in the <code>windowClosing</code>
  253. * method of a registered <code>WindowListener</code> object.
  254. *
  255. * <li><code>HIDE_ON_CLOSE</code>
  256. * (defined in <code>WindowConstants</code>):
  257. * Automatically hide the frame after
  258. * invoking any registered <code>WindowListener</code>
  259. * objects.
  260. *
  261. * <li><code>DISPOSE_ON_CLOSE</code>
  262. * (defined in <code>WindowConstants</code>):
  263. * Automatically hide and dispose the
  264. * frame after invoking any registered <code>WindowListener</code>
  265. * objects.
  266. *
  267. * <li><code>EXIT_ON_CLOSE</code>
  268. * (defined in <code>JFrame</code>):
  269. * Exit the application using the <code>System</code> <code>exit</code> method.
  270. * Use this only in applications.
  271. * </ul>
  272. * <p>
  273. * The value is set to <code>HIDE_ON_CLOSE</code> by default.
  274. * @see #addWindowListener
  275. * @see #getDefaultCloseOperation
  276. * @see WindowConstants
  277. *
  278. * @beaninfo
  279. * preferred: true
  280. * enum: DO_NOTHING_ON_CLOSE WindowConstants.DO_NOTHING_ON_CLOSE
  281. * HIDE_ON_CLOSE WindowConstants.HIDE_ON_CLOSE
  282. * DISPOSE_ON_CLOSE WindowConstants.DISPOSE_ON_CLOSE
  283. * EXIT_ON_CLOSE JFrame.EXIT_ON_CLOSE
  284. * description: The frame's default close operation.
  285. */
  286. public void setDefaultCloseOperation(int operation) {
  287. this.defaultCloseOperation = operation;
  288. }
  289. /**
  290. * Returns the operation that occurs when the user
  291. * initiates a "close" on this frame.
  292. *
  293. * @return an integer indicating the window-close operation
  294. * @see #setDefaultCloseOperation
  295. */
  296. public int getDefaultCloseOperation() {
  297. return defaultCloseOperation;
  298. }
  299. /**
  300. * Just calls <code>paint(g)</code>. This method was overridden to
  301. * prevent an unnecessary call to clear the background.
  302. *
  303. * @param g the Graphics context in which to paint
  304. */
  305. public void update(Graphics g) {
  306. paint(g);
  307. }
  308. /**
  309. * Sets the menubar for this frame.
  310. * @param menubar the menubar being placed in the frame
  311. *
  312. * @see #getJMenuBar
  313. *
  314. * @beaninfo
  315. * hidden: true
  316. * description: The menubar for accessing pulldown menus from this frame.
  317. */
  318. public void setJMenuBar(JMenuBar menubar) {
  319. getRootPane().setMenuBar(menubar);
  320. }
  321. /**
  322. * Returns the menubar set on this frame.
  323. * @return the menubar for this frame
  324. *
  325. * @see #setJMenuBar
  326. */
  327. public JMenuBar getJMenuBar() {
  328. return getRootPane().getMenuBar();
  329. }
  330. /**
  331. * Returns whether calls to <code>add</code> and
  332. * <code>setLayout</code> cause an exception to be thrown.
  333. *
  334. * @return true if <code>add</code> and <code>setLayout</code>
  335. * are checked; false otherwise
  336. *
  337. * @see #addImpl
  338. * @see #setLayout
  339. * @see #setRootPaneCheckingEnabled
  340. */
  341. protected boolean isRootPaneCheckingEnabled() {
  342. return rootPaneCheckingEnabled;
  343. }
  344. /**
  345. * Determines whether calls to <code>add</code> and
  346. * <code>setLayout</code> will cause an exception to be thrown.
  347. *
  348. * @param enabled true if checking is to be
  349. * enabled, which causes the exceptions to be thrown
  350. *
  351. * @see #addImpl
  352. * @see #setLayout
  353. * @see #isRootPaneCheckingEnabled
  354. * @beaninfo
  355. * hidden: true
  356. * description: Whether the add and setLayout methods throw exceptions when invoked.
  357. */
  358. protected void setRootPaneCheckingEnabled(boolean enabled) {
  359. rootPaneCheckingEnabled = enabled;
  360. }
  361. /**
  362. * Creates a runtime exception with a message like:
  363. * <pre>
  364. * "Do not use JFrame.add() use JFrame.getContentPane().add() instead"
  365. * </pre>
  366. *
  367. * @param op a <code>String</code> indicating the attempted operation;
  368. * in the example above, the operation string is "add"
  369. */
  370. private Error createRootPaneException(String op) {
  371. String type = getClass().getName();
  372. return new Error(
  373. "Do not use " + type + "." + op + "() use "
  374. + type + ".getContentPane()." + op + "() instead");
  375. }
  376. /**
  377. * By default, children may not be added directly to this component,
  378. * they must be added to its contentPane instead. For example:
  379. * <pre>
  380. * thisComponent.getContentPane().add(child)
  381. * </pre>
  382. * An attempt to add to directly to this component will cause an
  383. * runtime exception to be thrown. Subclasses can disable this
  384. * behavior.
  385. *
  386. * @param comp the component to be enhanced
  387. * @param constraints the constraints to be respected
  388. * @param index the index
  389. * @exception Error if called with <code>rootPaneChecking</code> true
  390. *
  391. * @see #setRootPaneCheckingEnabled
  392. */
  393. protected void addImpl(Component comp, Object constraints, int index)
  394. {
  395. if(isRootPaneCheckingEnabled()) {
  396. throw createRootPaneException("add");
  397. }
  398. else {
  399. super.addImpl(comp, constraints, index);
  400. }
  401. }
  402. /**
  403. * Removes the specified component from this container.
  404. * @param comp the component to be removed
  405. * @see #add
  406. */
  407. public void remove(Component comp) {
  408. if (comp == rootPane) {
  409. super.remove(comp);
  410. } else {
  411. // Client mistake, but we need to handle it to avoid a
  412. // common object leak in client applications.
  413. getContentPane().remove(comp);
  414. }
  415. }
  416. /**
  417. * By default the layout of this component may not be set,
  418. * the layout of its <code>contentPane</code> should be set instead.
  419. * For example:
  420. * <pre>
  421. * thiComponent.getContentPane().setLayout(new BorderLayout())
  422. * </pre>
  423. * An attempt to set the layout of this component will cause an
  424. * runtime exception to be thrown. Subclasses can disable this
  425. * behavior.
  426. * @param manager the <code>LayoutManager</code>
  427. * @exception Error if called with <code>rootPaneChecking</code> true
  428. *
  429. * @see #setRootPaneCheckingEnabled
  430. */
  431. public void setLayout(LayoutManager manager) {
  432. if(isRootPaneCheckingEnabled()) {
  433. throw createRootPaneException("setLayout");
  434. }
  435. else {
  436. super.setLayout(manager);
  437. }
  438. }
  439. /**
  440. * Returns the <code>rootPane</code> object for this frame.
  441. * @return the <code>rootPane</code> property
  442. *
  443. * @see #setRootPane
  444. * @see RootPaneContainer#getRootPane
  445. */
  446. public JRootPane getRootPane() {
  447. return rootPane;
  448. }
  449. /**
  450. * Sets the <code>rootPane</code> property.
  451. * This method is called by the constructor.
  452. * @param root the <code>rootPane</code> object for this frame
  453. *
  454. * @see #getRootPane
  455. *
  456. * @beaninfo
  457. * hidden: true
  458. * description: the RootPane object for this frame.
  459. */
  460. protected void setRootPane(JRootPane root)
  461. {
  462. if(rootPane != null) {
  463. remove(rootPane);
  464. }
  465. rootPane = root;
  466. if(rootPane != null) {
  467. boolean checkingEnabled = isRootPaneCheckingEnabled();
  468. try {
  469. setRootPaneCheckingEnabled(false);
  470. add(rootPane, BorderLayout.CENTER);
  471. }
  472. finally {
  473. setRootPaneCheckingEnabled(checkingEnabled);
  474. }
  475. }
  476. }
  477. /**
  478. * Returns the <code>contentPane</code> object for this frame.
  479. * @return the <code>contentPane</code> property
  480. *
  481. * @see #setContentPane
  482. * @see RootPaneContainer#getContentPane
  483. */
  484. public Container getContentPane() {
  485. return getRootPane().getContentPane();
  486. }
  487. /**
  488. * Sets the <code>contentPane</code> property.
  489. * This method is called by the constructor.
  490. *
  491. * @param contentPane the <code>contentPane</code> object for this frame
  492. *
  493. * @exception java.awt.IllegalComponentStateException (a runtime
  494. * exception) if the content pane parameter is <code>null</code>
  495. * @see #getContentPane
  496. * @see RootPaneContainer#setContentPane
  497. *
  498. * @beaninfo
  499. * hidden: true
  500. * description: The client area of the frame where child
  501. * components are normally inserted.
  502. */
  503. public void setContentPane(Container contentPane) {
  504. getRootPane().setContentPane(contentPane);
  505. }
  506. /**
  507. * Returns the <code>layeredPane</code> object for this frame.
  508. * @return the <code>layeredPane</code> property
  509. *
  510. * @see #setLayeredPane
  511. * @see RootPaneContainer#getLayeredPane
  512. */
  513. public JLayeredPane getLayeredPane() {
  514. return getRootPane().getLayeredPane();
  515. }
  516. /**
  517. * Sets the <code>layeredPane</code> property.
  518. * This method is called by the constructor.
  519. * @param layeredPane the <code>layeredPane</code> object for this frame
  520. *
  521. * @exception java.awt.IllegalComponentStateException (a runtime
  522. * exception) if the layered pane parameter is <code>null</code>
  523. * @see #getLayeredPane
  524. * @see RootPaneContainer#setLayeredPane
  525. *
  526. * @beaninfo
  527. * hidden: true
  528. * description: The pane that holds the various frame layers.
  529. */
  530. public void setLayeredPane(JLayeredPane layeredPane) {
  531. getRootPane().setLayeredPane(layeredPane);
  532. }
  533. /**
  534. * Returns the <code>glassPane</code> object for this frame.
  535. * @return the <code>glassPane</code> property
  536. *
  537. * @see #setGlassPane
  538. * @see RootPaneContainer#getGlassPane
  539. */
  540. public Component getGlassPane() {
  541. return getRootPane().getGlassPane();
  542. }
  543. /**
  544. * Sets the <code>glassPane</code> property.
  545. * This method is called by the constructor.
  546. * @param glassPane the <code>glassPane</code> object for this frame
  547. *
  548. * @see #getGlassPane
  549. * @see RootPaneContainer#setGlassPane
  550. *
  551. * @beaninfo
  552. * hidden: true
  553. * description: A transparent pane used for menu rendering.
  554. */
  555. public void setGlassPane(Component glassPane) {
  556. getRootPane().setGlassPane(glassPane);
  557. }
  558. /**
  559. * Returns a string representation of this <code>JFrame</code>.
  560. * This method
  561. * is intended to be used only for debugging purposes, and the
  562. * content and format of the returned string may vary between
  563. * implementations. The returned string may be empty but may not
  564. * be <code>null</code>.
  565. *
  566. * @return a string representation of this <code>JFrame</code>
  567. */
  568. protected String paramString() {
  569. String defaultCloseOperationString;
  570. if (defaultCloseOperation == HIDE_ON_CLOSE) {
  571. defaultCloseOperationString = "HIDE_ON_CLOSE";
  572. } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
  573. defaultCloseOperationString = "DISPOSE_ON_CLOSE";
  574. } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
  575. defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
  576. } else if (defaultCloseOperation == 3) {
  577. defaultCloseOperationString = "EXIT_ON_CLOSE";
  578. } else defaultCloseOperationString = "";
  579. String rootPaneString = (rootPane != null ?
  580. rootPane.toString() : "");
  581. String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
  582. "true" : "false");
  583. return super.paramString() +
  584. ",defaultCloseOperation=" + defaultCloseOperationString +
  585. ",rootPane=" + rootPaneString +
  586. ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString;
  587. }
  588. /////////////////
  589. // Accessibility support
  590. ////////////////
  591. /** The accessible context property. */
  592. protected AccessibleContext accessibleContext = null;
  593. /**
  594. * Gets the AccessibleContext associated with this JFrame.
  595. * For JFrames, the AccessibleContext takes the form of an
  596. * AccessibleJFrame.
  597. * A new AccessibleJFrame instance is created if necessary.
  598. *
  599. * @return an AccessibleJFrame that serves as the
  600. * AccessibleContext of this JFrame
  601. */
  602. public AccessibleContext getAccessibleContext() {
  603. if (accessibleContext == null) {
  604. accessibleContext = new AccessibleJFrame();
  605. }
  606. return accessibleContext;
  607. }
  608. /**
  609. * This class implements accessibility support for the
  610. * <code>JFrame</code> class. It provides an implementation of the
  611. * Java Accessibility API appropriate to frame user-interface
  612. * elements.
  613. */
  614. protected class AccessibleJFrame extends AccessibleAWTFrame {
  615. // AccessibleContext methods
  616. /**
  617. * Get the accessible name of this object.
  618. *
  619. * @return the localized name of the object -- can be null if this
  620. * object does not have a name
  621. */
  622. public String getAccessibleName() {
  623. if (accessibleName != null) {
  624. return accessibleName;
  625. } else {
  626. if (getTitle() == null) {
  627. return super.getAccessibleName();
  628. } else {
  629. return getTitle();
  630. }
  631. }
  632. }
  633. /**
  634. * Get the state of this object.
  635. *
  636. * @return an instance of AccessibleStateSet containing the current
  637. * state set of the object
  638. * @see AccessibleState
  639. */
  640. public AccessibleStateSet getAccessibleStateSet() {
  641. AccessibleStateSet states = super.getAccessibleStateSet();
  642. if (isResizable()) {
  643. states.add(AccessibleState.RESIZABLE);
  644. }
  645. if (getFocusOwner() != null) {
  646. states.add(AccessibleState.ACTIVE);
  647. }
  648. // FIXME: [[[WDW - should also return ICONIFIED and ICONIFIABLE
  649. // if we can ever figure these out]]]
  650. return states;
  651. }
  652. } // inner class AccessibleJFrame
  653. }