home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 19.1 KB | 493 lines |
- /*
- * @(#)JRootPane.java 1.20 98/02/02
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
- package java.awt.swing;
-
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.accessibility.*;
- import java.util.Vector;
- import java.io.Serializable;
-
-
- /** The JRootPane component is made up of several components.
- * In order they are:
- * <PRE>
- * JRootPane
- * glassPane
- * layeredPane
- * [menuBar]
- * contentPane
- * </PRE>
- * The menuBar component is optional and may or may
- * exist at any time. The layeredPane, contentPane, and glassPane will always
- * be available.
- * <p>
- * The <code>contentPane</code> should be the parent of any children of
- * the JRootPane. You would normally do something like this:
- * <PRE>
- * rootPane.add(child);
- * </PRE>
- * Using JRootPane the proper semantic is:
- * <PRE>
- * rootPane.getContentPane().add(child);
- * </PRE>
- * The same priniciple holds true for setting layout managers, removing
- * components, listing children, etc. All these methods should normally
- * be sent to the <code>contentPane</code> instead of to the JRootPane.
- * The <code>contentPane</code> is always non-null. Attempting to set it
- * to null generates an exception. The default <code>contentPane</code>
- * has a BorderLayout manager set on it.
- * <p>
- * If a JMenuBar component is set on the JRootPane, 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.
- * <p>
- * The JMenuBar and the <code>contentPane</code> are added
- * to the <code>layeredPane</code> component at the
- * JLayeredPane.FRAME_CONTENT_LAYER layer.
- * <p>
- * The <code>layeredPane</code> is an instance of the JLayeredPane class.
- * It's purpose is to be the parent of all children of the JRootPane. It
- * provides the ability to add components at several layers. This is very
- * useful when working with menu popups, dialog boxes, or during dragging.
- * Situations where you need to place a component over the top of all
- * other normal components. The <code>layeredPane</code> is always non-null.
- * Attempting to set it to null generates an exception.
- * <p>
- * The <code>glassPane</code> is always added as the first child of the
- * JRootPane. This allows the glass component to get in the way of all
- * mouse events, as well as providing a convient place to draw above all
- * other components. The <code>glassPane</code> is always non-null.
- * Attempting to set it to null generates an exception. Developers should
- * use <code>setVisible</code> on the glassPane to control when the
- * <code>glassPane</code> displays over the other children. By default the
- * <code>glassPane</code> is not visible.
- * <p>
- * The JRootPane uses a custom LayoutManager. This LayoutManager insures
- * the following:
- * <OL>
- * <LI>The <code>glassPane</code>, if present, fills the entire viewable
- * area of the JRootPane (bounds - insets).
- * <LI>The <code>layeredPane</code> fills the entire viewable area of the
- * JRootPane. (bounds - insets)
- * <LI>The <code>menuBar</code> is positioned at the upper edge of the
- * layeredPane().
- * <LI>The <code>contentPane</code> fills the entire viewable area,
- * minus the MenuBar, if present.
- * </OL>
- * Any other views in the JRootPane view hierarchy are ignored.
- * If you replace the LayoutManager of the JRootPane, you are responsible for managing
- * all of these views.
- * <p>
- * Warning: 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 Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- *
- * @see JLayeredPane
- * @see JMenuBar
- * @see JWindow
- * @see JFrame
- * @see JDialog
- *
- * @version 1.20 02/02/98
- * @author David Kloba
- */
- /// PENDING(klobad) Who should be opaque in this component?
- public class JRootPane extends JComponent implements Accessible {
- protected JMenuBar menuBar;
- protected Container contentPane;
- protected JLayeredPane layeredPane;
- protected Component glassPane;
- protected JButton defaultButton;
- protected DefaultAction defaultPressAction;
- protected DefaultAction defaultReleaseAction;
-
- public JRootPane() {
- setGlassPane(createGlassPane());
- setLayeredPane(createLayeredPane());
- setContentPane(createContentPane());
- setLayout(createRootLayout());
- setDoubleBuffered(true);
- setBackground(UIManager.getColor("control"));
- }
-
- /** Called by the constructor methods to create the default layeredPane.
- * Bt default it creates a new JLayeredPane.
- */
- protected JLayeredPane createLayeredPane() {
- JLayeredPane p = new JLayeredPane();
- p.setName(this.getName()+".layeredPane");
- return p;
- }
-
- /** Called by the constructor methods to create the default contentPane.
- * By default this method creates a new JComponent add sets a
- * BorderLayout as its LayoutManager.
- */
- 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 glassPane.
- * By default this method creates a new JComponent with visibility
- * set to false.
- */
- protected Component createGlassPane() {
- JComponent c = new JPanel();
- c.setName(this.getName()+".glassPane");
- c.setVisible(false);
- ((JPanel)c).setOpaque(false);
- return c;
- }
-
- /** Called by the constructor methods to create the default layoutManager. */
- protected LayoutManager createRootLayout() {
- return new RootLayout();
- }
-
- 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);
- }
- public JMenuBar getMenuBar() { return menuBar; }
-
- 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);
- }
- public Container getContentPane() { return contentPane; }
-
- // PENDING(klobad) Should this reparent the contentPane and MenuBar?
- 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);
- }
- public JLayeredPane getLayeredPane() { return layeredPane; }
-
- /**
- * Sets a specified Component 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. For example,
- * only one JInternalFrame is ever active when using a
- * DefaultDesktop, and any inactive JInternalFrames' glass panes
- * are made visible so that clicking anywhere within an inactive
- * JInternalFrame can activate it.
- * @param glass the Component to use as the glass pane for this
- * JRootPane.
- */
- public void setGlassPane(Component glass) {
- if (glass == null) {
- throw new NullPointerException("glassPane cannot be set to null.");
- }
-
- 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 JRootPane.
- * @return the current glass pane.
- */
- public Component getGlassPane() {
- return glassPane;
- }
-
-
- /**
- * Sets the current default button for this JRootPane.
- * The default button is the button which will be activated
- * when a UI-defined activation event (typically the <Enter> key)
- * occurs in the RootPane regardless of whether or not the button
- * has keyboard focus (unless there is another component within
- * the RootPane which consumes the activation event, such as a JTextPane).
- * For default activation to work, the button must be an enabled
- * descendent of the RootPane when activation occurs.
- * To remove a default button from this RootPane, set this
- * property to null.
- *
- * @see JButton#isDefaultButton
- * @param default the default button.
- */
- public void setDefaultButton(JButton defaultButton) {
- JButton oldDefault = this.defaultButton;
-
- this.defaultButton = defaultButton;
- if (defaultPressAction == null) {
- defaultPressAction = new DefaultAction(this, true);
- defaultReleaseAction = new DefaultAction(this, false);
- // Eventually we should get the KeyStroke from the UI
- // but hardcode it for now....
- registerKeyboardAction(defaultPressAction,
- KeyStroke.getKeyStroke('\n', 0, false),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- registerKeyboardAction(defaultReleaseAction,
- KeyStroke.getKeyStroke('\n', 0, true),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- }
- if (oldDefault != defaultButton) {
- defaultPressAction.setOwner(defaultButton);
- defaultReleaseAction.setOwner(defaultButton);
-
- if (oldDefault != null) {
- oldDefault.repaint();
- }
- if (defaultButton != null) {
- defaultButton.repaint();
- }
- }
-
- firePropertyChange("defaultButton", oldDefault, defaultButton);
- }
-
- /**
- * Returns the current default button for this JRootPane.
- * @return the current default button.
- */
- public JButton getDefaultButton() {
- return defaultButton;
- }
-
- static class DefaultAction extends AbstractAction {
- JButton owner;
- JRootPane root;
- boolean press;
- DefaultAction(JRootPane root, boolean press) {
- super(press? "pressedAction" : "releasedAction");
- this.root = root;
- this.press = press;
- }
- public void setOwner(JButton owner) {
- this.owner = owner;
- }
- public void actionPerformed(ActionEvent e) {
- if (owner != null && SwingUtilities.getRootPane(owner) == root) {
- ButtonModel model = owner.getModel();
- if (press) {
- model.setArmed(true);
- model.setPressed(true);
- } else {
- model.setPressed(false);
- }
- }
- }
- public boolean isEnabled() {
- return owner.getModel().isEnabled();
- }
- }
-
-
- /** Overridden to enforce the position of the glass component as the zero child. */
- 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
- ///////////////////////////////////////////////////////////////////////////////
-
-
- /** Responsible for Layout of layeredPane, glassPane, menuBar.
- * <p>
- * Warning: 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 Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class RootLayout implements LayoutManager2, Serializable
- {
-
- public Dimension preferredLayoutSize(Container parent) {
- Dimension rd, mbd;
- Insets i = getInsets();
-
- if(contentPane != null) {
- rd = contentPane.getPreferredSize();
- } else {
- rd = parent.getSize();
- }
- if(menuBar != null) {
- 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);
- }
-
- public Dimension minimumLayoutSize(Container parent) {
- Dimension rd, mbd;
- Insets i = getInsets();
- if(contentPane != null) {
- rd = contentPane.getMinimumSize();
- } else {
- rd = parent.getSize();
- }
- if(menuBar != null) {
- 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);
- }
-
- public Dimension maximumLayoutSize(Container target) {
- Dimension rd, mbd;
- Insets i = getInsets();
- if(menuBar != null) {
- 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.min(rd.width, mbd.width) + i.left + i.right,
- rd.height + mbd.height + i.top + i.bottom);
- }
-
- 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 chilren.
- if(menuBar != null) {
- 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) {}
- }
-
- /////////////////
- // Accessibility support
- ////////////////
-
- /**
- * Get the AccessibleContext associated with this JComponent
- *
- * @return the AccessibleContext of this JComponent
- */
- public AccessibleContext getAccessibleContext() {
- if (accessibleContext == null) {
- accessibleContext = new AccessibleJRootPane();
- }
- return accessibleContext;
- }
-
- /**
- * The class used to obtain the accessible role for this object.
- * <p>
- * Warning: 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 Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class AccessibleJRootPane extends AccessibleJComponent {
- /**
- * Get the role of this object.
- *
- * @return an instance of AccessibleRole describing the role of
- * the object
- */
- public AccessibleRole getAccessibleRole() {
- return AccessibleRole.ROOT_PANE;
- }
- } // inner class AccessibleJRootPane
-
- }
-