KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > Menu


1 /*
2  * @(#)Menu.java 1.75 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.awt;
8
9 import java.io.IOException JavaDoc;
10 import java.io.ObjectInputStream JavaDoc;
11 import java.util.Vector JavaDoc;
12 import java.util.Enumeration JavaDoc;
13 import java.awt.peer.MenuPeer;
14 import java.awt.event.KeyEvent JavaDoc;
15 import javax.accessibility.*;
16
17 /**
18  * A <code>Menu</code> object is a pull-down menu component
19  * that is deployed from a menu bar.
20  * <p>
21  * A menu can optionally be a <i>tear-off</i> menu. A tear-off menu
22  * can be opened and dragged away from its parent menu bar or menu.
23  * It remains on the screen after the mouse button has been released.
24  * The mechanism for tearing off a menu is platform dependent, since
25  * the look and feel of the tear-off menu is determined by its peer.
26  * On platforms that do not support tear-off menus, the tear-off
27  * property is ignored.
28  * <p>
29  * Each item in a menu must belong to the <code>MenuItem</code>
30  * class. It can be an instance of <code>MenuItem</code>, a submenu
31  * (an instance of <code>Menu</code>), or a check box (an instance of
32  * <code>CheckboxMenuItem</code>).
33  *
34  * @version 1.75, 05/18/04
35  * @author Sami Shaio
36  * @see java.awt.MenuItem
37  * @see java.awt.CheckboxMenuItem
38  * @since JDK1.0
39  */

