src/java.desktop/share/classes/java/awt/MenuBar.java
changeset 47216 71c04702a3d5
parent 45025 9ad3afa82b5e
child 48267 2469e21060a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/classes/java/awt/MenuBar.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+import java.awt.peer.MenuBarPeer;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+import sun.awt.AWTAccessor;
+
+/**
+ * The {@code MenuBar} class encapsulates the platform's
+ * concept of a menu bar bound to a frame. In order to associate
+ * the menu bar with a {@code Frame} object, call the
+ * frame's {@code setMenuBar} method.
+ * <p>
+ * <a id="mbexample"></a><!-- target for cross references -->
+ * This is what a menu bar might look like:
+ * <p>
+ * <img src="doc-files/MenuBar-1.gif"
+ * alt="Diagram of MenuBar containing 2 menus: Examples and Options.
+ * Examples menu is expanded showing items: Basic, Simple, Check, and More Examples."
+ * style="float:center; margin: 7px 10px;">
+ * <p>
+ * A menu bar handles keyboard shortcuts for menu items, passing them
+ * along to its child menus.
+ * (Keyboard shortcuts, which are optional, provide the user with
+ * an alternative to the mouse for invoking a menu item and the
+ * action that is associated with it.)
+ * Each menu item can maintain an instance of {@code MenuShortcut}.
+ * The {@code MenuBar} class defines several methods,
+ * {@link MenuBar#shortcuts} and
+ * {@link MenuBar#getShortcutMenuItem}
+ * that retrieve information about the shortcuts a given
+ * menu bar is managing.
+ *
+ * @author Sami Shaio
+ * @see        java.awt.Frame
+ * @see        java.awt.Frame#setMenuBar(java.awt.MenuBar)
+ * @see        java.awt.Menu
+ * @see        java.awt.MenuItem
+ * @see        java.awt.MenuShortcut
+ * @since      1.0
+ */
+public class MenuBar extends MenuComponent implements MenuContainer, Accessible {
+
+    static {
+        /* ensure that the necessary native libraries are loaded */
+        Toolkit.loadLibraries();
+        if (!GraphicsEnvironment.isHeadless()) {
+            initIDs();
+        }
+        AWTAccessor.setMenuBarAccessor(
+            new AWTAccessor.MenuBarAccessor() {
+                public Menu getHelpMenu(MenuBar menuBar) {
+                    return menuBar.helpMenu;
+                }
+
+                public Vector<Menu> getMenus(MenuBar menuBar) {
+                    return menuBar.menus;
+                }
+            });
+    }
+
+    /**
+     * This field represents a vector of the
+     * actual menus that will be part of the MenuBar.
+     *
+     * @serial
+     * @see #countMenus()
+     */
+    private final Vector<Menu> menus = new Vector<>();
+
+    /**
+     * This menu is a special menu dedicated to
+     * help.  The one thing to note about this menu
+     * is that on some platforms it appears at the
+     * right edge of the menubar.
+     *
+     * @serial
+     * @see #getHelpMenu()
+     * @see #setHelpMenu(Menu)
+     */
+    private volatile Menu helpMenu;
+
+    private static final String base = "menubar";
+    private static int nameCounter = 0;
+
+    /*
+     * JDK 1.1 serialVersionUID
+     */
+     private static final long serialVersionUID = -4930327919388951260L;
+
+    /**
+     * Creates a new menu bar.
+     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
+     * returns true.
+     * @see java.awt.GraphicsEnvironment#isHeadless
+     */
+    public MenuBar() throws HeadlessException {
+    }
+
+    /**
+     * Construct a name for this MenuComponent.  Called by getName() when
+     * the name is null.
+     */
+    String constructComponentName() {
+        synchronized (MenuBar.class) {
+            return base + nameCounter++;
+        }
+    }
+
+    /**
+     * Creates the menu bar's peer.  The peer allows us to change the
+     * appearance of the menu bar without changing any of the menu bar's
+     * functionality.
+     */
+    public void addNotify() {
+        synchronized (getTreeLock()) {
+            if (peer == null)
+                peer = getComponentFactory().createMenuBar(this);
+
+            int nmenus = getMenuCount();
+            for (int i = 0 ; i < nmenus ; i++) {
+                getMenu(i).addNotify();
+            }
+        }
+    }
+
+    /**
+     * Removes the menu bar's peer.  The peer allows us to change the
+     * appearance of the menu bar without changing any of the menu bar's
+     * functionality.
+     */
+    public void removeNotify() {
+        synchronized (getTreeLock()) {
+            int nmenus = getMenuCount();
+            for (int i = 0 ; i < nmenus ; i++) {
+                getMenu(i).removeNotify();
+            }
+            super.removeNotify();
+        }
+    }
+
+    /**
+     * Gets the help menu on the menu bar.
+     * @return    the help menu on this menu bar.
+     */
+    public Menu getHelpMenu() {
+        return helpMenu;
+    }
+
+    /**
+     * Sets the specified menu to be this menu bar's help menu.
+     * If this menu bar has an existing help menu, the old help menu is
+     * removed from the menu bar, and replaced with the specified menu.
+     * @param m    the menu to be set as the help menu
+     */
+    public void setHelpMenu(final Menu m) {
+        synchronized (getTreeLock()) {
+            if (helpMenu == m) {
+                return;
+            }
+            if (helpMenu != null) {
+                remove(helpMenu);
+            }
+            helpMenu = m;
+            if (m != null) {
+                if (m.parent != this) {
+                    add(m);
+                }
+                m.isHelpMenu = true;
+                m.parent = this;
+                MenuBarPeer peer = (MenuBarPeer)this.peer;
+                if (peer != null) {
+                    if (m.peer == null) {
+                        m.addNotify();
+                    }
+                    peer.addHelpMenu(m);
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds the specified menu to the menu bar.
+     * If the menu has been part of another menu bar,
+     * removes it from that menu bar.
+     *
+     * @param        m   the menu to be added
+     * @return       the menu added
+     * @see          java.awt.MenuBar#remove(int)
+     * @see          java.awt.MenuBar#remove(java.awt.MenuComponent)
+     */
+    public Menu add(Menu m) {
+        synchronized (getTreeLock()) {
+            if (m.parent != null) {
+                m.parent.remove(m);
+            }
+            m.parent = this;
+
+            MenuBarPeer peer = (MenuBarPeer)this.peer;
+            if (peer != null) {
+                if (m.peer == null) {
+                    m.addNotify();
+                }
+                menus.addElement(m);
+                peer.addMenu(m);
+            } else {
+                menus.addElement(m);
+            }
+            return m;
+        }
+    }
+
+    /**
+     * Removes the menu located at the specified
+     * index from this menu bar.
+     * @param        index   the position of the menu to be removed.
+     * @see          java.awt.MenuBar#add(java.awt.Menu)
+     */
+    public void remove(final int index) {
+        synchronized (getTreeLock()) {
+            Menu m = getMenu(index);
+            menus.removeElementAt(index);
+            MenuBarPeer peer = (MenuBarPeer)this.peer;
+            if (peer != null) {
+                peer.delMenu(index);
+                m.removeNotify();
+            }
+            m.parent = null;
+            if (helpMenu == m) {
+                helpMenu = null;
+                m.isHelpMenu = false;
+            }
+        }
+    }
+
+    /**
+     * Removes the specified menu component from this menu bar.
+     * @param        m the menu component to be removed.
+     * @see          java.awt.MenuBar#add(java.awt.Menu)
+     */
+    public void remove(MenuComponent m) {
+        synchronized (getTreeLock()) {
+            int index = menus.indexOf(m);
+            if (index >= 0) {
+                remove(index);
+            }
+        }
+    }
+
+    /**
+     * Gets the number of menus on the menu bar.
+     * @return     the number of menus on the menu bar.
+     * @since      1.1
+     */
+    public int getMenuCount() {
+        return countMenus();
+    }
+
+    /**
+     * Gets the number of menus on the menu bar.
+     *
+     * @return the number of menus on the menu bar.
+     * @deprecated As of JDK version 1.1,
+     * replaced by {@code getMenuCount()}.
+     */
+    @Deprecated
+    public int countMenus() {
+        return getMenuCountImpl();
+    }
+
+    /*
+     * This is called by the native code, so client code can't
+     * be called on the toolkit thread.
+     */
+    final int getMenuCountImpl() {
+        return menus.size();
+    }
+
+    /**
+     * Gets the specified menu.
+     * @param      i the index position of the menu to be returned.
+     * @return     the menu at the specified index of this menu bar.
+     */
+    public Menu getMenu(int i) {
+        return getMenuImpl(i);
+    }
+
+    /*
+     * This is called by the native code, so client code can't
+     * be called on the toolkit thread.
+     */
+    final Menu getMenuImpl(int i) {
+        return menus.elementAt(i);
+    }
+
+    /**
+     * Gets an enumeration of all menu shortcuts this menu bar
+     * is managing.
+     * @return      an enumeration of menu shortcuts that this
+     *                      menu bar is managing.
+     * @see         java.awt.MenuShortcut
+     * @since       1.1
+     */
+    public synchronized Enumeration<MenuShortcut> shortcuts() {
+        Vector<MenuShortcut> shortcuts = new Vector<>();
+        int nmenus = getMenuCount();
+        for (int i = 0 ; i < nmenus ; i++) {
+            Enumeration<MenuShortcut> e = getMenu(i).shortcuts();
+            while (e.hasMoreElements()) {
+                shortcuts.addElement(e.nextElement());
+            }
+        }
+        return shortcuts.elements();
+    }
+
+    /**
+     * Gets the instance of {@code MenuItem} associated
+     * with the specified {@code MenuShortcut} object,
+     * or {@code null} if none of the menu items being managed
+     * by this menu bar is associated with the specified menu
+     * shortcut.
+     * @param  s the specified menu shortcut.
+     * @return the menu item for the specified shortcut.
+     * @see java.awt.MenuItem
+     * @see java.awt.MenuShortcut
+     * @since 1.1
+     */
+     public MenuItem getShortcutMenuItem(MenuShortcut s) {
+        int nmenus = getMenuCount();
+        for (int i = 0 ; i < nmenus ; i++) {
+            MenuItem mi = getMenu(i).getShortcutMenuItem(s);
+            if (mi != null) {
+                return mi;
+            }
+        }
+        return null;  // MenuShortcut wasn't found
+     }
+
+    /*
+     * Post an ACTION_EVENT to the target of the MenuPeer
+     * associated with the specified keyboard event (on
+     * keydown).  Returns true if there is an associated
+     * keyboard event.
+     */
+    @SuppressWarnings("deprecation")
+    boolean handleShortcut(KeyEvent e) {
+        // Is it a key event?
+        int id = e.getID();
+        if (id != KeyEvent.KEY_PRESSED && id != KeyEvent.KEY_RELEASED) {
+            return false;
+        }
+
+        // Is the accelerator modifier key pressed?
+        int accelKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+        if ((e.getModifiers() & accelKey) == 0) {
+            return false;
+        }
+
+        // Pass MenuShortcut on to child menus.
+        int nmenus = getMenuCount();
+        for (int i = 0 ; i < nmenus ; i++) {
+            Menu m = getMenu(i);
+            if (m.handleShortcut(e)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Deletes the specified menu shortcut.
+     * @param     s the menu shortcut to delete.
+     * @since     1.1
+     */
+    public void deleteShortcut(MenuShortcut s) {
+        int nmenus = getMenuCount();
+        for (int i = 0 ; i < nmenus ; i++) {
+            getMenu(i).deleteShortcut(s);
+        }
+    }
+
+    /* Serialization support.  Restore the (transient) parent
+     * fields of Menubar menus here.
+     */
+
+    /**
+     * The MenuBar's serialized data version.
+     *
+     * @serial
+     */
+    private int menuBarSerializedDataVersion = 1;
+
+    /**
+     * Writes default serializable fields to stream.
+     *
+     * @param s the {@code ObjectOutputStream} to write
+     * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
+     * @see #readObject(java.io.ObjectInputStream)
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+      throws java.lang.ClassNotFoundException,
+             java.io.IOException
+    {
+      s.defaultWriteObject();
+    }
+
+    /**
+     * Reads the {@code ObjectInputStream}.
+     * Unrecognized keys or values will be ignored.
+     *
+     * @param s the {@code ObjectInputStream} to read
+     * @exception HeadlessException if
+     *   {@code GraphicsEnvironment.isHeadless} returns
+     *   {@code true}
+     * @see java.awt.GraphicsEnvironment#isHeadless
+     * @see #writeObject(java.io.ObjectOutputStream)
+     */
+    private void readObject(ObjectInputStream s)
+      throws ClassNotFoundException, IOException, HeadlessException
+    {
+      // HeadlessException will be thrown from MenuComponent's readObject
+      s.defaultReadObject();
+      for (int i = 0; i < menus.size(); i++) {
+        Menu m = menus.elementAt(i);
+        m.parent = this;
+      }
+    }
+
+    /**
+     * Initialize JNI field and method IDs
+     */
+    private static native void initIDs();
+
+
+/////////////////
+// Accessibility support
+////////////////
+
+    /**
+     * Gets the AccessibleContext associated with this MenuBar.
+     * For menu bars, the AccessibleContext takes the form of an
+     * AccessibleAWTMenuBar.
+     * A new AccessibleAWTMenuBar instance is created if necessary.
+     *
+     * @return an AccessibleAWTMenuBar that serves as the
+     *         AccessibleContext of this MenuBar
+     * @since 1.3
+     */
+    public AccessibleContext getAccessibleContext() {
+        if (accessibleContext == null) {
+            accessibleContext = new AccessibleAWTMenuBar();
+        }
+        return accessibleContext;
+    }
+
+    /**
+     * Defined in MenuComponent. Overridden here.
+     */
+    int getAccessibleChildIndex(MenuComponent child) {
+        return menus.indexOf(child);
+    }
+
+    /**
+     * Inner class of MenuBar used to provide default support for
+     * accessibility.  This class is not meant to be used directly by
+     * application developers, but is instead meant only to be
+     * subclassed by menu component developers.
+     * <p>
+     * This class implements accessibility support for the
+     * {@code MenuBar} class.  It provides an implementation of the
+     * Java Accessibility API appropriate to menu bar user-interface elements.
+     * @since 1.3
+     */
+    protected class AccessibleAWTMenuBar extends AccessibleAWTMenuComponent
+    {
+        /*
+         * JDK 1.3 serialVersionUID
+         */
+        private static final long serialVersionUID = -8577604491830083815L;
+
+        /**
+         * Get the role of this object.
+         *
+         * @return an instance of AccessibleRole describing the role of the
+         * object
+         * @since 1.4
+         */
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.MENU_BAR;
+        }
+
+    } // class AccessibleAWTMenuBar
+
+}