001: /*
002: * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package java.awt;
026:
027: import java.io.IOException;
028: import java.io.ObjectInputStream;
029: import java.util.Vector;
030: import java.util.Enumeration;
031: import java.awt.peer.MenuBarPeer;
032: import java.awt.event.KeyEvent;
033: import javax.accessibility.*;
034:
035: /**
036: * The <code>MenuBar</code> class encapsulates the platform's
037: * concept of a menu bar bound to a frame. In order to associate
038: * the menu bar with a <code>Frame</code> object, call the
039: * frame's <code>setMenuBar</code> method.
040: * <p>
041: * <A NAME="mbexample"></A><!-- target for cross references -->
042: * This is what a menu bar might look like:
043: * <p>
044: * <img src="doc-files/MenuBar-1.gif"
045: * <alt="Diagram of MenuBar containing 2 menus: Examples and Options.
046: * Examples menu is expanded showing items: Basic, Simple, Check, and More Examples."
047: * ALIGN=center HSPACE=10 VSPACE=7>
048: * <p>
049: * A menu bar handles keyboard shortcuts for menu items, passing them
050: * along to its child menus.
051: * (Keyboard shortcuts, which are optional, provide the user with
052: * an alternative to the mouse for invoking a menu item and the
053: * action that is associated with it.)
054: * Each menu item can maintain an instance of <code>MenuShortcut</code>.
055: * The <code>MenuBar</code> class defines several methods,
056: * {@link MenuBar#shortcuts} and
057: * {@link MenuBar#getShortcutMenuItem}
058: * that retrieve information about the shortcuts a given
059: * menu bar is managing.
060: *
061: * @version 1.79, 05/05/07
062: * @author Sami Shaio
063: * @see java.awt.Frame
064: * @see java.awt.Frame#setMenuBar(java.awt.MenuBar)
065: * @see java.awt.Menu
066: * @see java.awt.MenuItem
067: * @see java.awt.MenuShortcut
068: * @since JDK1.0
069: */
070: public class MenuBar extends MenuComponent implements MenuContainer,
071: Accessible {
072:
073: static {
074: /* ensure that the necessary native libraries are loaded */
075: Toolkit.loadLibraries();
076: if (!GraphicsEnvironment.isHeadless()) {
077: initIDs();
078: }
079: }
080:
081: /**
082: * This field represents a vector of the
083: * actual menus that will be part of the MenuBar.
084: *
085: * @serial
086: * @see #countMenus()
087: */
088: Vector menus = new Vector();
089:
090: /**
091: * This menu is a special menu dedicated to
092: * help. The one thing to note about this menu
093: * is that on some platforms it appears at the
094: * right edge of the menubar.
095: *
096: * @serial
097: * @see #getHelpMenu()
098: * @see #setHelpMenu(Menu)
099: */
100: Menu helpMenu;
101:
102: private static final String base = "menubar";
103: private static int nameCounter = 0;
104:
105: /*
106: * JDK 1.1 serialVersionUID
107: */
108: private static final long serialVersionUID = -4930327919388951260L;
109:
110: /**
111: * Creates a new menu bar.
112: * @exception HeadlessException if GraphicsEnvironment.isHeadless()
113: * returns true.
114: * @see java.awt.GraphicsEnvironment#isHeadless
115: */
116: public MenuBar() throws HeadlessException {
117: }
118:
119: /**
120: * Construct a name for this MenuComponent. Called by getName() when
121: * the name is null.
122: */
123: String constructComponentName() {
124: synchronized (MenuBar.class) {
125: return base + nameCounter++;
126: }
127: }
128:
129: /**
130: * Creates the menu bar's peer. The peer allows us to change the
131: * appearance of the menu bar without changing any of the menu bar's
132: * functionality.
133: */
134: public void addNotify() {
135: synchronized (getTreeLock()) {
136: if (peer == null)
137: peer = Toolkit.getDefaultToolkit().createMenuBar(this );
138:
139: int nmenus = getMenuCount();
140: for (int i = 0; i < nmenus; i++) {
141: getMenu(i).addNotify();
142: }
143: }
144: }
145:
146: /**
147: * Removes the menu bar's peer. The peer allows us to change the
148: * appearance of the menu bar without changing any of the menu bar's
149: * functionality.
150: */
151: public void removeNotify() {
152: synchronized (getTreeLock()) {
153: int nmenus = getMenuCount();
154: for (int i = 0; i < nmenus; i++) {
155: getMenu(i).removeNotify();
156: }
157: super .removeNotify();
158: }
159: }
160:
161: /**
162: * Gets the help menu on the menu bar.
163: * @return the help menu on this menu bar.
164: */
165: public Menu getHelpMenu() {
166: return helpMenu;
167: }
168:
169: /**
170: * Sets the specified menu to be this menu bar's help menu.
171: * If this menu bar has an existing help menu, the old help menu is
172: * removed from the menu bar, and replaced with the specified menu.
173: * @param m the menu to be set as the help menu
174: */
175: public void setHelpMenu(Menu m) {
176: synchronized (getTreeLock()) {
177: if (helpMenu == m) {
178: return;
179: }
180: if (helpMenu != null) {
181: remove(helpMenu);
182: }
183: if (m.parent != this ) {
184: add(m);
185: }
186: helpMenu = m;
187: if (m != null) {
188: m.isHelpMenu = true;
189: m.parent = this ;
190: MenuBarPeer peer = (MenuBarPeer) this .peer;
191: if (peer != null) {
192: if (m.peer == null) {
193: m.addNotify();
194: }
195: peer.addHelpMenu(m);
196: }
197: }
198: }
199: }
200:
201: /**
202: * Adds the specified menu to the menu bar.
203: * If the menu has been part of another menu bar,
204: * removes it from that menu bar.
205: *
206: * @param m the menu to be added
207: * @return the menu added
208: * @see java.awt.MenuBar#remove(int)
209: * @see java.awt.MenuBar#remove(java.awt.MenuComponent)
210: */
211: public Menu add(Menu m) {
212: synchronized (getTreeLock()) {
213: if (m.parent != null) {
214: m.parent.remove(m);
215: }
216: menus.addElement(m);
217: m.parent = this ;
218:
219: MenuBarPeer peer = (MenuBarPeer) this .peer;
220: if (peer != null) {
221: if (m.peer == null) {
222: m.addNotify();
223: }
224: peer.addMenu(m);
225: }
226: return m;
227: }
228: }
229:
230: /**
231: * Removes the menu located at the specified
232: * index from this menu bar.
233: * @param index the position of the menu to be removed.
234: * @see java.awt.MenuBar#add(java.awt.Menu)
235: */
236: public void remove(int index) {
237: synchronized (getTreeLock()) {
238: Menu m = getMenu(index);
239: menus.removeElementAt(index);
240: MenuBarPeer peer = (MenuBarPeer) this .peer;
241: if (peer != null) {
242: m.removeNotify();
243: m.parent = null;
244: peer.delMenu(index);
245: }
246: }
247: }
248:
249: /**
250: * Removes the specified menu component from this menu bar.
251: * @param m the menu component to be removed.
252: * @see java.awt.MenuBar#add(java.awt.Menu)
253: */
254: public void remove(MenuComponent m) {
255: synchronized (getTreeLock()) {
256: int index = menus.indexOf(m);
257: if (index >= 0) {
258: remove(index);
259: }
260: }
261: }
262:
263: /**
264: * Gets the number of menus on the menu bar.
265: * @return the number of menus on the menu bar.
266: * @since JDK1.1
267: */
268: public int getMenuCount() {
269: return countMenus();
270: }
271:
272: /**
273: * @deprecated As of JDK version 1.1,
274: * replaced by <code>getMenuCount()</code>.
275: */
276: @Deprecated
277: public int countMenus() {
278: return getMenuCountImpl();
279: }
280:
281: /*
282: * This is called by the native code, so client code can't
283: * be called on the toolkit thread.
284: */
285: final int getMenuCountImpl() {
286: return menus.size();
287: }
288:
289: /**
290: * Gets the specified menu.
291: * @param i the index position of the menu to be returned.
292: * @return the menu at the specified index of this menu bar.
293: */
294: public Menu getMenu(int i) {
295: return getMenuImpl(i);
296: }
297:
298: /*
299: * This is called by the native code, so client code can't
300: * be called on the toolkit thread.
301: */
302: final Menu getMenuImpl(int i) {
303: return (Menu) menus.elementAt(i);
304: }
305:
306: /**
307: * Gets an enumeration of all menu shortcuts this menu bar
308: * is managing.
309: * @return an enumeration of menu shortcuts that this
310: * menu bar is managing.
311: * @see java.awt.MenuShortcut
312: * @since JDK1.1
313: */
314: public synchronized Enumeration<MenuShortcut> shortcuts() {
315: Vector shortcuts = new Vector();
316: int nmenus = getMenuCount();
317: for (int i = 0; i < nmenus; i++) {
318: Enumeration e = getMenu(i).shortcuts();
319: while (e.hasMoreElements()) {
320: shortcuts.addElement(e.nextElement());
321: }
322: }
323: return shortcuts.elements();
324: }
325:
326: /**
327: * Gets the instance of <code>MenuItem</code> associated
328: * with the specified <code>MenuShortcut</code> object,
329: * or <code>null</code> if none of the menu items being managed
330: * by this menu bar is associated with the specified menu
331: * shortcut.
332: * @param s the specified menu shortcut.
333: * @see java.awt.MenuItem
334: * @see java.awt.MenuShortcut
335: * @since JDK1.1
336: */
337: public MenuItem getShortcutMenuItem(MenuShortcut s) {
338: int nmenus = getMenuCount();
339: for (int i = 0; i < nmenus; i++) {
340: MenuItem mi = getMenu(i).getShortcutMenuItem(s);
341: if (mi != null) {
342: return mi;
343: }
344: }
345: return null; // MenuShortcut wasn't found
346: }
347:
348: /*
349: * Post an ACTION_EVENT to the target of the MenuPeer
350: * associated with the specified keyboard event (on
351: * keydown). Returns true if there is an associated
352: * keyboard event.
353: */
354: boolean handleShortcut(KeyEvent e) {
355: // Is it a key event?
356: int id = e.getID();
357: if (id != KeyEvent.KEY_PRESSED && id != KeyEvent.KEY_RELEASED) {
358: return false;
359: }
360:
361: // Is the accelerator modifier key pressed?
362: int accelKey = Toolkit.getDefaultToolkit()
363: .getMenuShortcutKeyMask();
364: if ((e.getModifiers() & accelKey) == 0) {
365: return false;
366: }
367:
368: // Pass MenuShortcut on to child menus.
369: int nmenus = getMenuCount();
370: for (int i = 0; i < nmenus; i++) {
371: Menu m = getMenu(i);
372: if (m.handleShortcut(e)) {
373: return true;
374: }
375: }
376: return false;
377: }
378:
379: /**
380: * Deletes the specified menu shortcut.
381: * @param s the menu shortcut to delete.
382: * @since JDK1.1
383: */
384: public void deleteShortcut(MenuShortcut s) {
385: int nmenus = getMenuCount();
386: for (int i = 0; i < nmenus; i++) {
387: getMenu(i).deleteShortcut(s);
388: }
389: }
390:
391: /* Serialization support. Restore the (transient) parent
392: * fields of Menubar menus here.
393: */
394:
395: /**
396: * The MenuBar's serialized data version.
397: *
398: * @serial
399: */
400: private int menuBarSerializedDataVersion = 1;
401:
402: /**
403: * Writes default serializable fields to stream.
404: *
405: * @param s the <code>ObjectOutputStream</code> to write
406: * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
407: * @see #readObject(java.io.ObjectInputStream)
408: */
409: private void writeObject(java.io.ObjectOutputStream s)
410: throws java.lang.ClassNotFoundException,
411: java.io.IOException {
412: s.defaultWriteObject();
413: }
414:
415: /**
416: * Reads the <code>ObjectInputStream</code>.
417: * Unrecognized keys or values will be ignored.
418: *
419: * @param s the <code>ObjectInputStream</code> to read
420: * @exception HeadlessException if
421: * <code>GraphicsEnvironment.isHeadless</code> returns
422: * <code>true</code>
423: * @see java.awt.GraphicsEnvironment#isHeadless
424: * @see #writeObject(java.io.ObjectOutputStream)
425: */
426: private void readObject(ObjectInputStream s)
427: throws ClassNotFoundException, IOException,
428: HeadlessException {
429: // HeadlessException will be thrown from MenuComponent's readObject
430: s.defaultReadObject();
431: for (int i = 0; i < menus.size(); i++) {
432: Menu m = (Menu) menus.elementAt(i);
433: m.parent = this ;
434: }
435: }
436:
437: /**
438: * Initialize JNI field and method IDs
439: */
440: private static native void initIDs();
441:
442: /////////////////
443: // Accessibility support
444: ////////////////
445:
446: /**
447: * Gets the AccessibleContext associated with this MenuBar.
448: * For menu bars, the AccessibleContext takes the form of an
449: * AccessibleAWTMenuBar.
450: * A new AccessibleAWTMenuBar instance is created if necessary.
451: *
452: * @return an AccessibleAWTMenuBar that serves as the
453: * AccessibleContext of this MenuBar
454: * @since 1.3
455: */
456: public AccessibleContext getAccessibleContext() {
457: if (accessibleContext == null) {
458: accessibleContext = new AccessibleAWTMenuBar();
459: }
460: return accessibleContext;
461: }
462:
463: /**
464: * Defined in MenuComponent. Overridden here.
465: */
466: int getAccessibleChildIndex(MenuComponent child) {
467: return menus.indexOf(child);
468: }
469:
470: /**
471: * Inner class of MenuBar used to provide default support for
472: * accessibility. This class is not meant to be used directly by
473: * application developers, but is instead meant only to be
474: * subclassed by menu component developers.
475: * <p>
476: * This class implements accessibility support for the
477: * <code>MenuBar</code> class. It provides an implementation of the
478: * Java Accessibility API appropriate to menu bar user-interface elements.
479: * @since 1.3
480: */
481: protected class AccessibleAWTMenuBar extends
482: AccessibleAWTMenuComponent {
483: /*
484: * JDK 1.3 serialVersionUID
485: */
486: private static final long serialVersionUID = -8577604491830083815L;
487:
488: /**
489: * Get the role of this object.
490: *
491: * @return an instance of AccessibleRole describing the role of the
492: * object
493: * @since 1.4
494: */
495: public AccessibleRole getAccessibleRole() {
496: return AccessibleRole.MENU_BAR;
497: }
498:
499: } // class AccessibleAWTMenuBar
500:
501: }
|