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