001: /*
002: * @(#)MenuBar.java 1.61 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027: package java.awt;
028:
029: import java.util.Vector;
030: import java.util.Enumeration;
031: import sun.awt.peer.MenuBarPeer;
032: import sun.awt.PeerBasedToolkit;
033: import java.awt.event.KeyEvent;
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: * ALIGN=center HSPACE=10 VSPACE=7>
046: * <p>
047: * A menu bar handles keyboard shortcuts for menu items, passing them
048: * along to its child menus.
049: * (Keyboard shortcuts, which are optional, provide the user with
050: * an alternative to the mouse for invoking a menu item and the
051: * action that is associated with it.)
052: * Each menu item can maintain an instance of <code>MenuShortcut</code>.
053: * The <code>MenuBar</code> class defines several methods,
054: * {@link MenuBar#shortcuts} and
055: * {@link MenuBar#getShortcutMenuItem}
056: * that retrieve information about the shortcuts a given
057: * menu bar is managing.
058: *
059: * @version 1.56, 08/19/02
060: * @author Sami Shaio
061: * @see java.awt.Frame
062: * @see java.awt.Frame#setMenuBar(java.awt.MenuBar)
063: * @see java.awt.Menu
064: * @see java.awt.MenuItem
065: * @see java.awt.MenuShortcut
066: * @since JDK1.0
067: */
068: public class MenuBar extends MenuComponent implements MenuContainer {
069: /**
070: * This field represents a vector of the
071: * actual menus that will be part of the MenuBar.
072: *
073: * @serial
074: * @see countMenus()
075: */
076: Vector menus = new Vector();
077: /**
078: * This menu is a special menu dedicated to
079: * help. The one thing to note about this menu
080: * is that on some platforms it appears at the
081: * right edge of the menubar.
082: *
083: * @serial
084: * @see getHelpMenu()
085: * @see setHelpMenu()
086: */
087: Menu helpMenu;
088: private static final String base = "menubar";
089: private static int nameCounter = 0;
090: /*
091: * JDK 1.1 serialVersionUID
092: */
093: private static final long serialVersionUID = -4930327919388951260L;
094:
095: /**
096: * Creates a new menu bar.
097: */
098: public MenuBar() {
099: }
100:
101: /**
102: * Construct a name for this MenuComponent. Called by getName() when
103: * the name is null.
104: */
105: String constructComponentName() {
106: return base + nameCounter++;
107: }
108:
109: /**
110: * Creates the menu bar's peer. The peer allows us to change the
111: * appearance of the menu bar without changing any of the menu bar's
112: * functionality.
113: */
114: public void addNotify() {
115: synchronized (getTreeLock()) {
116: if (peer == null)
117: peer = ((PeerBasedToolkit) Toolkit.getDefaultToolkit())
118: .createMenuBar(this );
119: int nmenus = getMenuCount();
120: for (int i = 0; i < nmenus; i++) {
121: getMenu(i).addNotify();
122: }
123: }
124: }
125:
126: /**
127: * Removes the menu bar's peer. The peer allows us to change the
128: * appearance of the menu bar without changing any of the menu bar's
129: * functionality.
130: */
131: public void removeNotify() {
132: synchronized (getTreeLock()) {
133: int nmenus = getMenuCount();
134: for (int i = 0; i < nmenus; i++) {
135: getMenu(i).removeNotify();
136: }
137: super .removeNotify();
138: }
139: }
140:
141: /**
142: * Gets the help menu on the menu bar.
143: * @return the help menu on this menu bar.
144: */
145: public Menu getHelpMenu() {
146: return helpMenu;
147: }
148:
149: /**
150: * Sets the specified menu to be this menu bar's help menu.
151: * If this menu bar has an existing help menu, the old help menu is
152: * removed from the menu bar, and replaced with the specified menu.
153: * @param m the menu to be set as the help menu
154: */
155: public void setHelpMenu(Menu m) {
156: synchronized (getTreeLock()) {
157: if (helpMenu == m) {
158: return;
159: }
160: if (helpMenu != null) {
161: remove(helpMenu);
162: }
163: if (m.parent != this ) {
164: add(m);
165: }
166: helpMenu = m;
167: if (m != null) {
168: m.isHelpMenu = true;
169: m.parent = this ;
170: MenuBarPeer peer = (MenuBarPeer) this .peer;
171: if (peer != null) {
172: if (m.peer == null) {
173: m.addNotify();
174: }
175: peer.addHelpMenu(m);
176: }
177: }
178: }
179: }
180:
181: /**
182: * Adds the specified menu to the menu bar.
183: * @param m the menu to be added.
184: * @return the menu added.
185: * @see java.awt.MenuBar#remove(int)
186: * @see java.awt.MenuBar#remove(java.awt.MenuComponent)
187: * @since JDK1.0
188: */
189: public Menu add(Menu m) {
190: synchronized (getTreeLock()) {
191: if (m.parent != null) {
192: m.parent.remove(m);
193: }
194: menus.addElement(m);
195: m.parent = this ;
196: MenuBarPeer peer = (MenuBarPeer) this .peer;
197: if (peer != null) {
198: if (m.peer == null) {
199: m.addNotify();
200: }
201: peer.addMenu(m);
202: }
203: return m;
204: }
205: }
206:
207: /**
208: * Removes the menu located at the specified
209: * index from this menu bar.
210: * @param index the position of the menu to be removed.
211: * @see java.awt.MenuBar#add(java.awt.Menu)
212: */
213: public void remove(int index) {
214: synchronized (getTreeLock()) {
215: MenuBarPeer peer = (MenuBarPeer) this .peer;
216: if (peer != null) {
217: Menu m = getMenu(index);
218: m.removeNotify();
219: m.parent = null;
220: peer.delMenu(index);
221: }
222: menus.removeElementAt(index);
223: }
224: }
225:
226: /**
227: * Removes the specified menu component from this menu bar.
228: * @param m the menu component to be removed.
229: * @see java.awt.MenuBar#add(java.awt.Menu)
230: */
231: public void remove(MenuComponent m) {
232: synchronized (getTreeLock()) {
233: int index = menus.indexOf(m);
234: if (index >= 0) {
235: remove(index);
236: }
237: }
238: }
239:
240: /**
241: * Gets the number of menus on the menu bar.
242: * @return the number of menus on the menu bar.
243: * @since JDK1.1
244: */
245: public int getMenuCount() {
246: return countMenus();
247: }
248:
249: /**
250: * @deprecated As of JDK version 1.1,
251: * replaced by <code>getMenuCount()</code>.
252: */
253: public int countMenus() {
254: return menus.size();
255: }
256:
257: /**
258: * Gets the specified menu.
259: * @param i the index position of the menu to be returned.
260: * @return the menu at the specified index of this menu bar.
261: */
262: public Menu getMenu(int i) {
263: return (Menu) menus.elementAt(i);
264: }
265:
266: /**
267: * Gets an enumeration of all menu shortcuts this menu bar
268: * is managing.
269: * @return an enumeration of menu shortcuts that this
270: * menu bar is managing.
271: * @see java.awt.MenuShortcut
272: * @since JDK1.1
273: */
274: public synchronized Enumeration shortcuts() {
275: Vector shortcuts = new Vector();
276: int nmenus = getMenuCount();
277: for (int i = 0; i < nmenus; i++) {
278: Enumeration e = getMenu(i).shortcuts();
279: while (e.hasMoreElements()) {
280: shortcuts.addElement(e.nextElement());
281: }
282: }
283: return shortcuts.elements();
284: }
285:
286: /**
287: * Gets the instance of <code>MenuItem</code> associated
288: * with the specified <code>MenuShortcut</code> object,
289: * or <code>null</code> if none of the menu items being managed
290: * by this menu bar is associated with the specified menu
291: * shortcut.
292: * @param s the specified menu shortcut.
293: * @see java.awt.MenuItem
294: * @see java.awt.MenuShortcut
295: * @since JDK1.1
296: */
297: public MenuItem getShortcutMenuItem(MenuShortcut s) {
298: int nmenus = getMenuCount();
299: for (int i = 0; i < nmenus; i++) {
300: MenuItem mi = getMenu(i).getShortcutMenuItem(s);
301: if (mi != null) {
302: return mi;
303: }
304: }
305: return null; // MenuShortcut wasn't found
306: }
307:
308: /*
309: * Post an ACTION_EVENT to the target of the MenuPeer
310: * associated with the specified keyboard event (on
311: * keydown). Returns true if there is an associated
312: * keyboard event.
313: */
314: boolean handleShortcut(KeyEvent e) {
315: // Is it a key event?
316: int id = e.getID();
317: if (id != KeyEvent.KEY_PRESSED && id != KeyEvent.KEY_RELEASED) {
318: return false;
319: }
320: // Is the accelerator modifier key pressed?
321: int accelKey = Toolkit.getDefaultToolkit()
322: .getMenuShortcutKeyMask();
323: if ((e.getModifiers() & accelKey) == 0) {
324: return false;
325: }
326: // Pass MenuShortcut on to child menus.
327: int nmenus = getMenuCount();
328: for (int i = 0; i < nmenus; i++) {
329: Menu m = getMenu(i);
330: if (m.handleShortcut(e)) {
331: return true;
332: }
333: }
334: return false;
335: }
336:
337: /**
338: * Deletes the specified menu shortcut.
339: * @param s the menu shortcut to delete.
340: * @since JDK1.1
341: */
342: public void deleteShortcut(MenuShortcut s) {
343: int nmenus = getMenuCount();
344: for (int i = 0; i < nmenus; i++) {
345: getMenu(i).deleteShortcut(s);
346: }
347: }
348:
349: /* Serialization support. Restore the (transient) parent
350: * fields of Menubar menus here.
351: */
352:
353: private int menuBarSerializedDataVersion = 1;
354:
355: /**
356: * Writes default serializable fields to stream. Writes
357: * a list of serializable ItemListener(s) as optional data.
358: * The non-serializable ItemListner(s) are detected and
359: * no attempt is made to serialize them.
360: *
361: * @serialData Null terminated sequence of 0 or more pairs.
362: * The pair consists of a String and Object.
363: * The String indicates the type of object and
364: * is one of the following :
365: * itemListenerK indicating and ItemListener object.
366: *
367: * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
368: * @see java.awt.Component.itemListenerK
369: */
370: private void writeObject(java.io.ObjectOutputStream s)
371: throws java.lang.ClassNotFoundException,
372: java.io.IOException {
373: s.defaultWriteObject();
374: }
375:
376: /**
377: * Read the ObjectInputStream and if it isnt null
378: * add a listener to receive item events fired
379: * by the MenuBar.
380: * Unrecognised keys or values will be Ignored.
381: *
382: * @see removeActionListener()
383: * @see addActionListener()
384: */
385:
386: private void readObject(java.io.ObjectInputStream s)
387: throws java.lang.ClassNotFoundException,
388: java.io.IOException {
389: s.defaultReadObject();
390: for (int i = 0; i < menus.size(); i++) {
391: Menu m = (Menu) menus.elementAt(i);
392: m.parent = this;
393: }
394: }
395: }
|