| /* | |
| * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package javax.swing; | |
| import java.awt.*; | |
| import java.beans.*; | |
| import javax.accessibility.*; | |
| import javax.swing.plaf.RootPaneUI; | |
| import java.io.Serializable; | |
| /** | |
| * A lightweight container used behind the scenes by | |
| * <code>JFrame</code>, <code>JDialog</code>, <code>JWindow</code>, | |
| * <code>JApplet</code>, and <code>JInternalFrame</code>. | |
| * For task-oriented information on functionality provided by root panes | |
| * see <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html">How to Use Root Panes</a>, | |
| * a section in <em>The Java Tutorial</em>. | |
| * | |
| * <p> | |
| * The following image shows the relationships between | |
| * the classes that use root panes. | |
| * <p style="text-align:center"><img src="doc-files/JRootPane-1.gif" | |
| * alt="The following text describes this graphic." | |
| * HEIGHT=484 WIDTH=629></p> | |
| * The "heavyweight" components (those that delegate to a peer, or native | |
| * component on the host system) are shown with a darker, heavier box. The four | |
| * heavyweight JFC/Swing containers (<code>JFrame</code>, <code>JDialog</code>, | |
| * <code>JWindow</code>, and <code>JApplet</code>) are | |
| * shown in relation to the AWT classes they extend. | |
| * These four components are the | |
| * only heavyweight containers in the Swing library. The lightweight container | |
| * <code>JInternalFrame</code> is also shown. | |
| * All five of these JFC/Swing containers implement the | |
| * <code>RootPaneContainer</code> interface, | |
| * and they all delegate their operations to a | |
| * <code>JRootPane</code> (shown with a little "handle" on top). | |
| * <blockquote> | |
| * <b>Note:</b> The <code>JComponent</code> method <code>getRootPane</code> | |
| * can be used to obtain the <code>JRootPane</code> that contains | |
| * a given component. | |
| * </blockquote> | |
| * | |
| * <div style="float:right;text-align:center;font-weight:bold"> | |
| * <p>Example: | |
| * <p><img src="doc-files/JRootPane-2.gif" | |
| * alt="the following text describes this graphic." height=386 width=349> | |
| * </div> | |
| * The diagram at right shows the structure of a <code>JRootPane</code>. | |
| * A <code>JRootpane</code> is made up of a <code>glassPane</code>, | |
| * an optional <code>menuBar</code>, and a <code>contentPane</code>. | |
| * (The <code>JLayeredPane</code> manages the <code>menuBar</code> | |
| * and the <code>contentPane</code>.) | |
| * The <code>glassPane</code> sits over the top of everything, | |
| * where it is in a position to intercept mouse movements. | |
| * Since the <code>glassPane</code> (like the <code>contentPane</code>) | |
| * can be an arbitrary component, it is also possible to set up the | |
| * <code>glassPane</code> for drawing. Lines and images on the | |
| * <code>glassPane</code> can then range | |
| * over the frames underneath without being limited by their boundaries. | |
| * <p> | |
| * Although the <code>menuBar</code> component is optional, | |
| * the <code>layeredPane</code>, <code>contentPane</code>, | |
| * and <code>glassPane</code> always exist. | |
| * Attempting to set them to <code>null</code> generates an exception. | |
| * <p> | |
| * To add components to the <code>JRootPane</code> (other than the | |
| * optional menu bar), you add the object to the <code>contentPane</code> | |
| * of the <code>JRootPane</code>, like this: | |
| * <pre> | |
| * rootPane.getContentPane().add(child); | |
| * </pre> | |
| * The same principle holds true for setting layout managers, removing | |
| * components, listing children, etc. All these methods are invoked on | |
| * the <code>contentPane</code> instead of on the <code>JRootPane</code>. | |
| * <blockquote> | |
| * <b>Note:</b> The default layout manager for the <code>contentPane</code> is | |
| * a <code>BorderLayout</code> manager. However, the <code>JRootPane</code> | |
| * uses a custom <code>LayoutManager</code>. | |
| * So, when you want to change the layout manager for the components you added | |
| * to a <code>JRootPane</code>, be sure to use code like this: | |
| * <pre> | |
| * rootPane.getContentPane().setLayout(new BoxLayout()); | |
| * </pre></blockquote> | |
| * If a <code>JMenuBar</code> component is set on the <code>JRootPane</code>, | |
| * it is positioned along the upper edge of the frame. | |
| * The <code>contentPane</code> is adjusted in location and size to | |
| * fill the remaining area. | |
| * (The <code>JMenuBar</code> and the <code>contentPane</code> are added to the | |
| * <code>layeredPane</code> component at the | |
| * <code>JLayeredPane.FRAME_CONTENT_LAYER</code> layer.) | |
| * <p> | |
| * The <code>layeredPane</code> is the parent of all children in the | |
| * <code>JRootPane</code> -- both as the direct parent of the menu and | |
| * the grandparent of all components added to the <code>contentPane</code>. | |
| * It is an instance of <code>JLayeredPane</code>, | |
| * which provides the ability to add components at several layers. | |
| * This capability is very useful when working with menu popups, | |
| * dialog boxes, and dragging -- situations in which you need to place | |
| * a component on top of all other components in the pane. | |
| * <p> | |
| * The <code>glassPane</code> sits on top of all other components in the | |
| * <code>JRootPane</code>. | |
| * That provides a convenient place to draw above all other components, | |
| * and makes it possible to intercept mouse events, | |
| * which is useful both for dragging and for drawing. | |
| * Developers can use <code>setVisible</code> on the <code>glassPane</code> | |
| * to control when the <code>glassPane</code> displays over the other children. | |
| * By default the <code>glassPane</code> is not visible. | |
| * <p> | |
| * The custom <code>LayoutManager</code> used by <code>JRootPane</code> | |
| * ensures that: | |
| * <OL> | |
| * <LI>The <code>glassPane</code> fills the entire viewable | |
| * area of the <code>JRootPane</code> (bounds - insets). | |
| * <LI>The <code>layeredPane</code> fills the entire viewable area of the | |
| * <code>JRootPane</code>. (bounds - insets) | |
| * <LI>The <code>menuBar</code> is positioned at the upper edge of the | |
| * <code>layeredPane</code>. | |
| * <LI>The <code>contentPane</code> fills the entire viewable area, | |
| * minus the <code>menuBar</code>, if present. | |
| * </OL> | |
| * Any other views in the <code>JRootPane</code> view hierarchy are ignored. | |
| * <p> | |
| * If you replace the <code>LayoutManager</code> of the <code>JRootPane</code>, | |
| * you are responsible for managing all of these views. | |
| * So ordinarily you will want to be sure that you | |
| * change the layout manager for the <code>contentPane</code> rather than | |
| * for the <code>JRootPane</code> itself! | |
| * <p> | |
| * The painting architecture of Swing requires an opaque | |
| * <code>JComponent</code> | |
| * to exist in the containment hierarchy above all other components. This is | |
| * typically provided by way of the content pane. If you replace the content | |
| * pane, it is recommended that you make the content pane opaque | |
| * by way of <code>setOpaque(true)</code>. Additionally, if the content pane | |
| * overrides <code>paintComponent</code>, it | |
| * will need to completely fill in the background in an opaque color in | |
| * <code>paintComponent</code>. | |
| * <p> | |
| * <strong>Warning:</strong> Swing is not thread safe. For more | |
| * information see <a | |
| * href="package-summary.html#threading">Swing's Threading | |
| * Policy</a>. | |
| * <p> | |
| * <strong>Warning:</strong> | |
| * Serialized objects of this class will not be compatible with | |
| * future Swing releases. The current serialization support is | |
| * appropriate for short term storage or RMI between applications running | |
| * the same version of Swing. As of 1.4, support for long term storage | |
| * of all JavaBeans | |
| * has been added to the <code>java.beans</code> package. | |
| * Please see {@link java.beans.XMLEncoder}. | |
| * | |
| * @see JLayeredPane | |
| * @see JMenuBar | |
| * @see JWindow | |
| * @see JFrame | |
| * @see JDialog | |
| * @see JApplet | |
| * @see JInternalFrame | |
| * @see JComponent | |
| * @see BoxLayout | |
| * | |
| * @see <a href="http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html"> | |
| * Mixing Heavy and Light Components</a> | |
| * | |
| * @author David Kloba | |
| * @since 1.2 | |
| */ | |
| @SuppressWarnings("serial") | |
| public class JRootPane extends JComponent implements Accessible { | |
| private static final String uiClassID = "RootPaneUI"; | |
| /** | |
| * Whether or not we should dump the stack when true double buffering | |
| * is disabled. Default is false. | |
| */ | |
| private static final boolean LOG_DISABLE_TRUE_DOUBLE_BUFFERING | |
| = Boolean.getBoolean("swing.logDoubleBufferingDisable"); | |
| /** | |
| * Whether or not we should ignore requests to disable true double | |
| * buffering. Default is false. | |
| */ | |
| private static final boolean IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING | |
| = Boolean.getBoolean("swing.ignoreDoubleBufferingDisable"); | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should not provide any sort of | |
| * Window decorations. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int NONE = 0; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Frame. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int FRAME = 1; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int PLAIN_DIALOG = 2; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to display an informational message. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int INFORMATION_DIALOG = 3; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to display an error message. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int ERROR_DIALOG = 4; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to display a <code>JColorChooser</code>. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int COLOR_CHOOSER_DIALOG = 5; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to display a <code>JFileChooser</code>. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int FILE_CHOOSER_DIALOG = 6; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to present a question to the user. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int QUESTION_DIALOG = 7; | |
| /** | |
| * Constant used for the windowDecorationStyle property. Indicates that | |
| * the <code>JRootPane</code> should provide decorations appropriate for | |
| * a Dialog used to display a warning message. | |
| * | |
| * @since 1.4 | |
| */ | |
| public static final int WARNING_DIALOG = 8; | |
| private int windowDecorationStyle; | |
| /** The menu bar. */ | |
| protected JMenuBar menuBar; | |
| /** The content pane. */ | |
| protected Container contentPane; | |
| /** The layered pane that manages the menu bar and content pane. */ | |
| protected JLayeredPane layeredPane; | |
| /** | |
| * The glass pane that overlays the menu bar and content pane, | |
| * so it can intercept mouse movements and such. | |
| */ | |
| protected Component glassPane; | |
| /** | |
| * The button that gets activated when the pane has the focus and | |
| * a UI-specific action like pressing the <b>Enter</b> key occurs. | |
| */ | |
| protected JButton defaultButton; | |
| /** | |
| * Whether or not true double buffering should be used. This is typically | |
| * true, but may be set to false in special situations. For example, | |
| * heavy weight popups (backed by a window) set this to false. | |
| */ | |
| boolean useTrueDoubleBuffering = true; | |
| /** | |
| * Creates a <code>JRootPane</code>, setting up its | |
| * <code>glassPane</code>, <code>layeredPane</code>, | |
| * and <code>contentPane</code>. | |
| */ | |
| public JRootPane() { | |
| setGlassPane(createGlassPane()); | |
| setLayeredPane(createLayeredPane()); | |
| setContentPane(createContentPane()); | |
| setLayout(createRootLayout()); | |
| setDoubleBuffered(true); | |
| updateUI(); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * @since 1.6 | |
| */ | |
| public void setDoubleBuffered(boolean aFlag) { | |
| if (isDoubleBuffered() != aFlag) { | |
| super.setDoubleBuffered(aFlag); | |
| RepaintManager.currentManager(this).doubleBufferingChanged(this); | |
| } | |
| } | |
| /** | |
| * Returns a constant identifying the type of Window decorations the | |
| * <code>JRootPane</code> is providing. | |
| * | |
| * @return One of <code>NONE</code>, <code>FRAME</code>, | |
| * <code>PLAIN_DIALOG</code>, <code>INFORMATION_DIALOG</code>, | |
| * <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>, | |
| * <code>FILE_CHOOSER_DIALOG</code>, <code>QUESTION_DIALOG</code> or | |
| * <code>WARNING_DIALOG</code>. | |
| * @see #setWindowDecorationStyle | |
| * @since 1.4 | |
| */ | |
| public int getWindowDecorationStyle() { | |
| return windowDecorationStyle; | |
| } | |
| /** | |
| * Sets the type of Window decorations (such as borders, widgets for | |
| * closing a Window, title ...) the <code>JRootPane</code> should | |
| * provide. The default is to provide no Window decorations | |
| * (<code>NONE</code>). | |
| * <p> | |
| * This is only a hint, and some look and feels may not support | |
| * this. | |
| * This is a bound property. | |
| * | |
| * @param windowDecorationStyle Constant identifying Window decorations | |
| * to provide. | |
| * @see JDialog#setDefaultLookAndFeelDecorated | |
| * @see JFrame#setDefaultLookAndFeelDecorated | |
| * @see LookAndFeel#getSupportsWindowDecorations | |
| * @throws IllegalArgumentException if <code>style</code> is | |
| * not one of: <code>NONE</code>, <code>FRAME</code>, | |
| * <code>PLAIN_DIALOG</code>, <code>INFORMATION_DIALOG</code>, | |
| * <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>, | |
| * <code>FILE_CHOOSER_DIALOG</code>, <code>QUESTION_DIALOG</code>, or | |
| * <code>WARNING_DIALOG</code>. | |
| * @since 1.4 | |
| */ | |
| @BeanProperty(expert = true, visualUpdate = true, enumerationValues = { | |
| "JRootPane.NONE", | |
| "JRootPane.FRAME", | |
| "JRootPane.PLAIN_DIALOG", | |
| "JRootPane.INFORMATION_DIALOG", | |
| "JRootPane.ERROR_DIALOG", | |
| "JRootPane.COLOR_CHOOSER_DIALOG", | |
| "JRootPane.FILE_CHOOSER_DIALOG", | |
| "JRootPane.QUESTION_DIALOG", | |
| "JRootPane.WARNING_DIALOG"}, description | |
| = "Identifies the type of Window decorations to provide") | |
| public void setWindowDecorationStyle(int windowDecorationStyle) { | |
| if (windowDecorationStyle < 0 || | |
| windowDecorationStyle > WARNING_DIALOG) { | |
| throw new IllegalArgumentException("Invalid decoration style"); | |
| } | |
| int oldWindowDecorationStyle = getWindowDecorationStyle(); | |
| this.windowDecorationStyle = windowDecorationStyle; | |
| firePropertyChange("windowDecorationStyle", | |
| oldWindowDecorationStyle, | |
| windowDecorationStyle); | |
| } | |
| /** | |
| * Returns the L&F object that renders this component. | |
| * | |
| * @return <code>LabelUI</code> object | |
| * @since 1.3 | |
| */ | |
| public RootPaneUI getUI() { | |
| return (RootPaneUI)ui; | |
| } | |
| /** | |
| * Sets the L&F object that renders this component. | |
| * | |
| * @param ui the <code>LabelUI</code> L&F object | |
| * @see UIDefaults#getUI | |
| * @since 1.3 | |
| */ | |
| @BeanProperty(expert = true, hidden = true, visualUpdate = true, description | |
| = "The UI object that implements the Component's LookAndFeel.") | |
| public void setUI(RootPaneUI ui) { | |
| super.setUI(ui); | |
| } | |
| /** | |
| * Resets the UI property to a value from the current look and feel. | |
| * | |
| * @see JComponent#updateUI | |
| */ | |
| public void updateUI() { | |
| setUI((RootPaneUI)UIManager.getUI(this)); | |
| } | |
| /** | |
| * Returns a string that specifies the name of the L&F class | |
| * that renders this component. | |
| * | |
| * @return the string "RootPaneUI" | |
| * | |
| * @see JComponent#getUIClassID | |
| * @see UIDefaults#getUI | |
| */ | |
| public String getUIClassID() { | |
| return uiClassID; | |
| } | |
| /** | |
| * Called by the constructor methods to create the default | |
| * <code>layeredPane</code>. | |
| * Bt default it creates a new <code>JLayeredPane</code>. | |
| * @return the default <code>layeredPane</code> | |
| */ | |
| protected JLayeredPane createLayeredPane() { | |
| JLayeredPane p = new JLayeredPane(); | |
| p.setName(this.getName()+".layeredPane"); | |
| return p; | |
| } | |
| /** | |
| * Called by the constructor methods to create the default | |
| * <code>contentPane</code>. | |
| * By default this method creates a new <code>JComponent</code> add sets a | |
| * <code>BorderLayout</code> as its <code>LayoutManager</code>. | |
| * @return the default <code>contentPane</code> | |
| */ | |
| protected Container createContentPane() { | |
| JComponent c = new JPanel(); | |
| c.setName(this.getName()+".contentPane"); | |
| c.setLayout(new BorderLayout() { | |
| /* This BorderLayout subclass maps a null constraint to CENTER. | |
| * Although the reference BorderLayout also does this, some VMs | |
| * throw an IllegalArgumentException. | |
| */ | |
| public void addLayoutComponent(Component comp, Object constraints) { | |
| if (constraints == null) { | |
| constraints = BorderLayout.CENTER; | |
| } | |
| super.addLayoutComponent(comp, constraints); | |
| } | |
| }); | |
| return c; | |
| } | |
| /** | |
| * Called by the constructor methods to create the default | |
| * <code>glassPane</code>. | |
| * By default this method creates a new <code>JComponent</code> | |
| * with visibility set to false. | |
| * @return the default <code>glassPane</code> | |
| */ | |
| protected Component createGlassPane() { | |
| JPanel c = new JPanel(); | |
| c.setName(this.getName()+".glassPane"); | |
| c.setVisible(false); | |
| c.setOpaque(false); | |
| return c; | |
| } | |
| /** | |
| * Called by the constructor methods to create the default | |
| * <code>layoutManager</code>. | |
| * @return the default <code>layoutManager</code>. | |
| */ | |
| protected LayoutManager createRootLayout() { | |
| return new RootLayout(); | |
| } | |
| /** | |
| * Adds or changes the menu bar used in the layered pane. | |
| * @param menu the <code>JMenuBar</code> to add | |
| */ | |
| public void setJMenuBar(JMenuBar menu) { | |
| if(menuBar != null && menuBar.getParent() == layeredPane) | |
| layeredPane.remove(menuBar); | |
| menuBar = menu; | |
| if(menuBar != null) { | |
| menuBar.updateUI(); | |
| layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER); | |
| } | |
| } | |
| /** | |
| * Specifies the menu bar value. | |
| * @deprecated As of Swing version 1.0.3 | |
| * replaced by <code>setJMenuBar(JMenuBar menu)</code>. | |
| * @param menu the <code>JMenuBar</code> to add. | |
| */ | |
| @Deprecated | |
| public void setMenuBar(JMenuBar menu){ | |
| if(menuBar != null && menuBar.getParent() == layeredPane) | |
| layeredPane.remove(menuBar); | |
| menuBar = menu; | |
| if(menuBar != null) | |
| layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER); | |
| } | |
| /** | |
| * Returns the menu bar from the layered pane. | |
| * @return the <code>JMenuBar</code> used in the pane | |
| */ | |
| public JMenuBar getJMenuBar() { return menuBar; } | |
| /** | |
| * Returns the menu bar value. | |
| * @deprecated As of Swing version 1.0.3 | |
| * replaced by <code>getJMenuBar()</code>. | |
| * @return the <code>JMenuBar</code> used in the pane | |
| */ | |
| @Deprecated | |
| public JMenuBar getMenuBar() { return menuBar; } | |
| /** | |
| * Sets the content pane -- the container that holds the components | |
| * parented by the root pane. | |
| * <p> | |
| * Swing's painting architecture requires an opaque <code>JComponent</code> | |
| * in the containment hierarchy. This is typically provided by the | |
| * content pane. If you replace the content pane it is recommended you | |
| * replace it with an opaque <code>JComponent</code>. | |
| * | |
| * @param content the <code>Container</code> to use for component-contents | |
| * @throws java.awt.IllegalComponentStateException (a runtime | |
| * exception) if the content pane parameter is <code>null</code> | |
| */ | |
| public void setContentPane(Container content) { | |
| if(content == null) | |
| throw new IllegalComponentStateException("contentPane cannot be set to null."); | |
| if(contentPane != null && contentPane.getParent() == layeredPane) | |
| layeredPane.remove(contentPane); | |
| contentPane = content; | |
| layeredPane.add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER); | |
| } | |
| /** | |
| * Returns the content pane -- the container that holds the components | |
| * parented by the root pane. | |
| * | |
| * @return the <code>Container</code> that holds the component-contents | |
| */ | |
| public Container getContentPane() { return contentPane; } | |
| // PENDING(klobad) Should this reparent the contentPane and MenuBar? | |
| /** | |
| * Sets the layered pane for the root pane. The layered pane | |
| * typically holds a content pane and an optional <code>JMenuBar</code>. | |
| * | |
| * @param layered the <code>JLayeredPane</code> to use | |
| * @throws java.awt.IllegalComponentStateException (a runtime | |
| * exception) if the layered pane parameter is <code>null</code> | |
| */ | |
| public void setLayeredPane(JLayeredPane layered) { | |
| if(layered == null) | |
| throw new IllegalComponentStateException("layeredPane cannot be set to null."); | |
| if(layeredPane != null && layeredPane.getParent() == this) | |
| this.remove(layeredPane); | |
| layeredPane = layered; | |
| this.add(layeredPane, -1); | |
| } | |
| /** | |
| * Gets the layered pane used by the root pane. The layered pane | |
| * typically holds a content pane and an optional <code>JMenuBar</code>. | |
| * | |
| * @return the <code>JLayeredPane</code> currently in use | |
| */ | |
| public JLayeredPane getLayeredPane() { return layeredPane; } | |
| /** | |
| * Sets a specified <code>Component</code> to be the glass pane for this | |
| * root pane. The glass pane should normally be a lightweight, | |
| * transparent component, because it will be made visible when | |
| * ever the root pane needs to grab input events. | |
| * <p> | |
| * The new glass pane's visibility is changed to match that of | |
| * the current glass pane. An implication of this is that care | |
| * must be taken when you want to replace the glass pane and | |
| * make it visible. Either of the following will work: | |
| * <pre> | |
| * root.setGlassPane(newGlassPane); | |
| * newGlassPane.setVisible(true); | |
| * </pre> | |
| * or: | |
| * <pre> | |
| * root.getGlassPane().setVisible(true); | |
| * root.setGlassPane(newGlassPane); | |
| * </pre> | |
| * | |
| * @param glass the <code>Component</code> to use as the glass pane | |
| * for this <code>JRootPane</code> | |
| * @throws NullPointerException if the <code>glass</code> parameter is | |
| * <code>null</code> | |
| */ | |
| public void setGlassPane(Component glass) { | |
| if (glass == null) { | |
| throw new NullPointerException("glassPane cannot be set to null."); | |
| } | |
| glass.setMixingCutoutShape(new Rectangle()); | |
| boolean visible = false; | |
| if (glassPane != null && glassPane.getParent() == this) { | |
| this.remove(glassPane); | |
| visible = glassPane.isVisible(); | |
| } | |
| glass.setVisible(visible); | |
| glassPane = glass; | |
| this.add(glassPane, 0); | |
| if (visible) { | |
| repaint(); | |
| } | |
| } | |
| /** | |
| * Returns the current glass pane for this <code>JRootPane</code>. | |
| * @return the current glass pane | |
| * @see #setGlassPane | |
| */ | |
| public Component getGlassPane() { | |
| return glassPane; | |
| } | |
| /** | |
| * If a descendant of this <code>JRootPane</code> calls | |
| * <code>revalidate</code>, validate from here on down. | |
| *<p> | |
| * Deferred requests to layout a component and its descendents again. | |
| * For example, calls to <code>revalidate</code>, are pushed upwards to | |
| * either a <code>JRootPane</code> or a <code>JScrollPane</code> | |
| * because both classes override <code>isValidateRoot</code> to return true. | |
| * | |
| * @see JComponent#isValidateRoot | |
| * @see java.awt.Container#isValidateRoot | |
| * @return true | |
| */ | |
| @Override | |
| public boolean isValidateRoot() { | |
| return true; | |
| } | |
| /** | |
| * The <code>glassPane</code> and <code>contentPane</code> | |
| * have the same bounds, which means <code>JRootPane</code> | |
| * does not tiles its children and this should return false. | |
| * On the other hand, the <code>glassPane</code> | |
| * is normally not visible, and so this can return true if the | |
| * <code>glassPane</code> isn't visible. Therefore, the | |
| * return value here depends upon the visibility of the | |
| * <code>glassPane</code>. | |
| * | |
| * @return true if this component's children don't overlap | |
| */ | |
| public boolean isOptimizedDrawingEnabled() { | |
| return !glassPane.isVisible(); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| public void addNotify() { | |
| super.addNotify(); | |
| enableEvents(AWTEvent.KEY_EVENT_MASK); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| public void removeNotify() { | |
| super.removeNotify(); | |
| } | |
| /** | |
| * Sets the <code>defaultButton</code> property, | |
| * which determines the current default button for this <code>JRootPane</code>. | |
| * The default button is the button which will be activated | |
| * when a UI-defined activation event (typically the <b>Enter</b> key) | |
| * occurs in the root pane regardless of whether or not the button | |
| * has keyboard focus (unless there is another component within | |
| * the root pane which consumes the activation event, | |
| * such as a <code>JTextPane</code>). | |
| * For default activation to work, the button must be an enabled | |
| * descendent of the root pane when activation occurs. | |
| * To remove a default button from this root pane, set this | |
| * property to <code>null</code>. | |
| * | |
| * @see JButton#isDefaultButton | |
| * @param defaultButton the <code>JButton</code> which is to be the default button | |
| */ | |
| @BeanProperty(description | |
| = "The button activated by default in this root pane") | |
| public void setDefaultButton(JButton defaultButton) { | |
| JButton oldDefault = this.defaultButton; | |
| if (oldDefault != defaultButton) { | |
| this.defaultButton = defaultButton; | |
| if (oldDefault != null) { | |
| oldDefault.repaint(); | |
| } | |
| if (defaultButton != null) { | |
| defaultButton.repaint(); | |
| } | |
| } | |
| firePropertyChange("defaultButton", oldDefault, defaultButton); | |
| } | |
| /** | |
| * Returns the value of the <code>defaultButton</code> property. | |
| * @return the <code>JButton</code> which is currently the default button | |
| * @see #setDefaultButton | |
| */ | |
| public JButton getDefaultButton() { | |
| return defaultButton; | |
| } | |
| final void setUseTrueDoubleBuffering(boolean useTrueDoubleBuffering) { | |
| this.useTrueDoubleBuffering = useTrueDoubleBuffering; | |
| } | |
| final boolean getUseTrueDoubleBuffering() { | |
| return useTrueDoubleBuffering; | |
| } | |
| final void disableTrueDoubleBuffering() { | |
| if (useTrueDoubleBuffering) { | |
| if (!IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING) { | |
| if (LOG_DISABLE_TRUE_DOUBLE_BUFFERING) { | |
| System.out.println("Disabling true double buffering for " + | |
| this); | |
| Thread.dumpStack(); | |
| } | |
| useTrueDoubleBuffering = false; | |
| RepaintManager.currentManager(this). | |
| doubleBufferingChanged(this); | |
| } | |
| } | |
| } | |
| /** | |
| * Overridden to enforce the position of the glass component as | |
| * the zero child. | |
| * | |
| * @param comp the component to be enhanced | |
| * @param constraints the constraints to be respected | |
| * @param index the index | |
| */ | |
| protected void addImpl(Component comp, Object constraints, int index) { | |
| super.addImpl(comp, constraints, index); | |
| /// We are making sure the glassPane is on top. | |
| if(glassPane != null | |
| && glassPane.getParent() == this | |
| && getComponent(0) != glassPane) { | |
| add(glassPane, 0); | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////// | |
| //// Begin Inner Classes | |
| /////////////////////////////////////////////////////////////////////////////// | |
| /** | |
| * A custom layout manager that is responsible for the layout of | |
| * layeredPane, glassPane, and menuBar. | |
| * <p> | |
| * <strong>Warning:</strong> | |
| * Serialized objects of this class will not be compatible with | |
| * future Swing releases. The current serialization support is | |
| * appropriate for short term storage or RMI between applications running | |
| * the same version of Swing. As of 1.4, support for long term storage | |
| * of all JavaBeans | |
| * has been added to the <code>java.beans</code> package. | |
| * Please see {@link java.beans.XMLEncoder}. | |
| */ | |
| @SuppressWarnings("serial") | |
| protected class RootLayout implements LayoutManager2, Serializable | |
| { | |
| /** | |
| * Constructs a {@code RootLayout}. | |
| */ | |
| protected RootLayout() {} | |
| /** | |
| * Returns the amount of space the layout would like to have. | |
| * | |
| * @param parent the Container for which this layout manager | |
| * is being used | |
| * @return a Dimension object containing the layout's preferred size | |
| */ | |
| public Dimension preferredLayoutSize(Container parent) { | |
| Dimension rd, mbd; | |
| Insets i = getInsets(); | |
| if(contentPane != null) { | |
| rd = contentPane.getPreferredSize(); | |
| } else { | |
| rd = parent.getSize(); | |
| } | |
| if(menuBar != null && menuBar.isVisible()) { | |
| mbd = menuBar.getPreferredSize(); | |
| } else { | |
| mbd = new Dimension(0, 0); | |
| } | |
| return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right, | |
| rd.height + mbd.height + i.top + i.bottom); | |
| } | |
| /** | |
| * Returns the minimum amount of space the layout needs. | |
| * | |
| * @param parent the Container for which this layout manager | |
| * is being used | |
| * @return a Dimension object containing the layout's minimum size | |
| */ | |
| public Dimension minimumLayoutSize(Container parent) { | |
| Dimension rd, mbd; | |
| Insets i = getInsets(); | |
| if(contentPane != null) { | |
| rd = contentPane.getMinimumSize(); | |
| } else { | |
| rd = parent.getSize(); | |
| } | |
| if(menuBar != null && menuBar.isVisible()) { | |
| mbd = menuBar.getMinimumSize(); | |
| } else { | |
| mbd = new Dimension(0, 0); | |
| } | |
| return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right, | |
| rd.height + mbd.height + i.top + i.bottom); | |
| } | |
| /** | |
| * Returns the maximum amount of space the layout can use. | |
| * | |
| * @param target the Container for which this layout manager | |
| * is being used | |
| * @return a Dimension object containing the layout's maximum size | |
| */ | |
| public Dimension maximumLayoutSize(Container target) { | |
| Dimension rd, mbd; | |
| Insets i = getInsets(); | |
| if(menuBar != null && menuBar.isVisible()) { | |
| mbd = menuBar.getMaximumSize(); | |
| } else { | |
| mbd = new Dimension(0, 0); | |
| } | |
| if(contentPane != null) { | |
| rd = contentPane.getMaximumSize(); | |
| } else { | |
| // This is silly, but should stop an overflow error | |
| rd = new Dimension(Integer.MAX_VALUE, | |
| Integer.MAX_VALUE - i.top - i.bottom - mbd.height - 1); | |
| } | |
| return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right, | |
| rd.height + mbd.height + i.top + i.bottom); | |
| } | |
| /** | |
| * Instructs the layout manager to perform the layout for the specified | |
| * container. | |
| * | |
| * @param parent the Container for which this layout manager | |
| * is being used | |
| */ | |
| public void layoutContainer(Container parent) { | |
| Rectangle b = parent.getBounds(); | |
| Insets i = getInsets(); | |
| int contentY = 0; | |
| int w = b.width - i.right - i.left; | |
| int h = b.height - i.top - i.bottom; | |
| if(layeredPane != null) { | |
| layeredPane.setBounds(i.left, i.top, w, h); | |
| } | |
| if(glassPane != null) { | |
| glassPane.setBounds(i.left, i.top, w, h); | |
| } | |
| // Note: This is laying out the children in the layeredPane, | |
| // technically, these are not our children. | |
| if(menuBar != null && menuBar.isVisible()) { | |
| Dimension mbd = menuBar.getPreferredSize(); | |
| menuBar.setBounds(0, 0, w, mbd.height); | |
| contentY += mbd.height; | |
| } | |
| if(contentPane != null) { | |
| contentPane.setBounds(0, contentY, w, h - contentY); | |
| } | |
| } | |
| public void addLayoutComponent(String name, Component comp) {} | |
| public void removeLayoutComponent(Component comp) {} | |
| public void addLayoutComponent(Component comp, Object constraints) {} | |
| public float getLayoutAlignmentX(Container target) { return 0.0f; } | |
| public float getLayoutAlignmentY(Container target) { return 0.0f; } | |
| public void invalidateLayout(Container target) {} | |
| } | |
| /** | |
| * Returns a string representation of this <code>JRootPane</code>. | |
| * This method is intended to be used only for debugging purposes, | |
| * and the content and format of the returned string may vary between | |
| * implementations. The returned string may be empty but may not | |
| * be <code>null</code>. | |
| * | |
| * @return a string representation of this <code>JRootPane</code>. | |
| */ | |
| protected String paramString() { | |
| return super.paramString(); | |
| } | |
| ///////////////// | |
| // Accessibility support | |
| //////////////// | |
| /** | |
| * Gets the <code>AccessibleContext</code> associated with this | |
| * <code>JRootPane</code>. For root panes, the | |
| * <code>AccessibleContext</code> takes the form of an | |
| * <code>AccessibleJRootPane</code>. | |
| * A new <code>AccessibleJRootPane</code> instance is created if necessary. | |
| * | |
| * @return an <code>AccessibleJRootPane</code> that serves as the | |
| * <code>AccessibleContext</code> of this <code>JRootPane</code> | |
| */ | |
| public AccessibleContext getAccessibleContext() { | |
| if (accessibleContext == null) { | |
| accessibleContext = new AccessibleJRootPane(); | |
| } | |
| return accessibleContext; | |
| } | |
| /** | |
| * This class implements accessibility support for the | |
| * <code>JRootPane</code> class. It provides an implementation of the | |
| * Java Accessibility API appropriate to root pane user-interface elements. | |
| * <p> | |
| * <strong>Warning:</strong> | |
| * Serialized objects of this class will not be compatible with | |
| * future Swing releases. The current serialization support is | |
| * appropriate for short term storage or RMI between applications running | |
| * the same version of Swing. As of 1.4, support for long term storage | |
| * of all JavaBeans | |
| * has been added to the <code>java.beans</code> package. | |
| * Please see {@link java.beans.XMLEncoder}. | |
| */ | |
| @SuppressWarnings("serial") | |
| protected class AccessibleJRootPane extends AccessibleJComponent { | |
| /** | |
| * Constructs an {@code AccessibleJRootPane}. | |
| */ | |
| protected AccessibleJRootPane() {} | |
| /** | |
| * Get the role of this object. | |
| * | |
| * @return an instance of AccessibleRole describing the role of | |
| * the object | |
| */ | |
| public AccessibleRole getAccessibleRole() { | |
| return AccessibleRole.ROOT_PANE; | |
| } | |
| /** | |
| * Returns the number of accessible children of the object. | |
| * | |
| * @return the number of accessible children of the object. | |
| */ | |
| public int getAccessibleChildrenCount() { | |
| return super.getAccessibleChildrenCount(); | |
| } | |
| /** | |
| * Returns the specified Accessible child of the object. The Accessible | |
| * children of an Accessible object are zero-based, so the first child | |
| * of an Accessible child is at index 0, the second child is at index 1, | |
| * and so on. | |
| * | |
| * @param i zero-based index of child | |
| * @return the Accessible child of the object | |
| * @see #getAccessibleChildrenCount | |
| */ | |
| public Accessible getAccessibleChild(int i) { | |
| return super.getAccessibleChild(i); | |
| } | |
| } // inner class AccessibleJRootPane | |
| } |