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