1. /*
  2. * @(#)JRootPane.java 1.83 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import javax.accessibility.*;
  12. import javax.swing.plaf.RootPaneUI;
  13. import java.util.Vector;
  14. import java.io.Serializable;
  15. import javax.swing.border.*;
  16. /**
  17. * A lightweight container used behind the scenes by
  18. * <code>JFrame</code>, <code>JDialog</code>, <code>JWindow</code>,
  19. * <code>JApplet</code>, and <code>JInternalFrame</code>.
  20. * For task-oriented information on functionality provided by root panes
  21. * see <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html">How to Use Root Panes</a>,
  22. * a section in <em>The Java Tutorial</em>.
  23. *
  24. * <p>
  25. * The following image shows the relationships between
  26. * the classes that use root panes.
  27. * <p align=center><img src="doc-files/JRootPane-1.gif"
  28. * alt="The following text describes this graphic."
  29. * HEIGHT=484 WIDTH=629></p>
  30. * The "heavyweight" components (those that delegate to a peer, or native
  31. * component on the host system) are shown with a darker, heavier box. The four
  32. * heavyweight JFC/Swing containers (<code>JFrame</code>, <code>JDialog</code>,
  33. * <code>JWindow</code>, and <code>JApplet</code>) are
  34. * shown in relation to the AWT classes they extend.
  35. * These four components are the
  36. * only heavyweight containers in the Swing library. The lightweight container
  37. * <code>JInternalPane</code> is also shown.
  38. * All five of these JFC/Swing containers implement the
  39. * <code>RootPaneContainer</code> interface,
  40. * and they all delegate their operations to a
  41. * <code>JRootPane</code> (shown with a little "handle" on top).
  42. * <blockquote>
  43. * <b>Note:</b> The <code>JComponent</code> method <code>getRootPane</code>
  44. * can be used to obtain the <code>JRootPane</code> that contains
  45. * a given component.
  46. * </blockquote>
  47. * <table align="right" border="0" summary="layout">
  48. * <tr>
  49. * <td align="center">
  50. * <img src="doc-files/JRootPane-2.gif"
  51. * alt="The following text describes this graphic." HEIGHT=386 WIDTH=349>
  52. * </td>
  53. * </tr>
  54. * </table>
  55. * The diagram at right shows the structure of a <code>JRootPane</code>.
  56. * A <code>JRootpane</code> is made up of a <code>glassPane</code>,
  57. * an optional <code>menuBar</code>, and a <code>contentPane</code>.
  58. * (The <code>JLayeredPane</code> manages the <code>menuBar</code>
  59. * and the <code>contentPane</code>.)
  60. * The <code>glassPane</code> sits over the top of everything,
  61. * where it is in a position to intercept mouse movements.
  62. * Since the <code>glassPane</code> (like the <code>contentPane</code>)
  63. * can be an arbitrary component, it is also possible to set up the
  64. * <code>glassPane</code> for drawing. Lines and images on the
  65. * <code>glassPane</code> can then range
  66. * over the frames underneath without being limited by their boundaries.
  67. * <p>
  68. * Although the <code>menuBar</code> component is optional,
  69. * the <code>layeredPane</code>, <code>contentPane</code>,
  70. * and <code>glassPane</code> always exist.
  71. * Attempting to set them to <code>null</code> generates an exception.
  72. * <p>
  73. * To add components to the <code>JRootPane</code> (other than the
  74. * optional menu bar), you add the object to the <code>contentPane</code>
  75. * of the <code>JRootPane</code>, like this:
  76. * <pre>
  77. * rootPane.getContentPane().add(child);
  78. * </pre>
  79. * The same principle holds true for setting layout managers, removing
  80. * components, listing children, etc. All these methods are invoked on
  81. * the <code>contentPane</code> instead of on the <code>JRootPane</code>.
  82. * <blockquote>
  83. * <b>Note:</b> The default layout manager for the <code>contentPane</code> is
  84. * a <code>BorderLayout</code> manager. However, the <code>JRootPane</code>
  85. * uses a custom <code>LayoutManager</code>.
  86. * So, when you want to change the layout manager for the components you added
  87. * to a <code>JRootPane</code>, be sure to use code like this:
  88. * <pre>
  89. * rootPane.getContentPane().setLayout(new BoxLayout());
  90. * </pre></blockquote>
  91. * If a <code>JMenuBar</code> component is set on the <code>JRootPane</code>,
  92. * it is positioned along the upper edge of the frame.
  93. * The <code>contentPane</code> is adjusted in location and size to
  94. * fill the remaining area.
  95. * (The <code>JMenuBar</code> and the <code>contentPane</code> are added to the
  96. * <code>layeredPane</code> component at the
  97. * <code>JLayeredPane.FRAME_CONTENT_LAYER</code> layer.)
  98. * <p>
  99. * The <code>layeredPane</code> is the parent of all children in the
  100. * <code>JRootPane</code> -- both as the direct parent of the menu and
  101. * the grandparent of all components added to the <code>contentPane</code>.
  102. * It is an instance of <code>JLayeredPane</code>,
  103. * which provides the ability to add components at several layers.
  104. * This capability is very useful when working with menu popups,
  105. * dialog boxes, and dragging -- situations in which you need to place
  106. * a component on top of all other components in the pane.
  107. * <p>
  108. * The <code>glassPane</code> sits on top of all other components in the
  109. * <code>JRootPane</code>.
  110. * That provides a convenient place to draw above all other components,
  111. * and makes it possible to intercept mouse events,
  112. * which is useful both for dragging and for drawing.
  113. * Developers can use <code>setVisible</code> on the <code>glassPane</code>
  114. * to control when the <code>glassPane</code> displays over the other children.
  115. * By default the <code>glassPane</code> is not visible.
  116. * <p>
  117. * The custom <code>LayoutManager</code> used by <code>JRootPane</code>
  118. * ensures that:
  119. * <OL>
  120. * <LI>The <code>glassPane</code> fills the entire viewable
  121. * area of the <code>JRootPane</code> (bounds - insets).
  122. * <LI>The <code>layeredPane</code> fills the entire viewable area of the
  123. * <code>JRootPane</code>. (bounds - insets)
  124. * <LI>The <code>menuBar</code> is positioned at the upper edge of the
  125. * <code>layeredPane</code>.
  126. * <LI>The <code>contentPane</code> fills the entire viewable area,
  127. * minus the <code>menuBar</code>, if present.
  128. * </OL>
  129. * Any other views in the <code>JRootPane</code> view hierarchy are ignored.
  130. * <p>
  131. * If you replace the <code>LayoutManager</code> of the <code>JRootPane</code>,
  132. * you are responsible for managing all of these views.
  133. * So ordinarily you will want to be sure that you
  134. * change the layout manager for the <code>contentPane</code> rather than
  135. * for the <code>JRootPane</code> itself!
  136. * <p>
  137. * The painting architecture of Swing requires an opaque
  138. * <code>JComponent</code>
  139. * to exist in the containment hieararchy above all other components. This is
  140. * typically provided by way of the content pane. If you replace the content
  141. * pane, it is recommended that you make the content pane opaque
  142. * by way of <code>setOpaque(true)</code>. Additionally, if the content pane
  143. * overrides <code>paintComponent</code>, it
  144. * will need to completely fill in the background in an opaque color in
  145. * <code>paintComponent</code>.
  146. * <p>
  147. * <strong>Warning:</strong>
  148. * Serialized objects of this class will not be compatible with
  149. * future Swing releases. The current serialization support is
  150. * appropriate for short term storage or RMI between applications running
  151. * the same version of Swing. As of 1.4, support for long term storage
  152. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  153. * has been added to the <code>java.beans</code> package.
  154. * Please see {@link java.beans.XMLEncoder}.
  155. *
  156. * @see JLayeredPane
  157. * @see JMenuBar
  158. * @see JWindow
  159. * @see JFrame
  160. * @see JDialog
  161. * @see JApplet
  162. * @see JInternalFrame
  163. * @see JComponent
  164. * @see BoxLayout
  165. *
  166. * @see <a href="http://java.sun.com/products/jfc/swingdoc-archive/mixing.html">
  167. * Mixing Heavy and Light Components</a>
  168. *
  169. * @version 1.83 01/23/03
  170. * @author David Kloba
  171. */
  172. /// PENDING(klobad) Who should be opaque in this component?
  173. public class JRootPane extends JComponent implements Accessible {
  174. private static final String uiClassID = "RootPaneUI";
  175. /**
  176. * Constant used for the windowDecorationStyle property. Indicates that
  177. * the <code>JRootPane</code> should not provide any sort of
  178. * Window decorations.
  179. *
  180. * @since 1.4
  181. */
  182. public static final int NONE = 0;
  183. /**
  184. * Constant used for the windowDecorationStyle property. Indicates that
  185. * the <code>JRootPane</code> should provide decorations appropriate for
  186. * a Frame.
  187. *
  188. * @since 1.4
  189. */
  190. public static final int FRAME = 1;
  191. /**
  192. * Constant used for the windowDecorationStyle property. Indicates that
  193. * the <code>JRootPane</code> should provide decorations appropriate for
  194. * a Dialog.
  195. *
  196. * @since 1.4
  197. */
  198. public static final int PLAIN_DIALOG = 2;
  199. /**
  200. * Constant used for the windowDecorationStyle property. Indicates that
  201. * the <code>JRootPane</code> should provide decorations appropriate for
  202. * a Dialog used to display an informational message.
  203. *
  204. * @since 1.4
  205. */
  206. public static final int INFORMATION_DIALOG = 3;
  207. /**
  208. * Constant used for the windowDecorationStyle property. Indicates that
  209. * the <code>JRootPane</code> should provide decorations appropriate for
  210. * a Dialog used to display an error message.
  211. *
  212. * @since 1.4
  213. */
  214. public static final int ERROR_DIALOG = 4;
  215. /**
  216. * Constant used for the windowDecorationStyle property. Indicates that
  217. * the <code>JRootPane</code> should provide decorations appropriate for
  218. * a Dialog used to display a <code>JColorChooser</code>.
  219. *
  220. * @since 1.4
  221. */
  222. public static final int COLOR_CHOOSER_DIALOG = 5;
  223. /**
  224. * Constant used for the windowDecorationStyle property. Indicates that
  225. * the <code>JRootPane</code> should provide decorations appropriate for
  226. * a Dialog used to display a <code>JFileChooser</code>.
  227. *
  228. * @since 1.4
  229. */
  230. public static final int FILE_CHOOSER_DIALOG = 6;
  231. /**
  232. * Constant used for the windowDecorationStyle property. Indicates that
  233. * the <code>JRootPane</code> should provide decorations appropriate for
  234. * a Dialog used to present a question to the user.
  235. *
  236. * @since 1.4
  237. */
  238. public static final int QUESTION_DIALOG = 7;
  239. /**
  240. * Constant used for the windowDecorationStyle property. Indicates that
  241. * the <code>JRootPane</code> should provide decorations appropriate for
  242. * a Dialog used to display a warning message.
  243. *
  244. * @since 1.4
  245. */
  246. public static final int WARNING_DIALOG = 8;
  247. private Component mostRecentFocusOwner;
  248. private int windowDecorationStyle;
  249. /** The menu bar. */
  250. protected JMenuBar menuBar;
  251. /** The content pane. */
  252. protected Container contentPane;
  253. /** The layered pane that manages the menu bar and content pane. */
  254. protected JLayeredPane layeredPane;
  255. /**
  256. * The glass pane that overlays the menu bar and content pane,
  257. * so it can intercept mouse movements and such.
  258. */
  259. protected Component glassPane;
  260. /**
  261. * The button that gets activated when the pane has the focus and
  262. * a UI-specific action like pressing the <b>Enter</b> key occurs.
  263. */
  264. protected JButton defaultButton;
  265. /**
  266. * As of Java 2 platform v1.3 this unusable field is no longer used.
  267. * To override the default button you should replace the <code>Action</code>
  268. * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
  269. * the key bindings specification for further details.
  270. *
  271. * @deprecated As of Java 2 platform v1.3.
  272. * @see #defaultButton
  273. */
  274. protected DefaultAction defaultPressAction;
  275. /**
  276. * As of Java 2 platform v1.3 this unusable field is no longer used.
  277. * To override the default button you should replace the <code>Action</code>
  278. * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
  279. * the key bindings specification for further details.
  280. *
  281. * @deprecated As of Java 2 platform v1.3.
  282. * @see #defaultButton
  283. */
  284. protected DefaultAction defaultReleaseAction;
  285. /**
  286. * Creates a <code>JRootPane</code>, setting up its
  287. * <code>glassPane</code>, <code>layeredPane</code>,
  288. * and <code>contentPane</code>.
  289. */
  290. public JRootPane() {
  291. setGlassPane(createGlassPane());
  292. setLayeredPane(createLayeredPane());
  293. setContentPane(createContentPane());
  294. setLayout(createRootLayout());
  295. setDoubleBuffered(true);
  296. updateUI();
  297. }
  298. /**
  299. * Returns a constant identifying the type of Window decorations the
  300. * <code>JRootPane</code> is providing.
  301. *
  302. * @return One of <code>NONE</code>, <code>FRAME</code>,
  303. * <code>PLAIN_DIALOG</code>, <code>INFORMATION_DIALOG</code>,
  304. * <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>,
  305. * <code>FILE_CHOOSER_DIALOG</code>, <code>QUESTION_DIALOG</code> or
  306. * <code>WARNING_DIALOG</code>.
  307. * @see #setWindowDecorationStyle
  308. * @since 1.4
  309. */
  310. public int getWindowDecorationStyle() {
  311. return windowDecorationStyle;
  312. }
  313. /**
  314. * Sets the type of Window decorations (such as borders, widgets for
  315. * closing a Window, title ...) the <code>JRootPane</code> should
  316. * provide. The default is to provide no Window decorations
  317. * (<code>NONE</code>).
  318. * <p>
  319. * This is only a hint, and some look and feels may not support
  320. * this.
  321. * This is a bound property.
  322. *
  323. * @param windowDecorationStyle Constant identifying Window decorations
  324. * to provide.
  325. * @see JDialog#setDefaultLookAndFeelDecorated
  326. * @see JFrame#setDefaultLookAndFeelDecorated
  327. * @see LookAndFeel#getSupportsWindowDecorations
  328. * @throws IllegalArgumentException if <code>style</code> is
  329. * not one of: <code>NONE</code>, <code>FRAME</code>,
  330. * <code>PLAIN_DIALOG</code>, <code>INFORMATION_DIALOG</code>,
  331. * <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>,
  332. * <code>FILE_CHOOSER_DIALOG</code>, <code>QUESTION_DIALOG</code>, or
  333. * <code>WARNING_DIALOG</code>.
  334. * @since 1.4
  335. * @beaninfo
  336. * bound: true
  337. * enum: NONE JRootPane.NONE
  338. * FRAME JRootPane.FRAME
  339. * PLAIN_DIALOG JRootPane.PLAIN_DIALOG
  340. * INFORMATION_DIALOG JRootPane.INFORMATION_DIALOG
  341. * ERROR_DIALOG JRootPane.ERROR_DIALOG
  342. * COLOR_CHOOSER_DIALOG JRootPane.COLOR_CHOOSER_DIALOG
  343. * FILE_CHOOSER_DIALOG JRootPane.FILE_CHOOSER_DIALOG
  344. * QUESTION_DIALOG JRootPane.QUESTION_DIALOG
  345. * WARNING_DIALOG JRootPane.WARNING_DIALOG
  346. * expert: true
  347. * attribute: visualUpdate true
  348. * description: Identifies the type of Window decorations to provide
  349. */
  350. public void setWindowDecorationStyle(int windowDecorationStyle) {
  351. if (windowDecorationStyle < 0 ||
  352. windowDecorationStyle > WARNING_DIALOG) {
  353. throw new IllegalArgumentException("Invalid decoration style");
  354. }
  355. int oldWindowDecorationStyle = getWindowDecorationStyle();
  356. this.windowDecorationStyle = windowDecorationStyle;
  357. firePropertyChange("windowDecorationStyle",
  358. oldWindowDecorationStyle,
  359. windowDecorationStyle);
  360. }
  361. /**
  362. * Returns the L&F object that renders this component.
  363. *
  364. * @return <code>LabelUI</code> object
  365. * @since 1.3
  366. */
  367. public RootPaneUI getUI() {
  368. return (RootPaneUI)ui;
  369. }
  370. /**
  371. * Sets the L&F object that renders this component.
  372. *
  373. * @param ui the <code>LabelUI</code> L&F object
  374. * @see UIDefaults#getUI
  375. * @beaninfo
  376. * bound: true
  377. * hidden: true
  378. * expert: true
  379. * attribute: visualUpdate true
  380. * description: The UI object that implements the Component's LookAndFeel.
  381. * @since 1.3
  382. */
  383. public void setUI(RootPaneUI ui) {
  384. super.setUI(ui);
  385. }
  386. /**
  387. * Resets the UI property to a value from the current look and feel.
  388. *
  389. * @see JComponent#updateUI
  390. */
  391. public void updateUI() {
  392. setUI((RootPaneUI)UIManager.getUI(this));
  393. }
  394. /**
  395. * Returns a string that specifies the name of the L&F class
  396. * that renders this component.
  397. *
  398. * @return the string "RootPaneUI"
  399. *
  400. * @see JComponent#getUIClassID
  401. * @see UIDefaults#getUI
  402. */
  403. public String getUIClassID() {
  404. return uiClassID;
  405. }
  406. /**
  407. * Called by the constructor methods to create the default
  408. * <code>layeredPane</code>.
  409. * Bt default it creates a new <code>JLayeredPane</code>.
  410. * @return the default <code>layeredPane</code>
  411. */
  412. protected JLayeredPane createLayeredPane() {
  413. JLayeredPane p = new JLayeredPane();
  414. p.setName(this.getName()+".layeredPane");
  415. return p;
  416. }
  417. /**
  418. * Called by the constructor methods to create the default
  419. * <code>contentPane</code>.
  420. * By default this method creates a new <code>JComponent</code> add sets a
  421. * <code>BorderLayout</code> as its <code>LayoutManager</code>.
  422. * @return the default <code>contentPane</code>
  423. */
  424. protected Container createContentPane() {
  425. JComponent c = new JPanel();
  426. c.setName(this.getName()+".contentPane");
  427. c.setLayout(new BorderLayout() {
  428. /* This BorderLayout subclass maps a null constraint to CENTER.
  429. * Although the reference BorderLayout also does this, some VMs
  430. * throw an IllegalArgumentException.
  431. */
  432. public void addLayoutComponent(Component comp, Object constraints) {
  433. if (constraints == null) {
  434. constraints = BorderLayout.CENTER;
  435. }
  436. super.addLayoutComponent(comp, constraints);
  437. }
  438. });
  439. return c;
  440. }
  441. /**
  442. * Called by the constructor methods to create the default
  443. * <code>glassPane</code>.
  444. * By default this method creates a new <code>JComponent</code>
  445. * with visibility set to false.
  446. * @return the default <code>glassPane</code>
  447. */
  448. protected Component createGlassPane() {
  449. JComponent c = new JPanel();
  450. c.setName(this.getName()+".glassPane");
  451. c.setVisible(false);
  452. ((JPanel)c).setOpaque(false);
  453. return c;
  454. }
  455. /**
  456. * Called by the constructor methods to create the default
  457. * <code>layoutManager</code>.
  458. * @return the default <code>layoutManager</code>.
  459. */
  460. protected LayoutManager createRootLayout() {
  461. return new RootLayout();
  462. }
  463. /**
  464. * Adds or changes the menu bar used in the layered pane.
  465. * @param menu the <code>JMenuBar</code> to add
  466. */
  467. public void setJMenuBar(JMenuBar menu) {
  468. if(menuBar != null && menuBar.getParent() == layeredPane)
  469. layeredPane.remove(menuBar);
  470. menuBar = menu;
  471. if(menuBar != null)
  472. layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER);
  473. }
  474. /**
  475. * Specifies the menu bar value.
  476. * @deprecated As of Swing version 1.0.3
  477. * replaced by <code>setJMenuBar(JMenuBar menu)</code>.
  478. * @param menu the <code>JMenuBar</code> to add.
  479. */
  480. public void setMenuBar(JMenuBar menu){
  481. if(menuBar != null && menuBar.getParent() == layeredPane)
  482. layeredPane.remove(menuBar);
  483. menuBar = menu;
  484. if(menuBar != null)
  485. layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER);
  486. }
  487. /**
  488. * Returns the menu bar from the layered pane.
  489. * @return the <code>JMenuBar</code> used in the pane
  490. */
  491. public JMenuBar getJMenuBar() { return menuBar; }
  492. /**
  493. * Returns the menu bar value.
  494. * @deprecated As of Swing version 1.0.3
  495. * replaced by <code>getJMenubar()</code>.
  496. * @return the <code>JMenuBar</code> used in the pane
  497. */
  498. public JMenuBar getMenuBar() { return menuBar; }
  499. /**
  500. * Sets the content pane -- the container that holds the components
  501. * parented by the root pane.
  502. * <p>
  503. * Swing's painting architecture requires an opaque <code>JComponent</code>
  504. * in the containment hiearchy. This is typically provided by the
  505. * content pane. If you replace the content pane it is recommended you
  506. * replace it with an opaque <code>JComponent</code>.
  507. *
  508. * @param content the <code>Container</code> to use for component-contents
  509. * @exception java.awt.IllegalComponentStateException (a runtime
  510. * exception) if the content pane parameter is <code>null</code>
  511. */
  512. public void setContentPane(Container content) {
  513. if(content == null)
  514. throw new IllegalComponentStateException("contentPane cannot be set to null.");
  515. if(contentPane != null && contentPane.getParent() == layeredPane)
  516. layeredPane.remove(contentPane);
  517. contentPane = content;
  518. layeredPane.add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER);
  519. }
  520. /**
  521. * Returns the content pane -- the container that holds the components
  522. * parented by the root pane.
  523. *
  524. * @return the <code>Container</code> that holds the component-contents
  525. */
  526. public Container getContentPane() { return contentPane; }
  527. // PENDING(klobad) Should this reparent the contentPane and MenuBar?
  528. /**
  529. * Sets the layered pane for the root pane. The layered pane
  530. * typically holds a content pane and an optional <code>JMenuBar</code>.
  531. *
  532. * @param layered the <code>JLayeredPane</code> to use
  533. * @exception java.awt.IllegalComponentStateException (a runtime
  534. * exception) if the layered pane parameter is <code>null</code>
  535. */
  536. public void setLayeredPane(JLayeredPane layered) {
  537. if(layered == null)
  538. throw new IllegalComponentStateException("layeredPane cannot be set to null.");
  539. if(layeredPane != null && layeredPane.getParent() == this)
  540. this.remove(layeredPane);
  541. layeredPane = layered;
  542. this.add(layeredPane, -1);
  543. }
  544. /**
  545. * Gets the layered pane used by the root pane. The layered pane
  546. * typically holds a content pane and an optional <code>JMenuBar</code>.
  547. *
  548. * @return the <code>JLayeredPane</code> currently in use
  549. */
  550. public JLayeredPane getLayeredPane() { return layeredPane; }
  551. /**
  552. * Sets a specified <code>Component</code> to be the glass pane for this
  553. * root pane. The glass pane should normally be a lightweight,
  554. * transparent component, because it will be made visible when
  555. * ever the root pane needs to grab input events. For example,
  556. * only one <code>JInternalFrame</code> is ever active when using a
  557. * DefaultDesktop, and any inactive <code>JInternalFrame</code>s'
  558. * glass panes are made visible so that clicking anywhere within
  559. * an inactive <code>JInternalFrame</code> can activate it.
  560. *
  561. * @param glass the <code>Component</code> to use as the glass pane
  562. * for this <code>JRootPane</code>
  563. * @exception NullPointerException if the <code>glass</code> parameter is
  564. * <code>null</code>
  565. */
  566. public void setGlassPane(Component glass) {
  567. if (glass == null) {
  568. throw new NullPointerException("glassPane cannot be set to null.");
  569. }
  570. boolean visible = false;
  571. if (glassPane != null && glassPane.getParent() == this) {
  572. this.remove(glassPane);
  573. visible = glassPane.isVisible();
  574. }
  575. glass.setVisible(visible);
  576. glassPane = glass;
  577. this.add(glassPane, 0);
  578. if (visible) {
  579. repaint();
  580. }
  581. }
  582. /**
  583. * Returns the current glass pane for this <code>JRootPane</code>.
  584. * @return the current glass pane
  585. * @see #setGlassPane
  586. */
  587. public Component getGlassPane() {
  588. return glassPane;
  589. }
  590. /**
  591. * If a descendant of this <code>JRootPane</code> calls
  592. * <code>revalidate</code>, validate from here on down.
  593. *<p>
  594. * Deferred requests to layout a component and its descendents again.
  595. * For example, calls to <code>revalidate</code>, are pushed upwards to
  596. * either a <code>JRootPane</code> or a <code>JScrollPane</code>
  597. * because both classes override <code>isValidateRoot</code> to return true.
  598. *
  599. * @see JComponent#isValidateRoot
  600. * @return true
  601. */
  602. public boolean isValidateRoot() {
  603. return true;
  604. }
  605. /**
  606. * The <code>glassPane</code> and <code>contentPane</code>
  607. * have the same bounds, which means <code>JRootPane</code>
  608. * does not tiles its children and this should return false.
  609. * On the other hand, the <code>glassPane</code>
  610. * is normally not visible, and so this can return true if the
  611. * <code>glassPane</code> isn't visible. Therefore, the
  612. * return value here depends upon the visiblity of the
  613. * <code>glassPane</code>.
  614. *
  615. * @return true if this component's children don't overlap
  616. */
  617. public boolean isOptimizedDrawingEnabled() {
  618. return !glassPane.isVisible();
  619. }
  620. /**
  621. * Register ourselves with the <code>SystemEventQueueUtils</code> as a new
  622. * root pane.
  623. */
  624. public void addNotify() {
  625. SystemEventQueueUtilities.addRunnableCanvas(this);
  626. super.addNotify();
  627. enableEvents(AWTEvent.KEY_EVENT_MASK);
  628. }
  629. // Note: These links don't work because the target
  630. // class is package private
  631. // @see SystemEventQueueUtilities#addRunnableCanvas
  632. // @see SystemEventQueueUtilities#removeRunnableCanvas
  633. /**
  634. * Unregister ourselves from <code>SystemEventQueueUtils</code>.
  635. * @see #addNotify
  636. */
  637. public void removeNotify() {
  638. SystemEventQueueUtilities.removeRunnableCanvas(this);
  639. super.removeNotify();
  640. }
  641. /**
  642. * Sets the <code>defaultButton</code> property,
  643. * which determines the current default button for this <code>JRootPane</code>.
  644. * The default button is the button which will be activated
  645. * when a UI-defined activation event (typically the <b>Enter</b> key)
  646. * occurs in the root pane regardless of whether or not the button
  647. * has keyboard focus (unless there is another component within
  648. * the root pane which consumes the activation event,
  649. * such as a <code>JTextPane</code>).
  650. * For default activation to work, the button must be an enabled
  651. * descendent of the root pane when activation occurs.
  652. * To remove a default button from this root pane, set this
  653. * property to <code>null</code>.
  654. *
  655. * @see JButton#isDefaultButton
  656. * @param defaultButton the <code>JButton</code> which is to be the default button
  657. *
  658. * @beaninfo
  659. * description: The button activated by default in this root pane
  660. */
  661. public void setDefaultButton(JButton defaultButton) {
  662. JButton oldDefault = this.defaultButton;
  663. if (oldDefault != defaultButton) {
  664. this.defaultButton = defaultButton;
  665. if (oldDefault != null) {
  666. oldDefault.repaint();
  667. }
  668. if (defaultButton != null) {
  669. defaultButton.repaint();
  670. }
  671. }
  672. firePropertyChange("defaultButton", oldDefault, defaultButton);
  673. }
  674. /**
  675. * Returns the value of the <code>defaultButton</code> property.
  676. * @return the <code>JButton</code> which is currently the default button
  677. * @see #setDefaultButton
  678. */
  679. public JButton getDefaultButton() {
  680. return defaultButton;
  681. }
  682. static class DefaultAction extends AbstractAction {
  683. JButton owner;
  684. JRootPane root;
  685. boolean press;
  686. DefaultAction(JRootPane root, boolean press) {
  687. this.root = root;
  688. this.press = press;
  689. }
  690. public void setOwner(JButton owner) {
  691. this.owner = owner;
  692. }
  693. public void actionPerformed(ActionEvent e) {
  694. if (owner != null && SwingUtilities.getRootPane(owner) == root) {
  695. ButtonModel model = owner.getModel();
  696. if (press) {
  697. model.setArmed(true);
  698. model.setPressed(true);
  699. } else {
  700. model.setPressed(false);
  701. }
  702. }
  703. }
  704. public boolean isEnabled() {
  705. return owner.getModel().isEnabled();
  706. }
  707. }
  708. /**
  709. * Overridden to enforce the position of the glass component as
  710. * the zero child.
  711. *
  712. * @param comp the component to be enhanced
  713. * @param constraints the constraints to be respected
  714. * @param index the index
  715. */
  716. protected void addImpl(Component comp, Object constraints, int index) {
  717. super.addImpl(comp, constraints, index);
  718. /// We are making sure the glassPane is on top.
  719. if(glassPane != null
  720. && glassPane.getParent() == this
  721. && getComponent(0) != glassPane) {
  722. add(glassPane, 0);
  723. }
  724. }
  725. ///////////////////////////////////////////////////////////////////////////////
  726. //// Begin Inner Classes
  727. ///////////////////////////////////////////////////////////////////////////////
  728. /**
  729. * A custom layout manager that is responsible for the layout of
  730. * layeredPane, glassPane, and menuBar.
  731. * <p>
  732. * <strong>Warning:</strong>
  733. * Serialized objects of this class will not be compatible with
  734. * future Swing releases. The current serialization support is
  735. * appropriate for short term storage or RMI between applications running
  736. * the same version of Swing. As of 1.4, support for long term storage
  737. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  738. * has been added to the <code>java.beans</code> package.
  739. * Please see {@link java.beans.XMLEncoder}.
  740. */
  741. protected class RootLayout implements LayoutManager2, Serializable
  742. {
  743. /**
  744. * Returns the amount of space the layout would like to have.
  745. *
  746. * @param parent the Container for which this layout manager
  747. * is being used
  748. * @return a Dimension object containing the layout's preferred size
  749. */
  750. public Dimension preferredLayoutSize(Container parent) {
  751. Dimension rd, mbd;
  752. Insets i = getInsets();
  753. if(contentPane != null) {
  754. rd = contentPane.getPreferredSize();
  755. } else {
  756. rd = parent.getSize();
  757. }
  758. if(menuBar != null && menuBar.isVisible()) {
  759. mbd = menuBar.getPreferredSize();
  760. } else {
  761. mbd = new Dimension(0, 0);
  762. }
  763. return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
  764. rd.height + mbd.height + i.top + i.bottom);
  765. }
  766. /**
  767. * Returns the minimum amount of space the layout needs.
  768. *
  769. * @param parent the Container for which this layout manager
  770. * is being used
  771. * @return a Dimension object containing the layout's minimum size
  772. */
  773. public Dimension minimumLayoutSize(Container parent) {
  774. Dimension rd, mbd;
  775. Insets i = getInsets();
  776. if(contentPane != null) {
  777. rd = contentPane.getMinimumSize();
  778. } else {
  779. rd = parent.getSize();
  780. }
  781. if(menuBar != null && menuBar.isVisible()) {
  782. mbd = menuBar.getMinimumSize();
  783. } else {
  784. mbd = new Dimension(0, 0);
  785. }
  786. return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
  787. rd.height + mbd.height + i.top + i.bottom);
  788. }
  789. /**
  790. * Returns the maximum amount of space the layout can use.
  791. *
  792. * @param target the Container for which this layout manager
  793. * is being used
  794. * @return a Dimension object containing the layout's maximum size
  795. */
  796. public Dimension maximumLayoutSize(Container target) {
  797. Dimension rd, mbd;
  798. Insets i = getInsets();
  799. if(menuBar != null && menuBar.isVisible()) {
  800. mbd = menuBar.getMaximumSize();
  801. } else {
  802. mbd = new Dimension(0, 0);
  803. }
  804. if(contentPane != null) {
  805. rd = contentPane.getMaximumSize();
  806. } else {
  807. // This is silly, but should stop an overflow error
  808. rd = new Dimension(Integer.MAX_VALUE,
  809. Integer.MAX_VALUE - i.top - i.bottom - mbd.height - 1);
  810. }
  811. return new Dimension(Math.min(rd.width, mbd.width) + i.left + i.right,
  812. rd.height + mbd.height + i.top + i.bottom);
  813. }
  814. /**
  815. * Instructs the layout manager to perform the layout for the specified
  816. * container.
  817. *
  818. * @param parent the Container for which this layout manager
  819. * is being used
  820. */
  821. public void layoutContainer(Container parent) {
  822. Rectangle b = parent.getBounds();
  823. Insets i = getInsets();
  824. int contentY = 0;
  825. int w = b.width - i.right - i.left;
  826. int h = b.height - i.top - i.bottom;
  827. if(layeredPane != null) {
  828. layeredPane.setBounds(i.left, i.top, w, h);
  829. }
  830. if(glassPane != null) {
  831. glassPane.setBounds(i.left, i.top, w, h);
  832. }
  833. // Note: This is laying out the children in the layeredPane,
  834. // technically, these are not our children.
  835. if(menuBar != null && menuBar.isVisible()) {
  836. Dimension mbd = menuBar.getPreferredSize();
  837. menuBar.setBounds(0, 0, w, mbd.height);
  838. contentY += mbd.height;
  839. }
  840. if(contentPane != null) {
  841. contentPane.setBounds(0, contentY, w, h - contentY);
  842. }
  843. }
  844. public void addLayoutComponent(String name, Component comp) {}
  845. public void removeLayoutComponent(Component comp) {}
  846. public void addLayoutComponent(Component comp, Object constraints) {}
  847. public float getLayoutAlignmentX(Container target) { return 0.0f; }
  848. public float getLayoutAlignmentY(Container target) { return 0.0f; }
  849. public void invalidateLayout(Container target) {}
  850. }
  851. void setMostRecentFocusOwner(Component focusOwner) {
  852. mostRecentFocusOwner = focusOwner;
  853. }
  854. Component getMostRecentFocusOwner() {
  855. return mostRecentFocusOwner;
  856. }
  857. /**
  858. * Returns a string representation of this <code>JRootPane</code>.
  859. * This method is intended to be used only for debugging purposes,
  860. * and the content and format of the returned string may vary between
  861. * implementations. The returned string may be empty but may not
  862. * be <code>null</code>.
  863. *
  864. * @return a string representation of this <code>JRootPane</code>.
  865. */
  866. protected String paramString() {
  867. return super.paramString();
  868. }
  869. /////////////////
  870. // Accessibility support
  871. ////////////////
  872. /**
  873. * Gets the <code>AccessibleContext</code> associated with this
  874. * <code>JRootPane</code>. For root panes, the
  875. * <code>AccessibleContext</code> takes the form of an
  876. * <code>AccessibleJRootPane</code>.
  877. * A new <code>AccessibleJRootPane</code> instance is created if necessary.
  878. *
  879. * @return an <code>AccessibleJRootPane</code> that serves as the
  880. * <code>AccessibleContext</code> of this <code>JRootPane</code>
  881. */
  882. public AccessibleContext getAccessibleContext() {
  883. if (accessibleContext == null) {
  884. accessibleContext = new AccessibleJRootPane();
  885. }
  886. return accessibleContext;
  887. }
  888. /**
  889. * This class implements accessibility support for the
  890. * <code>JRootPane</code> class. It provides an implementation of the
  891. * Java Accessibility API appropriate to root pane user-interface elements.
  892. * <p>
  893. * <strong>Warning:</strong>
  894. * Serialized objects of this class will not be compatible with
  895. * future Swing releases. The current serialization support is
  896. * appropriate for short term storage or RMI between applications running
  897. * the same version of Swing. As of 1.4, support for long term storage
  898. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  899. * has been added to the <code>java.beans</code> package.
  900. * Please see {@link java.beans.XMLEncoder}.
  901. */
  902. protected class AccessibleJRootPane extends AccessibleJComponent {
  903. /**
  904. * Get the role of this object.
  905. *
  906. * @return an instance of AccessibleRole describing the role of
  907. * the object
  908. */
  909. public AccessibleRole getAccessibleRole() {
  910. return AccessibleRole.ROOT_PANE;
  911. }
  912. } // inner class AccessibleJRootPane
  913. }