40 public class Menu extends MenuItem JavaDoc implements MenuContainer JavaDoc, Accessible {
41
42     static {
43         /* ensure that the necessary native libraries are loaded */
44     Toolkit.loadLibraries();
45         if (!GraphicsEnvironment.isHeadless()) {
46             initIDs();
47         }
48     }
49
50     /**
51      * A vector of the items that will be part of the Menu.
52      *
53      * @serial
54      * @see #countItems()
55      */

56     Vector JavaDoc items = new Vector JavaDoc();
57
58     /**
59      * This field indicates whether the menu has the
60      * tear of property or not. It will be set to
61      * <code>true</code> if the menu has the tear off
62      * property and it will be set to <code>false></code>
63      * if it does not.
64      * A torn off menu can be deleted by a user when
65      * it is no longer needed.
66      *
67      * @serial
68      * @see #isTearOff()
69      */

70     boolean tearOff;
71
72     /**
73      * This field will be set to <code>true</code>
74      * if the Menu in question is actually a help
75      * menu. Otherwise it will be set to <code>
76      * false</code>.
77      *
78      * @serial
79      */

80     boolean isHelpMenu;
81
82     private static final String JavaDoc base = "menu";
83     private static int nameCounter = 0;
84
85     /*
86      * JDK 1.1 serialVersionUID
87      */

88      private static final long serialVersionUID = -8809584163345499784L;
89
90     /**
91      * Constructs a new menu with an empty label. This menu is not
92      * a tear-off menu.
93      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
94      * returns true.
95      * @see java.awt.GraphicsEnvironment#isHeadless
96      * @since JDK1.1
97      */

98     public Menu() throws HeadlessException JavaDoc {
99     this("", false);
100     }
101
102     /**
103      * Constructs a new menu with the specified label. This menu is not
104      * a tear-off menu.
105      * @param label the menu's label in the menu bar, or in
106      * another menu of which this menu is a submenu.
107      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
108      * returns true.
109      * @see java.awt.GraphicsEnvironment#isHeadless
110      */

111     public Menu(String JavaDoc label) throws HeadlessException JavaDoc {
112     this(label, false);
113     }
114
115     /**
116      * Constructs a new menu with the specified label,
117      * indicating whether the menu can be torn off.
118      * <p>
119      * Tear-off functionality may not be supported by all
120      * implementations of AWT. If a particular implementation doesn't
121      * support tear-off menus, this value is silently ignored.
122      * @param label the menu's label in the menu bar, or in
123      * another menu of which this menu is a submenu.
124      * @param tearOff if <code>true</code>, the menu
125      * is a tear-off menu.
126      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
127      * returns true.
128      * @see java.awt.GraphicsEnvironment#isHeadless
129      * @since JDK1.0.
130      */

131     public Menu(String JavaDoc label, boolean tearOff) throws HeadlessException JavaDoc {
132     super(label);
133     this.tearOff = tearOff;
134     }
135
136     /**
137      * Construct a name for this MenuComponent. Called by getName() when
138      * the name is null.
139      */

140     String JavaDoc constructComponentName() {
141         synchronized (getClass()) {
142         return base + nameCounter++;
143     }
144     }
145
146     /**
147      * Creates the menu's peer. The peer allows us to modify the
148      * appearance of the menu without changing its functionality.
149      */

150     public void addNotify() {
151         synchronized (getTreeLock()) {
152         if (peer == null)
153             peer = Toolkit.getDefaultToolkit().createMenu(this);
154         int nitems = getItemCount();
155         for (int i = 0 ; i < nitems ; i++) {
156             MenuItem JavaDoc mi = getItem(i);
157         mi.parent = this;
158         mi.addNotify();
159         }
160     }
161     }
162
163     /**
164      * Removes the menu's peer. The peer allows us to modify the appearance
165      * of the menu without changing its functionality.
166      */

167     public void removeNotify() {
168         synchronized (getTreeLock()) {
169         int nitems = getItemCount();
170         for (int i = 0 ; i < nitems ; i++) {
171             getItem(i).removeNotify();
172         }
173         super.removeNotify();
174     }
175     }
176
177     /**
178      * Indicates whether this menu is a tear-off menu.
179      * <p>
180      * Tear-off functionality may not be supported by all
181      * implementations of AWT. If a particular implementation doesn't
182      * support tear-off menus, this value is silently ignored.
183      * @return <code>true</code> if this is a tear-off menu;
184      * <code>false</code> otherwise.
185      */

186     public boolean isTearOff() {
187     return tearOff;
188     }
189
190     /**
191       * Get the number of items in this menu.
192       * @return the number of items in this menu.
193       * @since JDK1.1
194       */

195     public int getItemCount() {
196     return countItems();
197     }
198
199     /**
200      * @deprecated As of JDK version 1.1,
201      * replaced by <code>getItemCount()</code>.
202      */

203     @Deprecated JavaDoc
204     public int countItems() {
205     return countItemsImpl();
206     }
207
208     /*
209      * This is called by the native code, so client code can't
210      * be called on the toolkit thread.
211      */

212     final int countItemsImpl() {
213     return items.size();
214     }
215
216     /**
217      * Gets the item located at the specified index of this menu.
218      * @param index the position of the item to be returned.
219      * @return the item located at the specified index.
220      */

221     public MenuItem JavaDoc getItem(int index) {
222     return getItemImpl(index);
223     }
224
225     /*
226      * This is called by the native code, so client code can't
227      * be called on the toolkit thread.
228      */

229     final MenuItem JavaDoc getItemImpl(int index) {
230     return (MenuItem JavaDoc)items.elementAt(index);
231     }
232
233     /**
234      * Adds the specified menu item to this menu. If the
235      * menu item has been part of another menu, removes it
236      * from that menu.
237      *
238      * @param mi the menu item to be added
239      * @return the menu item added
240      * @see java.awt.Menu#insert(java.lang.String, int)
241      * @see java.awt.Menu#insert(java.awt.MenuItem, int)
242      */

243     public MenuItem JavaDoc add(MenuItem JavaDoc mi) {
244         synchronized (getTreeLock()) {
245         if (mi.parent != null) {
246             mi.parent.remove(mi);
247         }
248         items.addElement(mi);
249         mi.parent = this;
250         MenuPeer peer = (MenuPeer)this.peer;
251         if (peer != null) {
252             mi.addNotify();
253         peer.addItem(mi);
254         }
255         return mi;
256     }
257     }
258
259     /**
260      * Adds an item with the specified label to this menu.
261      *
262      * @param label the text on the item
263      * @see java.awt.Menu#insert(java.lang.String, int)
264      * @see java.awt.Menu#insert(java.awt.MenuItem, int)
265      */

266     public void add(String JavaDoc label) {
267     add(new MenuItem JavaDoc(label));
268     }
269
270     /**
271      * Inserts a menu item into this menu
272      * at the specified position.
273      *
274      * @param menuitem the menu item to be inserted.
275      * @param index the position at which the menu
276      * item should be inserted.
277      * @see java.awt.Menu#add(java.lang.String)
278      * @see java.awt.Menu#add(java.awt.MenuItem)
279      * @exception IllegalArgumentException if the value of
280      * <code>index</code> is less than zero
281      * @since JDK1.1
282      */

283
284     public void insert(MenuItem JavaDoc menuitem, int index) {
285         synchronized (getTreeLock()) {
286         if (index < 0) {
287             throw new IllegalArgumentException JavaDoc("index less than zero.");
288         }
289
290         int nitems = getItemCount();
291         Vector JavaDoc tempItems = new Vector JavaDoc();
292
293         /* Remove the item at index, nitems-index times
294            storing them in a temporary vector in the
295            order they appear on the menu.
296         */

297         for (int i = index ; i < nitems; i++) {
298             tempItems.addElement(getItem(index));
299         remove(index);
300         }
301
302         add(menuitem);
303
304         /* Add the removed items back to the menu, they are
305            already in the correct order in the temp vector.
306         */

307         for (int i = 0; i < tempItems.size() ; i++) {
308             add((MenuItem JavaDoc)tempItems.elementAt(i));
309         }
310     }
311     }
312
313     /**
314      * Inserts a menu item with the specified label into this menu
315      * at the specified position. This is a convenience method for
316      * <code>insert(menuItem, index)</code>.
317      *
318      * @param label the text on the item
319      * @param index the position at which the menu item
320      * should be inserted
321      * @see java.awt.Menu#add(java.lang.String)
322      * @see java.awt.Menu#add(java.awt.MenuItem)
323      * @exception IllegalArgumentException if the value of
324      * <code>index</code> is less than zero
325      * @since JDK1.1
326      */

327
328     public void insert(String JavaDoc label, int index) {
329         insert(new MenuItem JavaDoc(label), index);
330     }
331
332     /**
333      * Adds a separator line, or a hypen, to the menu at the current position.
334      * @see java.awt.Menu#insertSeparator(int)
335      */

336     public void addSeparator() {
337     add("-");
338     }
339
340     /**
341      * Inserts a separator at the specified position.
342      * @param index the position at which the
343      * menu separator should be inserted.
344      * @exception IllegalArgumentException if the value of
345      * <code>index</code> is less than 0.
346      * @see java.awt.Menu#addSeparator
347      * @since JDK1.1
348      */

349
350     public void insertSeparator(int index) {
351         synchronized (getTreeLock()) {
352         if (index < 0) {
353             throw new IllegalArgumentException JavaDoc("index less than zero.");
354         }
355
356         int nitems = getItemCount();
357         Vector JavaDoc tempItems = new Vector JavaDoc();
358
359         /* Remove the item at index, nitems-index times
360            storing them in a temporary vector in the
361            order they appear on the menu.
362         */

363         for (int i = index ; i < nitems; i++) {
364             tempItems.addElement(getItem(index));
365         remove(index);
366         }
367
368         addSeparator();
369
370         /* Add the removed items back to the menu, they are
371            already in the correct order in the temp vector.
372         */

373         for (int i = 0; i < tempItems.size() ; i++) {
374             add((MenuItem JavaDoc)tempItems.elementAt(i));
375         }
376     }
377     }
378
379     /**
380      * Removes the menu item at the specified index from this menu.
381      * @param index the position of the item to be removed.
382      */

383     public void remove(int index) {
384         synchronized (getTreeLock()) {
385         MenuItem JavaDoc mi = getItem(index);
386         items.removeElementAt(index);
387         MenuPeer peer = (MenuPeer)this.peer;
388         if (peer != null) {
389             mi.removeNotify();
390         mi.parent = null;
391         peer.delItem(index);
392         }
393     }
394     }
395
396     /**
397      * Removes the specified menu item from this menu.
398      * @param item the item to be removed from the menu.
399      * If <code>item</code> is <code>null</code>
400      * or is not in this menu, this method does
401      * nothing.
402      */

403     public void remove(MenuComponent JavaDoc item) {
404         synchronized (getTreeLock()) {
405         int index = items.indexOf(item);
406         if (index >= 0) {
407             remove(index);
408         }
409     }
410     }
411
412     /**
413      * Removes all items from this menu.
414      * @since JDK1.0.
415      */

416     public void removeAll() {
417         synchronized (getTreeLock()) {
418         int nitems = getItemCount();
419         for (int i = nitems-1 ; i >= 0 ; i--) {
420             remove(i);
421         }
422     }
423     }
424
425     /*
426      * Post an ActionEvent to the target of the MenuPeer
427      * associated with the specified keyboard event (on
428      * keydown). Returns true if there is an associated
429      * keyboard event.
430      */

431     boolean handleShortcut(KeyEvent JavaDoc e) {
432         int nitems = getItemCount();
433         for (int i = 0 ; i < nitems ; i++) {
434             MenuItem JavaDoc mi = getItem(i);
435             if (mi.handleShortcut(e)) {
436                 return true;
437             }
438         }
439         return false;
440     }
441
442     MenuItem JavaDoc getShortcutMenuItem(MenuShortcut JavaDoc s) {
443     int nitems = getItemCount();
444     for (int i = 0 ; i < nitems ; i++) {
445             MenuItem JavaDoc mi = getItem(i).getShortcutMenuItem(s);
446             if (mi != null) {
447                 return mi;
448             }
449     }
450         return null;
451     }
452
453     synchronized Enumeration JavaDoc shortcuts() {
454         Vector JavaDoc shortcuts = new Vector JavaDoc();
455         int nitems = getItemCount();
456     for (int i = 0 ; i < nitems ; i++) {
457             MenuItem JavaDoc mi = getItem(i);
458             if (mi instanceof Menu JavaDoc) {
459                 Enumeration JavaDoc e = ((Menu JavaDoc)mi).shortcuts();
460                 while (e.hasMoreElements()) {
461                     shortcuts.addElement(e.nextElement());
462                 }
463             } else {
464                 MenuShortcut JavaDoc ms = mi.getShortcut();
465                 if (ms != null) {
466                     shortcuts.addElement(ms);
467                 }
468             }
469     }
470         return shortcuts.elements();
471     }
472
473     void deleteShortcut(MenuShortcut JavaDoc s) {
474     int nitems = getItemCount();
475     for (int i = 0 ; i < nitems ; i++) {
476         getItem(i).deleteShortcut(s);
477     }
478     }
479
480
481     /* Serialization support. A MenuContainer is responsible for
482      * restoring the parent fields of its children.
483      */

484
485     /**
486      * The menu serialized Data Version.
487      *
488      * @serial
489      */

490     private int menuSerializedDataVersion = 1;
491
492     /**
493      * Writes default serializable fields to stream.
494      *
495      * @param s the <code>ObjectOutputStream</code> to write
496      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
497      * @see #readObject(ObjectInputStream)
498      */

499     private void writeObject(java.io.ObjectOutputStream JavaDoc s)
500       throws java.io.IOException JavaDoc
501     {
502       s.defaultWriteObject();
503     }
504
505     /**
506      * Reads the <code>ObjectInputStream</code>.
507      * Unrecognized keys or values will be ignored.
508      *
509      * @param s the <code>ObjectInputStream</code> to read
510      * @exception HeadlessException if
511      * <code>GraphicsEnvironment.isHeadless</code> returns
512      * <code>true</code>
513      * @see java.awt.GraphicsEnvironment#isHeadless
514      * @see #writeObject(ObjectOutputStream)
515      */

516     private void readObject(ObjectInputStream JavaDoc s)
517       throws IOException JavaDoc, ClassNotFoundException JavaDoc, HeadlessException JavaDoc
518     {
519       // HeadlessException will be thrown from MenuComponent's readObject
520
s.defaultReadObject();
521       for(int i = 0; i < items.size(); i++) {
522     MenuItem JavaDoc item = (MenuItem JavaDoc)items.elementAt(i);
523     item.parent = this;
524       }
525     }
526
527     /**
528      * Returns a string representing the state of this <code>Menu</code>.
529      * This method is intended to be used only for debugging purposes, and the
530      * content and format of the returned string may vary between
531      * implementations. The returned string may be empty but may not be
532      * <code>null</code>.
533      *
534      * @return the parameter string of this menu
535      */

536     public String JavaDoc paramString() {
537         String JavaDoc str = ",tearOff=" + tearOff+",isHelpMenu=" + isHelpMenu;
538         return super.paramString() + str;
539     }
540
541     /**
542      * Initialize JNI field and method IDs
543      */

544     private static native void initIDs();
545
546
547 /////////////////
548
// Accessibility support
549
////////////////
550

551     /**
552      * Gets the AccessibleContext associated with this Menu.
553      * For menus, the AccessibleContext takes the form of an
554      * AccessibleAWTMenu.
555      * A new AccessibleAWTMenu instance is created if necessary.
556      *
557      * @return an AccessibleAWTMenu that serves as the
558      * AccessibleContext of this Menu
559      */

560     public AccessibleContext getAccessibleContext() {
561         if (accessibleContext == null) {
562             accessibleContext = new AccessibleAWTMenu();
563         }
564         return accessibleContext;
565     }
566
567     /**
568      * Defined in MenuComponent. Overridden here.
569      */

570     int getAccessibleChildIndex(MenuComponent JavaDoc child) {
571         return items.indexOf(child);
572     }
573
574     /**
575      * Inner class of Menu used to provide default support for
576      * accessibility. This class is not meant to be used directly by
577      * application developers, but is instead meant only to be
578      * subclassed by menu component developers.
579      * <p>
580      * This class implements accessibility support for the
581      * <code>Menu</code> class. It provides an implementation of the
582      * Java Accessibility API appropriate to menu user-interface elements.
583      */

584     protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
585     {
586         /*
587          * JDK 1.3 serialVersionUID
588          */

589         private static final long serialVersionUID = 5228160894980069094L;
590
591         /**
592          * Get the role of this object.
593          *
594          * @return an instance of AccessibleRole describing the role of the
595          * object
596          */

597         public AccessibleRole getAccessibleRole() {
598             return AccessibleRole.MENU;
599         }
600
601     } // class AccessibleAWTMenu
602

603 }
604
Popular Tags