Source Code Cross Referenced for JMenu.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.swing;
0027
0028        import java.awt.AWTEvent;
0029        import java.awt.Component;
0030        import java.awt.ComponentOrientation;
0031        import java.awt.Container;
0032        import java.awt.Dimension;
0033        import java.awt.Frame;
0034        import java.awt.Graphics;
0035        import java.awt.GraphicsConfiguration;
0036        import java.awt.GraphicsDevice;
0037        import java.awt.GraphicsEnvironment;
0038        import java.awt.Insets;
0039        import java.awt.Point;
0040        import java.awt.Polygon;
0041        import java.awt.Rectangle;
0042        import java.awt.Toolkit;
0043        import java.awt.event.*;
0044        import java.beans.*;
0045
0046        import java.util.*;
0047
0048        import java.io.Serializable;
0049        import java.io.ObjectOutputStream;
0050        import java.io.ObjectInputStream;
0051        import java.io.IOException;
0052
0053        import javax.swing.event.*;
0054        import javax.swing.plaf.*;
0055        import javax.swing.plaf.basic.*;
0056        import javax.accessibility.*;
0057
0058        import java.lang.ref.WeakReference;
0059
0060        /**
0061         * An implementation of a menu -- a popup window containing
0062         * <code>JMenuItem</code>s that
0063         * is displayed when the user selects an item on the <code>JMenuBar</code>.
0064         * In addition to <code>JMenuItem</code>s, a <code>JMenu</code> can
0065         * also contain <code>JSeparator</code>s. 
0066         * <p>
0067         * In essence, a menu is a button with an associated <code>JPopupMenu</code>.
0068         * When the "button" is pressed, the <code>JPopupMenu</code> appears. If the
0069         * "button" is on the <code>JMenuBar</code>, the menu is a top-level window.
0070         * If the "button" is another menu item, then the <code>JPopupMenu</code> is
0071         * "pull-right" menu.
0072         * <p>
0073         * Menus can be configured, and to some degree controlled, by 
0074         * <code><a href="Action.html">Action</a></code>s.  Using an
0075         * <code>Action</code> with a menu has many benefits beyond directly
0076         * configuring a menu.  Refer to <a href="Action.html#buttonActions">
0077         * Swing Components Supporting <code>Action</code></a> for more
0078         * details, and you can find more information in <a
0079         * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/action.html">How
0080         * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
0081         * <p>
0082         * For information and examples of using menus see
0083         * <a href="http://java.sun.com/doc/books/tutorial/uiswing/components/menu.html">How to Use Menus</a>,
0084         * a section in <em>The Java Tutorial.</em>
0085         * <p>
0086         * <strong>Warning:</strong> Swing is not thread safe. For more
0087         * information see <a
0088         * href="package-summary.html#threading">Swing's Threading
0089         * Policy</a>.
0090         * <p>
0091         * <strong>Warning:</strong>
0092         * Serialized objects of this class will not be compatible with
0093         * future Swing releases. The current serialization support is
0094         * appropriate for short term storage or RMI between applications running
0095         * the same version of Swing.  As of 1.4, support for long term storage
0096         * of all JavaBeans<sup><font size="-2">TM</font></sup>
0097         * has been added to the <code>java.beans</code> package.
0098         * Please see {@link java.beans.XMLEncoder}.
0099         *
0100         * @beaninfo
0101         *   attribute: isContainer true
0102         * description: A popup window containing menu items displayed in a menu bar.
0103         *
0104         * @version 1.187 05/05/07
0105         * @author Georges Saab
0106         * @author David Karlton
0107         * @author Arnaud Weber
0108         * @see JMenuItem
0109         * @see JSeparator
0110         * @see JMenuBar
0111         * @see JPopupMenu
0112         */
0113        public class JMenu extends JMenuItem implements  Accessible, MenuElement {
0114            /**
0115             * @see #getUIClassID
0116             * @see #readObject
0117             */
0118            private static final String uiClassID = "MenuUI";
0119
0120            /*
0121             * The popup menu portion of the menu.
0122             */
0123            private JPopupMenu popupMenu;
0124
0125            /*
0126             * The button's model listeners.  Default is <code>null</code>.
0127             */
0128            private ChangeListener menuChangeListener = null;
0129
0130            /*
0131             * Only one <code>MenuEvent</code> is needed for each menu since the
0132             * event's only state is the source property.  The source of events
0133             * generated is always "this".  Default is <code>null</code>.
0134             */
0135            private MenuEvent menuEvent = null;
0136
0137            /* Registry of listeners created for <code>Action-JMenuItem</code>
0138             * linkage.  This is needed so that references can
0139             * be cleaned up at remove time to allow garbage collection
0140             * Default is <code>null</code>.
0141             */
0142            private static Hashtable listenerRegistry = null;
0143
0144            /*
0145             * Used by the look and feel (L&F) code to handle
0146             * implementation specific menu behaviors.
0147             */
0148            private int delay;
0149
0150            /*
0151             * Location of the popup component. Location is <code>null</code>
0152             * if it was not customized by <code>setMenuLocation</code>
0153             */
0154            private Point customMenuLocation = null;
0155
0156            /* Diagnostic aids -- should be false for production builds. */
0157            private static final boolean TRACE = false; // trace creates and disposes
0158            private static final boolean VERBOSE = false; // show reuse hits/misses
0159            private static final boolean DEBUG = false; // show bad params, misc.
0160
0161            /**
0162             * Constructs a new <code>JMenu</code> with no text.
0163             */
0164            public JMenu() {
0165                this ("");
0166            }
0167
0168            /**
0169             * Constructs a new <code>JMenu</code> with the supplied string
0170             * as its text.
0171             *
0172             * @param s  the text for the menu label
0173             */
0174            public JMenu(String s) {
0175                super (s);
0176            }
0177
0178            /**
0179             * Constructs a menu whose properties are taken from the 
0180             * <code>Action</code> supplied.
0181             * @param a an <code>Action</code>
0182             *
0183             * @since 1.3
0184             */
0185            public JMenu(Action a) {
0186                this ();
0187                setAction(a);
0188            }
0189
0190            /**
0191             * Constructs a new <code>JMenu</code> with the supplied string as
0192             * its text and specified as a tear-off menu or not.
0193             *
0194             * @param s the text for the menu label
0195             * @param b can the menu be torn off (not yet implemented)
0196             */
0197            public JMenu(String s, boolean b) {
0198                this (s);
0199            }
0200
0201            /**
0202             * Overriden to do nothing. We want JMenu to be focusable, but
0203             * <code>JMenuItem</code> doesn't want to be, thus we override this
0204             * do nothing. We don't invoke <code>setFocusable(true)</code> after
0205             * super's constructor has completed as this has the side effect that 
0206             * <code>JMenu</code> will be considered traversable via the
0207             * keyboard, which we don't want. Making a Component traversable by
0208             * the keyboard after invoking <code>setFocusable(true)</code> is OK,
0209             * as <code>setFocusable</code> is new API
0210             * and is speced as such, but internally we don't want to use it like
0211             * this else we change the keyboard traversability.
0212             */
0213            void initFocusability() {
0214            }
0215
0216            /**
0217             * Resets the UI property with a value from the current look and feel.
0218             *
0219             * @see JComponent#updateUI
0220             */
0221            public void updateUI() {
0222                setUI((MenuItemUI) UIManager.getUI(this ));
0223
0224                if (popupMenu != null) {
0225                    popupMenu.setUI((PopupMenuUI) UIManager.getUI(popupMenu));
0226                }
0227
0228            }
0229
0230            /**
0231             * Returns the name of the L&F class that renders this component.
0232             *
0233             * @return the string "MenuUI"
0234             * @see JComponent#getUIClassID
0235             * @see UIDefaults#getUI
0236             */
0237            public String getUIClassID() {
0238                return uiClassID;
0239            }
0240
0241            //    public void repaint(long tm, int x, int y, int width, int height) {
0242            //        Thread.currentThread().dumpStack();
0243            //        super.repaint(tm,x,y,width,height);
0244            //    }
0245
0246            /**
0247             * Sets the data model for the "menu button" -- the label
0248             * that the user clicks to open or close the menu.
0249             *
0250             * @param newModel the <code>ButtonModel</code>
0251             * @see #getModel
0252             * @beaninfo
0253             * description: The menu's model
0254             *       bound: true
0255             *      expert: true
0256             *      hidden: true
0257             */
0258            public void setModel(ButtonModel newModel) {
0259                ButtonModel oldModel = getModel();
0260
0261                super .setModel(newModel);
0262
0263                if (oldModel != null && menuChangeListener != null) {
0264                    oldModel.removeChangeListener(menuChangeListener);
0265                    menuChangeListener = null;
0266                }
0267
0268                model = newModel;
0269
0270                if (newModel != null) {
0271                    menuChangeListener = createMenuChangeListener();
0272                    newModel.addChangeListener(menuChangeListener);
0273                }
0274            }
0275
0276            /**
0277             * Returns true if the menu is currently selected (highlighted).
0278             *
0279             * @return true if the menu is selected, else false
0280             */
0281            public boolean isSelected() {
0282                return getModel().isSelected();
0283            }
0284
0285            /**
0286             * Sets the selection status of the menu.
0287             *
0288             * @param b  true to select (highlight) the menu; false to de-select
0289             *		the menu
0290             * @beaninfo
0291             *      description: When the menu is selected, its popup child is shown.
0292             *           expert: true
0293             *           hidden: true
0294             */
0295            public void setSelected(boolean b) {
0296                ButtonModel model = getModel();
0297                boolean oldValue = model.isSelected();
0298
0299                // TIGER - 4840653
0300                // Removed code which fired an AccessibleState.SELECTED
0301                // PropertyChangeEvent since this resulted in two
0302                // identical events being fired since
0303                // AbstractButton.fireItemStateChanged also fires the
0304                // same event. This caused screen readers to speak the
0305                // name of the item twice.
0306
0307                if (b != model.isSelected()) {
0308                    getModel().setSelected(b);
0309                }
0310            }
0311
0312            /**
0313             * Returns true if the menu's popup window is visible.
0314             *
0315             * @return true if the menu is visible, else false
0316             */
0317            public boolean isPopupMenuVisible() {
0318                ensurePopupMenuCreated();
0319                return popupMenu.isVisible();
0320            }
0321
0322            /**
0323             * Sets the visibility of the menu's popup.  If the menu is
0324             * not enabled, this method will have no effect.
0325             *
0326             * @param b  a boolean value -- true to make the menu visible,
0327             *           false to hide it
0328             * @beaninfo
0329             *      description: The popup menu's visibility
0330             *           expert: true
0331             *           hidden: true
0332             */
0333            public void setPopupMenuVisible(boolean b) {
0334                if (DEBUG) {
0335                    System.out.println("in JMenu.setPopupMenuVisible " + b);
0336                    // Thread.dumpStack();
0337                }
0338
0339                boolean isVisible = isPopupMenuVisible();
0340                if (b != isVisible && (isEnabled() || !b)) {
0341                    ensurePopupMenuCreated();
0342                    if ((b == true) && isShowing()) {
0343                        // Set location of popupMenu (pulldown or pullright)
0344                        Point p = getCustomMenuLocation();
0345                        if (p == null) {
0346                            p = getPopupMenuOrigin();
0347                        }
0348                        getPopupMenu().show(this , p.x, p.y);
0349                    } else {
0350                        getPopupMenu().setVisible(false);
0351                    }
0352                }
0353            }
0354
0355            /**
0356             * Computes the origin for the <code>JMenu</code>'s popup menu.
0357             * This method uses Look and Feel properties named
0358             * <code>Menu.menuPopupOffsetX</code>,
0359             * <code>Menu.menuPopupOffsetY</code>,
0360             * <code>Menu.submenuPopupOffsetX</code>, and
0361             * <code>Menu.submenuPopupOffsetY</code>
0362             * to adjust the exact location of popup.
0363             *
0364             * @return a <code>Point</code> in the coordinate space of the
0365             *		menu which should be used as the origin
0366             * 		of the <code>JMenu</code>'s popup menu
0367             *
0368             * @since 1.3
0369             */
0370            protected Point getPopupMenuOrigin() {
0371                int x = 0;
0372                int y = 0;
0373                JPopupMenu pm = getPopupMenu();
0374                // Figure out the sizes needed to caclulate the menu position
0375                Dimension s = getSize();
0376                Dimension pmSize = pm.getSize();
0377                // For the first time the menu is popped up, 
0378                // the size has not yet been initiated
0379                if (pmSize.width == 0) {
0380                    pmSize = pm.getPreferredSize();
0381                }
0382                Point position = getLocationOnScreen();
0383                Toolkit toolkit = Toolkit.getDefaultToolkit();
0384                GraphicsConfiguration gc = getGraphicsConfiguration();
0385                Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
0386                GraphicsEnvironment ge = GraphicsEnvironment
0387                        .getLocalGraphicsEnvironment();
0388                GraphicsDevice[] gd = ge.getScreenDevices();
0389                for (int i = 0; i < gd.length; i++) {
0390                    if (gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
0391                        GraphicsConfiguration dgc = gd[i]
0392                                .getDefaultConfiguration();
0393                        if (dgc.getBounds().contains(position)) {
0394                            gc = dgc;
0395                            break;
0396                        }
0397                    }
0398                }
0399
0400                if (gc != null) {
0401                    screenBounds = gc.getBounds();
0402                    // take screen insets (e.g. taskbar) into account
0403                    Insets screenInsets = toolkit.getScreenInsets(gc);
0404
0405                    screenBounds.width -= Math.abs(screenInsets.left
0406                            + screenInsets.right);
0407                    screenBounds.height -= Math.abs(screenInsets.top
0408                            + screenInsets.bottom);
0409                    position.x -= Math.abs(screenInsets.left);
0410                    position.y -= Math.abs(screenInsets.top);
0411                }
0412
0413                Container parent = getParent();
0414                if (parent instanceof  JPopupMenu) {
0415                    // We are a submenu (pull-right)
0416                    int xOffset = UIManager.getInt("Menu.submenuPopupOffsetX");
0417                    int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");
0418
0419                    if (SwingUtilities.isLeftToRight(this )) {
0420                        // First determine x:
0421                        x = s.width + xOffset; // Prefer placement to the right
0422                        if (position.x + x + pmSize.width >= screenBounds.width
0423                                + screenBounds.x
0424                                &&
0425                                // popup doesn't fit - place it wherever there's more room
0426                                screenBounds.width - s.width < 2 * (position.x - screenBounds.x)) {
0427
0428                            x = 0 - xOffset - pmSize.width;
0429                        }
0430                    } else {
0431                        // First determine x:
0432                        x = 0 - xOffset - pmSize.width; // Prefer placement to the left
0433                        if (position.x + x < screenBounds.x &&
0434                        // popup doesn't fit - place it wherever there's more room
0435                                screenBounds.width - s.width > 2 * (position.x - screenBounds.x)) {
0436
0437                            x = s.width + xOffset;
0438                        }
0439                    }
0440                    // Then the y:
0441                    y = yOffset; // Prefer dropping down
0442                    if (position.y + y + pmSize.height >= screenBounds.height
0443                            + screenBounds.y
0444                            &&
0445                            // popup doesn't fit - place it wherever there's more room
0446                            screenBounds.height - s.height < 2 * (position.y - screenBounds.y)) {
0447
0448                        y = s.height - yOffset - pmSize.height;
0449                    }
0450                } else {
0451                    // We are a toplevel menu (pull-down)
0452                    int xOffset = UIManager.getInt("Menu.menuPopupOffsetX");
0453                    int yOffset = UIManager.getInt("Menu.menuPopupOffsetY");
0454
0455                    if (SwingUtilities.isLeftToRight(this )) {
0456                        // First determine the x:
0457                        x = xOffset; // Extend to the right
0458                        if (position.x + x + pmSize.width >= screenBounds.width
0459                                + screenBounds.x
0460                                &&
0461                                // popup doesn't fit - place it wherever there's more room
0462                                screenBounds.width - s.width < 2 * (position.x - screenBounds.x)) {
0463
0464                            x = s.width - xOffset - pmSize.width;
0465                        }
0466                    } else {
0467                        // First determine the x:
0468                        x = s.width - xOffset - pmSize.width; // Extend to the left
0469                        if (position.x + x < screenBounds.x &&
0470                        // popup doesn't fit - place it wherever there's more room
0471                                screenBounds.width - s.width > 2 * (position.x - screenBounds.x)) {
0472
0473                            x = xOffset;
0474                        }
0475                    }
0476                    // Then the y:
0477                    y = s.height + yOffset; // Prefer dropping down
0478                    if (position.y + y + pmSize.height >= screenBounds.height &&
0479                    // popup doesn't fit - place it wherever there's more room
0480                            screenBounds.height - s.height < 2 * (position.y - screenBounds.y)) {
0481
0482                        y = 0 - yOffset - pmSize.height; // Otherwise drop 'up'
0483                    }
0484                }
0485                return new Point(x, y);
0486            }
0487
0488            /**
0489             * Returns the suggested delay, in milliseconds, before submenus
0490             * are popped up or down.  
0491             * Each look and feel (L&F) may determine its own policy for
0492             * observing the <code>delay</code> property.
0493             * In most cases, the delay is not observed for top level menus
0494             * or while dragging.  The default for <code>delay</code> is 0.
0495             * This method is a property of the look and feel code and is used
0496             * to manage the idiosyncracies of the various UI implementations.
0497             *
0498             *
0499             * @return the <code>delay</code> property
0500             */
0501            public int getDelay() {
0502                return delay;
0503            }
0504
0505            /**
0506             * Sets the suggested delay before the menu's <code>PopupMenu</code>
0507             * is popped up or down.  Each look and feel (L&F) may determine
0508             * it's own policy for observing the delay property.  In most cases,
0509             * the delay is not observed for top level menus or while dragging.
0510             * This method is a property of the look and feel code and is used
0511             * to manage the idiosyncracies of the various UI implementations.
0512             *
0513             * @param       d the number of milliseconds to delay
0514             * @exception   IllegalArgumentException if <code>d</code> 
0515             *                       is less than 0
0516             * @beaninfo
0517             *      description: The delay between menu selection and making the popup menu visible
0518             *           expert: true
0519             */
0520            public void setDelay(int d) {
0521                if (d < 0)
0522                    throw new IllegalArgumentException(
0523                            "Delay must be a positive integer");
0524
0525                delay = d;
0526            }
0527
0528            /**
0529             * The window-closing listener for the popup.
0530             *
0531             * @see WinListener
0532             */
0533            protected WinListener popupListener;
0534
0535            private void ensurePopupMenuCreated() {
0536                if (popupMenu == null) {
0537                    final JMenu this Menu = this ;
0538                    this .popupMenu = new JPopupMenu();
0539                    popupMenu.setInvoker(this );
0540                    popupListener = createWinListener(popupMenu);
0541                }
0542            }
0543
0544            /*
0545             * Return the customized location of the popup component.
0546             */
0547            private Point getCustomMenuLocation() {
0548                return customMenuLocation;
0549            }
0550
0551            /**
0552             * Sets the location of the popup component.
0553             *
0554             * @param x the x coordinate of the popup's new position
0555             * @param y the y coordinate of the popup's new position
0556             */
0557            public void setMenuLocation(int x, int y) {
0558                customMenuLocation = new Point(x, y);
0559                if (popupMenu != null)
0560                    popupMenu.setLocation(x, y);
0561            }
0562
0563            /**
0564             * Appends a menu item to the end of this menu. 
0565             * Returns the menu item added.
0566             *
0567             * @param menuItem the <code>JMenuitem</code> to be added
0568             * @return the <code>JMenuItem</code> added
0569             */
0570            public JMenuItem add(JMenuItem menuItem) {
0571                ensurePopupMenuCreated();
0572                return popupMenu.add(menuItem);
0573            }
0574
0575            /**
0576             * Appends a component to the end of this menu.
0577             * Returns the component added.
0578             *
0579             * @param c the <code>Component</code> to add
0580             * @return the <code>Component</code> added
0581             */
0582            public Component add(Component c) {
0583                ensurePopupMenuCreated();
0584                popupMenu.add(c);
0585                return c;
0586            }
0587
0588            /** 
0589             * Adds the specified component to this container at the given 
0590             * position. If <code>index</code> equals -1, the component will
0591             * be appended to the end.
0592             * @param     c   the <code>Component</code> to add
0593             * @param     index    the position at which to insert the component
0594             * @return    the <code>Component</code> added
0595             * @see	  #remove
0596             * @see java.awt.Container#add(Component, int)
0597             */
0598            public Component add(Component c, int index) {
0599                ensurePopupMenuCreated();
0600                popupMenu.add(c, index);
0601                return c;
0602            }
0603
0604            /**
0605             * Creates a new menu item with the specified text and appends
0606             * it to the end of this menu.
0607             *  
0608             * @param s the string for the menu item to be added
0609             */
0610            public JMenuItem add(String s) {
0611                return add(new JMenuItem(s));
0612            }
0613
0614            /**
0615             * Creates a new menu item attached to the specified 
0616             * <code>Action</code> object and appends it to the end of this menu.
0617             *
0618             * @param a the <code>Action</code> for the menu item to be added
0619             * @see Action
0620             */
0621            public JMenuItem add(Action a) {
0622                JMenuItem mi = createActionComponent(a);
0623                mi.setAction(a);
0624                add(mi);
0625                return mi;
0626            }
0627
0628            /**
0629             * Factory method which creates the <code>JMenuItem</code> for 
0630             * <code>Action</code>s added to the <code>JMenu</code>.
0631             *
0632             * @param a the <code>Action</code> for the menu item to be added
0633             * @return the new menu item
0634             * @see Action
0635             *
0636             * @since 1.3
0637             */
0638            protected JMenuItem createActionComponent(Action a) {
0639                JMenuItem mi = new JMenuItem() {
0640                    protected PropertyChangeListener createActionPropertyChangeListener(
0641                            Action a) {
0642                        PropertyChangeListener pcl = createActionChangeListener(this );
0643                        if (pcl == null) {
0644                            pcl = super .createActionPropertyChangeListener(a);
0645                        }
0646                        return pcl;
0647                    }
0648                };
0649                mi.setHorizontalTextPosition(JButton.TRAILING);
0650                mi.setVerticalTextPosition(JButton.CENTER);
0651                return mi;
0652            }
0653
0654            /**
0655             * Returns a properly configured <code>PropertyChangeListener</code>
0656             * which updates the control as changes to the <code>Action</code> occur. 
0657             */
0658            protected PropertyChangeListener createActionChangeListener(
0659                    JMenuItem b) {
0660                return b.createActionPropertyChangeListener0(b.getAction());
0661            }
0662
0663            /**
0664             * Appends a new separator to the end of the menu.
0665             */
0666            public void addSeparator() {
0667                ensurePopupMenuCreated();
0668                popupMenu.addSeparator();
0669            }
0670
0671            /**
0672             * Inserts a new menu item with the specified text at a 
0673             * given position.
0674             *
0675             * @param s the text for the menu item to add
0676             * @param pos an integer specifying the position at which to add the 
0677             *               new menu item
0678             * @exception IllegalArgumentException when the value of 
0679             *			<code>pos</code> < 0
0680             */
0681            public void insert(String s, int pos) {
0682                if (pos < 0) {
0683                    throw new IllegalArgumentException("index less than zero.");
0684                }
0685
0686                ensurePopupMenuCreated();
0687                popupMenu.insert(new JMenuItem(s), pos);
0688            }
0689
0690            /**
0691             * Inserts the specified <code>JMenuitem</code> at a given position.
0692             *
0693             * @param mi the <code>JMenuitem</code> to add
0694             * @param pos an integer specifying the position at which to add the 
0695             *               new <code>JMenuitem</code>
0696             * @return the new menu item
0697             * @exception IllegalArgumentException if the value of 
0698             *			<code>pos</code> < 0
0699             */
0700            public JMenuItem insert(JMenuItem mi, int pos) {
0701                if (pos < 0) {
0702                    throw new IllegalArgumentException("index less than zero.");
0703                }
0704                ensurePopupMenuCreated();
0705                popupMenu.insert(mi, pos);
0706                return mi;
0707            }
0708
0709            /**
0710             * Inserts a new menu item attached to the specified <code>Action</code> 
0711             * object at a given position.
0712             *
0713             * @param a the <code>Action</code> object for the menu item to add
0714             * @param pos an integer specifying the position at which to add the 
0715             *               new menu item
0716             * @exception IllegalArgumentException if the value of 
0717             *			<code>pos</code> < 0
0718             */
0719            public JMenuItem insert(Action a, int pos) {
0720                if (pos < 0) {
0721                    throw new IllegalArgumentException("index less than zero.");
0722                }
0723
0724                ensurePopupMenuCreated();
0725                JMenuItem mi = new JMenuItem(a);
0726                mi.setHorizontalTextPosition(JButton.TRAILING);
0727                mi.setVerticalTextPosition(JButton.CENTER);
0728                popupMenu.insert(mi, pos);
0729                return mi;
0730            }
0731
0732            /**
0733             * Inserts a separator at the specified position.
0734             *
0735             * @param       index an integer specifying the position at which to 
0736             *                    insert the menu separator
0737             * @exception   IllegalArgumentException if the value of 
0738             *                       <code>index</code> < 0
0739             */
0740            public void insertSeparator(int index) {
0741                if (index < 0) {
0742                    throw new IllegalArgumentException("index less than zero.");
0743                }
0744
0745                ensurePopupMenuCreated();
0746                popupMenu.insert(new JPopupMenu.Separator(), index);
0747            }
0748
0749            /** 
0750             * Returns the <code>JMenuItem</code> at the specified position.
0751             * If the component at <code>pos</code> is not a menu item,
0752             * <code>null</code> is returned.
0753             * This method is included for AWT compatibility.
0754             *
0755             * @param pos    an integer specifying the position
0756             * @exception   IllegalArgumentException if the value of 
0757             *                       <code>pos</code> < 0
0758             * @return  the menu item at the specified position; or <code>null</code>
0759             *		if the item as the specified position is not a menu item
0760             */
0761            public JMenuItem getItem(int pos) {
0762                if (pos < 0) {
0763                    throw new IllegalArgumentException("index less than zero.");
0764                }
0765
0766                Component c = getMenuComponent(pos);
0767                if (c instanceof  JMenuItem) {
0768                    JMenuItem mi = (JMenuItem) c;
0769                    return mi;
0770                }
0771
0772                // 4173633
0773                return null;
0774            }
0775
0776            /**
0777             * Returns the number of items on the menu, including separators.
0778             * This method is included for AWT compatibility.
0779             *
0780             * @return an integer equal to the number of items on the menu
0781             * @see #getMenuComponentCount
0782             */
0783            public int getItemCount() {
0784                return getMenuComponentCount();
0785            }
0786
0787            /**
0788             * Returns true if the menu can be torn off.  This method is not
0789             * yet implemented.
0790             *
0791             * @return true if the menu can be torn off, else false
0792             * @exception  Error  if invoked -- this method is not yet implemented
0793             */
0794            public boolean isTearOff() {
0795                throw new Error("boolean isTearOff() {} not yet implemented");
0796            }
0797
0798            /**
0799             * Removes the specified menu item from this menu.  If there is no
0800             * popup menu, this method will have no effect.
0801             *
0802             * @param    item the <code>JMenuItem</code> to be removed from the menu
0803             */
0804            public void remove(JMenuItem item) {
0805                if (popupMenu != null)
0806                    popupMenu.remove(item);
0807            }
0808
0809            /**
0810             * Removes the menu item at the specified index from this menu.
0811             *
0812             * @param       pos the position of the item to be removed
0813             * @exception   IllegalArgumentException if the value of 
0814             *                       <code>pos</code> < 0, or if <code>pos</code>
0815             *			     is greater than the number of menu items
0816             */
0817            public void remove(int pos) {
0818                if (pos < 0) {
0819                    throw new IllegalArgumentException("index less than zero.");
0820                }
0821                if (pos > getItemCount()) {
0822                    throw new IllegalArgumentException(
0823                            "index greater than the number of items.");
0824                }
0825                if (popupMenu != null)
0826                    popupMenu.remove(pos);
0827            }
0828
0829            /**
0830             * Removes the component <code>c</code> from this menu.
0831             *
0832             * @param       c the component to be removed
0833             */
0834            public void remove(Component c) {
0835                if (popupMenu != null)
0836                    popupMenu.remove(c);
0837            }
0838
0839            /**
0840             * Removes all menu items from this menu.
0841             */
0842            public void removeAll() {
0843                if (popupMenu != null)
0844                    popupMenu.removeAll();
0845            }
0846
0847            /**
0848             * Returns the number of components on the menu.
0849             *
0850             * @return an integer containing the number of components on the menu
0851             */
0852            public int getMenuComponentCount() {
0853                int componentCount = 0;
0854                if (popupMenu != null)
0855                    componentCount = popupMenu.getComponentCount();
0856                return componentCount;
0857            }
0858
0859            /**
0860             * Returns the component at position <code>n</code>.
0861             *
0862             * @param n the position of the component to be returned
0863             * @return the component requested, or <code>null</code>
0864             *			if there is no popup menu
0865             *
0866             */
0867            public Component getMenuComponent(int n) {
0868                if (popupMenu != null)
0869                    return popupMenu.getComponent(n);
0870
0871                return null;
0872            }
0873
0874            /**
0875             * Returns an array of <code>Component</code>s of the menu's
0876             * subcomponents.  Note that this returns all <code>Component</code>s
0877             * in the popup menu, including separators.
0878             *
0879             * @return an array of <code>Component</code>s or an empty array
0880             *		if there is no popup menu
0881             */
0882            public Component[] getMenuComponents() {
0883                if (popupMenu != null)
0884                    return popupMenu.getComponents();
0885
0886                return new Component[0];
0887            }
0888
0889            /**
0890             * Returns true if the menu is a 'top-level menu', that is, if it is
0891             * the direct child of a menubar.
0892             *
0893             * @return true if the menu is activated from the menu bar;
0894             *         false if the menu is activated from a menu item
0895             *         on another menu
0896             */
0897            public boolean isTopLevelMenu() {
0898                if (getParent() instanceof  JMenuBar)
0899                    return true;
0900
0901                return false;
0902            }
0903
0904            /**
0905             * Returns true if the specified component exists in the 
0906             * submenu hierarchy.
0907             *
0908             * @param c the <code>Component</code> to be tested
0909             * @return true if the <code>Component</code> exists, false otherwise
0910             */
0911            public boolean isMenuComponent(Component c) {
0912                // Are we in the MenuItem part of the menu
0913                if (c == this )
0914                    return true;
0915                // Are we in the PopupMenu?
0916                if (c instanceof  JPopupMenu) {
0917                    JPopupMenu comp = (JPopupMenu) c;
0918                    if (comp == this .getPopupMenu())
0919                        return true;
0920                }
0921                // Are we in a Component on the PopupMenu
0922                int ncomponents = this .getMenuComponentCount();
0923                Component[] component = this .getMenuComponents();
0924                for (int i = 0; i < ncomponents; i++) {
0925                    Component comp = component[i];
0926                    // Are we in the current component?
0927                    if (comp == c)
0928                        return true;
0929                    // Hmmm, what about Non-menu containers?
0930
0931                    // Recursive call for the Menu case
0932                    if (comp instanceof  JMenu) {
0933                        JMenu subMenu = (JMenu) comp;
0934                        if (subMenu.isMenuComponent(c))
0935                            return true;
0936                    }
0937                }
0938                return false;
0939            }
0940
0941            /*
0942             * Returns a point in the coordinate space of this menu's popupmenu
0943             * which corresponds to the point <code>p</code> in the menu's
0944             * coordinate space.
0945             *
0946             * @param p the point to be translated
0947             * @return the point in the coordinate space of this menu's popupmenu
0948             */
0949            private Point translateToPopupMenu(Point p) {
0950                return translateToPopupMenu(p.x, p.y);
0951            }
0952
0953            /*
0954             * Returns a point in the coordinate space of this menu's popupmenu
0955             * which corresponds to the point (x,y) in the menu's coordinate space.
0956             *
0957             * @param x the x coordinate of the point to be translated
0958             * @param y the y coordinate of the point to be translated
0959             * @return the point in the coordinate space of this menu's popupmenu
0960             */
0961            private Point translateToPopupMenu(int x, int y) {
0962                int newX;
0963                int newY;
0964
0965                if (getParent() instanceof  JPopupMenu) {
0966                    newX = x - getSize().width;
0967                    newY = y;
0968                } else {
0969                    newX = x;
0970                    newY = y - getSize().height;
0971                }
0972
0973                return new Point(newX, newY);
0974            }
0975
0976            /**
0977             * Returns the popupmenu associated with this menu.  If there is
0978             * no popupmenu, it will create one.
0979             */
0980            public JPopupMenu getPopupMenu() {
0981                ensurePopupMenuCreated();
0982                return popupMenu;
0983            }
0984
0985            /**
0986             * Adds a listener for menu events.
0987             *
0988             * @param l the listener to be added
0989             */
0990            public void addMenuListener(MenuListener l) {
0991                listenerList.add(MenuListener.class, l);
0992            }
0993
0994            /**
0995             * Removes a listener for menu events.
0996             *
0997             * @param l the listener to be removed
0998             */
0999            public void removeMenuListener(MenuListener l) {
1000                listenerList.remove(MenuListener.class, l);
1001            }
1002
1003            /**
1004             * Returns an array of all the <code>MenuListener</code>s added
1005             * to this JMenu with addMenuListener().
1006             *
1007             * @return all of the <code>MenuListener</code>s added or an empty
1008             *         array if no listeners have been added
1009             * @since 1.4
1010             */
1011            public MenuListener[] getMenuListeners() {
1012                return (MenuListener[]) listenerList
1013                        .getListeners(MenuListener.class);
1014            }
1015
1016            /**
1017             * Notifies all listeners that have registered interest for
1018             * notification on this event type.  The event instance 
1019             * is created lazily.
1020             *
1021             * @exception Error  if there is a <code>null</code> listener
1022             * @see EventListenerList
1023             */
1024            protected void fireMenuSelected() {
1025                if (DEBUG) {
1026                    System.out.println("In JMenu.fireMenuSelected");
1027                }
1028                // Guaranteed to return a non-null array
1029                Object[] listeners = listenerList.getListenerList();
1030                // Process the listeners last to first, notifying
1031                // those that are interested in this event
1032                for (int i = listeners.length - 2; i >= 0; i -= 2) {
1033                    if (listeners[i] == MenuListener.class) {
1034                        if (listeners[i + 1] == null) {
1035                            throw new Error(getText()
1036                                    + " has a NULL Listener!! " + i);
1037                        } else {
1038                            // Lazily create the event:
1039                            if (menuEvent == null)
1040                                menuEvent = new MenuEvent(this );
1041                            ((MenuListener) listeners[i + 1])
1042                                    .menuSelected(menuEvent);
1043                        }
1044                    }
1045                }
1046            }
1047
1048            /**
1049             * Notifies all listeners that have registered interest for
1050             * notification on this event type.  The event instance 
1051             * is created lazily.
1052             *
1053             * @exception Error if there is a <code>null</code> listener
1054             * @see EventListenerList
1055             */
1056            protected void fireMenuDeselected() {
1057                if (DEBUG) {
1058                    System.out.println("In JMenu.fireMenuDeselected");
1059                }
1060                // Guaranteed to return a non-null array
1061                Object[] listeners = listenerList.getListenerList();
1062                // Process the listeners last to first, notifying
1063                // those that are interested in this event
1064                for (int i = listeners.length - 2; i >= 0; i -= 2) {
1065                    if (listeners[i] == MenuListener.class) {
1066                        if (listeners[i + 1] == null) {
1067                            throw new Error(getText()
1068                                    + " has a NULL Listener!! " + i);
1069                        } else {
1070                            // Lazily create the event:
1071                            if (menuEvent == null)
1072                                menuEvent = new MenuEvent(this );
1073                            ((MenuListener) listeners[i + 1])
1074                                    .menuDeselected(menuEvent);
1075                        }
1076                    }
1077                }
1078            }
1079
1080            /**
1081             * Notifies all listeners that have registered interest for
1082             * notification on this event type.  The event instance 
1083             * is created lazily.
1084             *
1085             * @exception Error if there is a <code>null</code> listener
1086             * @see EventListenerList
1087             */
1088            protected void fireMenuCanceled() {
1089                if (DEBUG) {
1090                    System.out.println("In JMenu.fireMenuCanceled");
1091                }
1092                // Guaranteed to return a non-null array
1093                Object[] listeners = listenerList.getListenerList();
1094                // Process the listeners last to first, notifying
1095                // those that are interested in this event
1096                for (int i = listeners.length - 2; i >= 0; i -= 2) {
1097                    if (listeners[i] == MenuListener.class) {
1098                        if (listeners[i + 1] == null) {
1099                            throw new Error(getText()
1100                                    + " has a NULL Listener!! " + i);
1101                        } else {
1102                            // Lazily create the event:
1103                            if (menuEvent == null)
1104                                menuEvent = new MenuEvent(this );
1105                            ((MenuListener) listeners[i + 1])
1106                                    .menuCanceled(menuEvent);
1107                        }
1108                    }
1109                }
1110            }
1111
1112            // Overriden to do nothing, JMenu doesn't support an accelerator
1113            void configureAcceleratorFromAction(Action a) {
1114            }
1115
1116            class MenuChangeListener implements  ChangeListener, Serializable {
1117                boolean isSelected = false;
1118
1119                public void stateChanged(ChangeEvent e) {
1120                    ButtonModel model = (ButtonModel) e.getSource();
1121                    boolean modelSelected = model.isSelected();
1122
1123                    if (modelSelected != isSelected) {
1124                        if (modelSelected == true) {
1125                            fireMenuSelected();
1126                        } else {
1127                            fireMenuDeselected();
1128                        }
1129                        isSelected = modelSelected;
1130                    }
1131                }
1132            }
1133
1134            private ChangeListener createMenuChangeListener() {
1135                return new MenuChangeListener();
1136            }
1137
1138            /**
1139             * Creates a window-closing listener for the popup.
1140             *
1141             * @param p the <code>JPopupMenu</code>
1142             * @return the new window-closing listener
1143             *
1144             * @see WinListener
1145             */
1146            protected WinListener createWinListener(JPopupMenu p) {
1147                return new WinListener(p);
1148            }
1149
1150            /**
1151             * A listener class that watches for a popup window closing.
1152             * When the popup is closing, the listener deselects the menu.
1153             * <p>
1154             * <strong>Warning:</strong>
1155             * Serialized objects of this class will not be compatible with
1156             * future Swing releases. The current serialization support is
1157             * appropriate for short term storage or RMI between applications running
1158             * the same version of Swing.  As of 1.4, support for long term storage
1159             * of all JavaBeans<sup><font size="-2">TM</font></sup>
1160             * has been added to the <code>java.beans</code> package.
1161             * Please see {@link java.beans.XMLEncoder}.
1162             */
1163            protected class WinListener extends WindowAdapter implements 
1164                    Serializable {
1165                JPopupMenu popupMenu;
1166
1167                /**
1168                 *  Create the window listener for the specified popup.
1169                 * @since 1.4
1170                 */
1171                public WinListener(JPopupMenu p) {
1172                    this .popupMenu = p;
1173                }
1174
1175                /**
1176                 * Deselect the menu when the popup is closed from outside.
1177                 */
1178                public void windowClosing(WindowEvent e) {
1179                    setSelected(false);
1180                }
1181            }
1182
1183            /**
1184             * Messaged when the menubar selection changes to activate or
1185             * deactivate this menu.
1186             * Overrides <code>JMenuItem.menuSelectionChanged</code>.
1187             *
1188             * @param isIncluded  true if this menu is active, false if
1189             *        it is not
1190             */
1191            public void menuSelectionChanged(boolean isIncluded) {
1192                if (DEBUG) {
1193                    System.out.println("In JMenu.menuSelectionChanged to "
1194                            + isIncluded);
1195                }
1196                setSelected(isIncluded);
1197            }
1198
1199            /**
1200             * Returns an array of <code>MenuElement</code>s containing the submenu 
1201             * for this menu component.  If popup menu is <code>null</code> returns
1202             * an empty array.  This method is required to conform to the
1203             * <code>MenuElement</code> interface.  Note that since
1204             * <code>JSeparator</code>s do not conform to the <code>MenuElement</code>
1205             * interface, this array will only contain <code>JMenuItem</code>s.
1206             *
1207             * @return an array of <code>MenuElement</code> objects
1208             */
1209            public MenuElement[] getSubElements() {
1210                if (popupMenu == null)
1211                    return new MenuElement[0];
1212                else {
1213                    MenuElement result[] = new MenuElement[1];
1214                    result[0] = popupMenu;
1215                    return result;
1216                }
1217            }
1218
1219            // implements javax.swing.MenuElement
1220            /**
1221             * Returns the <code>java.awt.Component</code> used to 
1222             * paint this <code>MenuElement</code>.
1223             * The returned component is used to convert events and detect if
1224             * an event is inside a menu component.
1225             */
1226            public Component getComponent() {
1227                return this ;
1228            }
1229
1230            /**
1231             * Sets the <code>ComponentOrientation</code> property of this menu
1232             * and all components contained within it. This includes all 
1233             * components returned by {@link #getMenuComponents getMenuComponents}.
1234             *
1235             * @param o the new component orientation of this menu and
1236             *        the components contained within it.
1237             * @exception NullPointerException if <code>orientation</code> is null.
1238             * @see java.awt.Component#setComponentOrientation
1239             * @see java.awt.Component#getComponentOrientation
1240             * @since 1.4
1241             */
1242            public void applyComponentOrientation(ComponentOrientation o) {
1243                super .applyComponentOrientation(o);
1244
1245                if (popupMenu != null) {
1246                    int ncomponents = getMenuComponentCount();
1247                    for (int i = 0; i < ncomponents; ++i) {
1248                        getMenuComponent(i).applyComponentOrientation(o);
1249                    }
1250                    popupMenu.setComponentOrientation(o);
1251                }
1252            }
1253
1254            public void setComponentOrientation(ComponentOrientation o) {
1255                super .setComponentOrientation(o);
1256                if (popupMenu != null) {
1257                    popupMenu.setComponentOrientation(o);
1258                }
1259            }
1260
1261            /** 
1262             * <code>setAccelerator</code> is not defined for <code>JMenu</code>.
1263             * Use <code>setMnemonic</code> instead. 
1264             * @param keyStroke  the keystroke combination which will invoke
1265             *			the <code>JMenuItem</code>'s actionlisteners
1266             *			without navigating the menu hierarchy
1267             * @exception Error  if invoked -- this method is not defined for JMenu.
1268             *			Use <code>setMnemonic</code> instead
1269             *
1270             * @beaninfo
1271             *     description: The keystroke combination which will invoke the JMenuItem's
1272             *                  actionlisteners without navigating the menu hierarchy
1273             *          hidden: true
1274             */
1275            public void setAccelerator(KeyStroke keyStroke) {
1276                throw new Error(
1277                        "setAccelerator() is not defined for JMenu.  Use setMnemonic() instead.");
1278            }
1279
1280            /**
1281             * Processes key stroke events such as mnemonics and accelerators.
1282             *
1283             * @param evt  the key event to be processed
1284             */
1285            protected void processKeyEvent(KeyEvent evt) {
1286                MenuSelectionManager.defaultManager().processKeyEvent(evt);
1287                if (evt.isConsumed())
1288                    return;
1289
1290                super .processKeyEvent(evt);
1291            }
1292
1293            /**
1294             * Programmatically performs a "click".  This overrides the method
1295             * <code>AbstractButton.doClick</code> in order to make the menu pop up.
1296             * @param pressTime  indicates the number of milliseconds the
1297             *		button was pressed for
1298             */
1299            public void doClick(int pressTime) {
1300                MenuElement me[] = buildMenuElementArray(this );
1301                MenuSelectionManager.defaultManager().setSelectedPath(me);
1302            }
1303
1304            /*
1305             * Build an array of menu elements - from <code>PopupMenu</code> to 
1306             * the root <code>JMenuBar</code>.
1307             * @param  leaf  the leaf node from which to start building up the array
1308             * @return the array of menu items
1309             */
1310            private MenuElement[] buildMenuElementArray(JMenu leaf) {
1311                Vector elements = new Vector();
1312                Component current = leaf.getPopupMenu();
1313                JPopupMenu pop;
1314                JMenu menu;
1315                JMenuBar bar;
1316
1317                while (true) {
1318                    if (current instanceof  JPopupMenu) {
1319                        pop = (JPopupMenu) current;
1320                        elements.insertElementAt(pop, 0);
1321                        current = pop.getInvoker();
1322                    } else if (current instanceof  JMenu) {
1323                        menu = (JMenu) current;
1324                        elements.insertElementAt(menu, 0);
1325                        current = menu.getParent();
1326                    } else if (current instanceof  JMenuBar) {
1327                        bar = (JMenuBar) current;
1328                        elements.insertElementAt(bar, 0);
1329                        MenuElement me[] = new MenuElement[elements.size()];
1330                        elements.copyInto(me);
1331                        return me;
1332                    }
1333                }
1334            }
1335
1336            /** 
1337             * See <code>readObject</code> and <code>writeObject</code> in
1338             * <code>JComponent</code> for more 
1339             * information about serialization in Swing.
1340             */
1341            private void writeObject(ObjectOutputStream s) throws IOException {
1342                s.defaultWriteObject();
1343                if (getUIClassID().equals(uiClassID)) {
1344                    byte count = JComponent.getWriteObjCounter(this );
1345                    JComponent.setWriteObjCounter(this , --count);
1346                    if (count == 0 && ui != null) {
1347                        ui.installUI(this );
1348                    }
1349                }
1350            }
1351
1352            /**
1353             * Returns a string representation of this <code>JMenu</code>. This 
1354             * method is intended to be used only for debugging purposes, and the 
1355             * content and format of the returned string may vary between      
1356             * implementations. The returned string may be empty but may not 
1357             * be <code>null</code>.
1358             * 
1359             * @return  a string representation of this JMenu.
1360             */
1361            protected String paramString() {
1362                return super .paramString();
1363            }
1364
1365            /////////////////
1366            // Accessibility support
1367            ////////////////
1368
1369            /**
1370             * Gets the AccessibleContext associated with this JMenu. 
1371             * For JMenus, the AccessibleContext takes the form of an 
1372             * AccessibleJMenu. 
1373             * A new AccessibleJMenu instance is created if necessary.
1374             *
1375             * @return an AccessibleJMenu that serves as the 
1376             *         AccessibleContext of this JMenu
1377             */
1378            public AccessibleContext getAccessibleContext() {
1379                if (accessibleContext == null) {
1380                    accessibleContext = new AccessibleJMenu();
1381                }
1382                return accessibleContext;
1383            }
1384
1385            /**
1386             * This class implements accessibility support for the 
1387             * <code>JMenu</code> class.  It provides an implementation of the 
1388             * Java Accessibility API appropriate to menu user-interface elements.
1389             * <p>
1390             * <strong>Warning:</strong>
1391             * Serialized objects of this class will not be compatible with
1392             * future Swing releases. The current serialization support is
1393             * appropriate for short term storage or RMI between applications running
1394             * the same version of Swing.  As of 1.4, support for long term storage
1395             * of all JavaBeans<sup><font size="-2">TM</font></sup>
1396             * has been added to the <code>java.beans</code> package.
1397             * Please see {@link java.beans.XMLEncoder}.
1398             */
1399            protected class AccessibleJMenu extends AccessibleJMenuItem
1400                    implements  AccessibleSelection {
1401
1402                /**
1403                 * Returns the number of accessible children in the object.  If all
1404                 * of the children of this object implement Accessible, than this
1405                 * method should return the number of children of this object.
1406                 *
1407                 * @return the number of accessible children in the object.
1408                 */
1409                public int getAccessibleChildrenCount() {
1410                    Component[] children = getMenuComponents();
1411                    int count = 0;
1412                    for (int j = 0; j < children.length; j++) {
1413                        if (children[j] instanceof  Accessible) {
1414                            count++;
1415                        }
1416                    }
1417                    return count;
1418                }
1419
1420                /**
1421                 * Returns the nth Accessible child of the object.  
1422                 *
1423                 * @param i zero-based index of child
1424                 * @return the nth Accessible child of the object
1425                 */
1426                public Accessible getAccessibleChild(int i) {
1427                    Component[] children = getMenuComponents();
1428                    int count = 0;
1429                    for (int j = 0; j < children.length; j++) {
1430                        if (children[j] instanceof  Accessible) {
1431                            if (count == i) {
1432                                if (children[j] instanceof  JComponent) {
1433                                    // FIXME:  [[[WDW - probably should set this when
1434                                    // the component is added to the menu.  I tried
1435                                    // to do this in most cases, but the separators
1436                                    // added by addSeparator are hard to get to.]]]
1437                                    AccessibleContext ac = ((Accessible) children[j])
1438                                            .getAccessibleContext();
1439                                    ac.setAccessibleParent(JMenu.this );
1440                                }
1441                                return (Accessible) children[j];
1442                            } else {
1443                                count++;
1444                            }
1445                        }
1446                    }
1447                    return null;
1448                }
1449
1450                /**
1451                 * Get the role of this object.
1452                 *
1453                 * @return an instance of AccessibleRole describing the role of the 
1454                 * object
1455                 * @see AccessibleRole
1456                 */
1457                public AccessibleRole getAccessibleRole() {
1458                    return AccessibleRole.MENU;
1459                }
1460
1461                /**
1462                 * Get the AccessibleSelection associated with this object.  In the
1463                 * implementation of the Java Accessibility API for this class, 
1464                 * return this object, which is responsible for implementing the
1465                 * AccessibleSelection interface on behalf of itself.
1466                 * 
1467                 * @return this object
1468                 */
1469                public AccessibleSelection getAccessibleSelection() {
1470                    return this ;
1471                }
1472
1473                /**
1474                 * Returns 1 if a sub-menu is currently selected in this menu.
1475                 *
1476                 * @return 1 if a menu is currently selected, else 0
1477                 */
1478                public int getAccessibleSelectionCount() {
1479                    MenuElement me[] = MenuSelectionManager.defaultManager()
1480                            .getSelectedPath();
1481                    if (me != null) {
1482                        for (int i = 0; i < me.length; i++) {
1483                            if (me[i] == JMenu.this ) { // this menu is selected
1484                                if (i + 1 < me.length) {
1485                                    return 1;
1486                                }
1487                            }
1488                        }
1489                    }
1490                    return 0;
1491                }
1492
1493                /**
1494                 * Returns the currently selected sub-menu if one is selected,
1495                 * otherwise null (there can only be one selection, and it can
1496                 * only be a sub-menu, as otherwise menu items don't remain
1497                 * selected).
1498                 */
1499                public Accessible getAccessibleSelection(int i) {
1500                    // if i is a sub-menu & popped, return it
1501                    if (i < 0 || i >= getItemCount()) {
1502                        return null;
1503                    }
1504                    MenuElement me[] = MenuSelectionManager.defaultManager()
1505                            .getSelectedPath();
1506                    if (me != null) {
1507                        for (int j = 0; j < me.length; j++) {
1508                            if (me[j] == JMenu.this ) { // this menu is selected
1509                                // so find the next JMenuItem in the MenuElement 
1510                                // array, and return it!
1511                                while (++j < me.length) {
1512                                    if (me[j] instanceof  JMenuItem) {
1513                                        return (Accessible) me[j];
1514                                    }
1515                                }
1516                            }
1517                        }
1518                    }
1519                    return null;
1520                }
1521
1522                /**
1523                 * Returns true if the current child of this object is selected
1524                 * (that is, if this child is a popped-up submenu).
1525                 *
1526                 * @param i the zero-based index of the child in this Accessible
1527                 * object.
1528                 * @see AccessibleContext#getAccessibleChild
1529                 */
1530                public boolean isAccessibleChildSelected(int i) {
1531                    // if i is a sub-menu and is pop-ed up, return true, else false
1532                    MenuElement me[] = MenuSelectionManager.defaultManager()
1533                            .getSelectedPath();
1534                    if (me != null) {
1535                        JMenuItem mi = JMenu.this .getItem(i);
1536                        for (int j = 0; j < me.length; j++) {
1537                            if (me[j] == mi) {
1538                                return true;
1539                            }
1540                        }
1541                    }
1542                    return false;
1543                }
1544
1545                /**
1546                 * Selects the <code>i</code>th menu in the menu. 
1547                 * If that item is a submenu,
1548                 * it will pop up in response.  If a different item is already
1549                 * popped up, this will force it to close.  If this is a sub-menu
1550                 * that is already popped up (selected), this method has no
1551                 * effect.
1552                 *
1553                 * @param i the index of the item to be selected
1554                 * @see #getAccessibleStateSet
1555                 */
1556                public void addAccessibleSelection(int i) {
1557                    if (i < 0 || i >= getItemCount()) {
1558                        return;
1559                    }
1560                    JMenuItem mi = getItem(i);
1561                    if (mi != null) {
1562                        if (mi instanceof  JMenu) {
1563                            MenuElement me[] = buildMenuElementArray((JMenu) mi);
1564                            MenuSelectionManager.defaultManager()
1565                                    .setSelectedPath(me);
1566                        } else {
1567                            MenuSelectionManager.defaultManager()
1568                                    .setSelectedPath(null);
1569                        }
1570                    }
1571                }
1572
1573                /**
1574                 * Removes the nth item from the selection.  In general, menus 
1575                 * can only have one item within them selected at a time 
1576                 * (e.g. one sub-menu popped open).
1577                 *
1578                 * @param i the zero-based index of the selected item
1579                 */
1580                public void removeAccessibleSelection(int i) {
1581                    if (i < 0 || i >= getItemCount()) {
1582                        return;
1583                    }
1584                    JMenuItem mi = getItem(i);
1585                    if (mi != null && mi instanceof  JMenu) {
1586                        if (((JMenu) mi).isSelected()) {
1587                            MenuElement old[] = MenuSelectionManager
1588                                    .defaultManager().getSelectedPath();
1589                            MenuElement me[] = new MenuElement[old.length - 2];
1590                            for (int j = 0; j < old.length - 2; j++) {
1591                                me[j] = old[j];
1592                            }
1593                            MenuSelectionManager.defaultManager()
1594                                    .setSelectedPath(me);
1595                        }
1596                    }
1597                }
1598
1599                /**
1600                 * Clears the selection in the object, so that nothing in the
1601                 * object is selected.  This will close any open sub-menu.
1602                 */
1603                public void clearAccessibleSelection() {
1604                    // if this menu is selected, reset selection to only go
1605                    // to this menu; else do nothing
1606                    MenuElement old[] = MenuSelectionManager.defaultManager()
1607                            .getSelectedPath();
1608                    if (old != null) {
1609                        for (int j = 0; j < old.length; j++) {
1610                            if (old[j] == JMenu.this ) { // menu is in the selection!
1611                                MenuElement me[] = new MenuElement[j + 1];
1612                                System.arraycopy(old, 0, me, 0, j);
1613                                me[j] = JMenu.this .getPopupMenu();
1614                                MenuSelectionManager.defaultManager()
1615                                        .setSelectedPath(me);
1616                            }
1617                        }
1618                    }
1619                }
1620
1621                /**
1622                 * Normally causes every selected item in the object to be selected
1623                 * if the object supports multiple selections.  This method
1624                 * makes no sense in a menu bar, and so does nothing.
1625                 */
1626                public void selectAllAccessibleSelection() {
1627                }
1628            } // inner class AccessibleJMenu
1629
1630        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.