001    /* MenuBar.java -- An AWT menu bar class
002       Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.awt;
041    
042    import java.awt.peer.MenuBarPeer;
043    
044    import java.io.Serializable;
045    import java.util.Enumeration;
046    import java.util.Vector;
047    
048    import javax.accessibility.Accessible;
049    import javax.accessibility.AccessibleContext;
050    import javax.accessibility.AccessibleRole;
051    
052    /**
053      * This class implements a menu bar in the AWT system.
054      *
055      * @author Aaron M. Renn (arenn@urbanophile.com)
056      * @author Tom Tromey (tromey@redhat.com)
057      * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
058      */
059    public class MenuBar extends MenuComponent
060      implements MenuContainer, Serializable, Accessible
061    {
062    
063      // Serialization Constant
064      private static final long serialVersionUID = -4930327919388951260L;
065    
066      /**
067       * The number used to generate the name returned by getName.
068       */
069      private static transient long next_menubar_number;
070    
071      /**
072       * @serial The menu used for providing help information
073       */
074      private Menu helpMenu;
075    
076      /**
077       * @serial The menus contained in this menu bar.
078       */
079      private Vector menus = new Vector();
080    
081      /**
082       * Initializes a new instance of <code>MenuBar</code>.
083       *
084       * @throws HeadlessException if GraphicsEnvironment.isHeadless() is true
085       */
086      public MenuBar()
087      {
088        if (GraphicsEnvironment.isHeadless())
089          throw new HeadlessException();
090      }
091    
092      /**
093       * Returns the help menu for this menu bar.  This may be <code>null</code>.
094       *
095       * @return the help menu for this menu bar
096       */
097      public Menu getHelpMenu()
098      {
099        return helpMenu;
100      }
101    
102      /**
103       * Sets the help menu for this menu bar.
104       *
105       * @param menu the new help menu for this menu bar
106       */
107      public synchronized void setHelpMenu(Menu menu)
108      {
109        MenuBarPeer myPeer = (MenuBarPeer) getPeer ();
110    
111        if (helpMenu != null)
112          {
113            if (myPeer != null)
114              helpMenu.removeNotify();
115            helpMenu.setParent(null);
116          }
117        helpMenu = menu;
118    
119        MenuContainer parent = menu.getParent();
120        if (parent != null)
121          parent.remove(menu);
122        menu.setParent(this);
123    
124        if (myPeer != null)
125          {
126            menu.addNotify();
127            myPeer.addHelpMenu(menu);
128          }
129      }
130    
131      /**
132       * Add a menu to this MenuBar.  If the menu has already has a
133       * parent, it is first removed from its old parent before being
134       * added.
135       *
136       * @param menu the menu to add
137       *
138       * @return the menu that was added
139       */
140      public synchronized Menu add(Menu menu)
141      {
142        MenuBarPeer myPeer = (MenuBarPeer) getPeer ();
143    
144        MenuContainer parent = menu.getParent();
145        if (parent != null)
146          parent.remove(menu);
147    
148        menus.addElement(menu);
149        menu.setParent(this);
150    
151        if (myPeer != null)
152          {
153            menu.addNotify();
154            myPeer.addMenu(menu);
155          }
156        return menu;
157      }
158    
159      /**
160       * Removes the menu at the specified index.
161       *
162       * @param index the index of the menu to remove from the menu bar
163       */
164      public synchronized void remove(int index)
165      {
166        Menu m = (Menu) menus.remove(index);
167        MenuBarPeer mp = (MenuBarPeer) getPeer();
168    
169        if (mp != null)
170          m.removeNotify();
171    
172        m.setParent(null);
173    
174        if (mp != null)
175          mp.delMenu(index);
176      }
177    
178      /**
179       * Removes the specified menu from the menu bar.
180       *
181       * @param menu the menu to remove from the menu bar
182       */
183      public void remove(MenuComponent menu)
184      {
185        int index = menus.indexOf(menu);
186        if (index == -1)
187          return;
188    
189        remove(index);
190      }
191    
192      /**
193       * Returns the number of elements in this menu bar.
194       *
195       * @return the number of elements in the menu bar
196       */
197      public int getMenuCount()
198      {
199        return countMenus();
200      }
201    
202      /**
203       * Returns the number of elements in this menu bar.
204       *
205       * @return the number of elements in the menu bar
206       *
207       * @deprecated This method is deprecated in favor of
208       *             <code>getMenuCount()</code>.
209       */
210      public int countMenus()
211      {
212        return menus.size() + (getHelpMenu() == null ? 0 : 1);
213      }
214    
215      /**
216       * Returns the menu at the specified index.
217       *
218       * @param index the index of the menu
219       *
220       * @return the requested menu
221       *
222       * @throws ArrayIndexOutOfBoundsException if the index is not valid
223       */
224      public Menu getMenu(int index)
225      {
226        return (Menu) menus.elementAt(index);
227      }
228    
229      /**
230       * Creates this object's native peer.
231       */
232      public void addNotify()
233      {
234        MenuBarPeer peer = (MenuBarPeer) getPeer();
235        if (peer == null)
236          {
237            peer = getToolkit().createMenuBar(this);
238            setPeer(peer);
239          }
240    
241        Enumeration e = menus.elements();
242        while (e.hasMoreElements())
243          {
244            Menu mi = (Menu)e.nextElement();
245            mi.addNotify();
246            peer.addMenu(mi);
247          }
248    
249        if (helpMenu != null)
250          {
251            helpMenu.addNotify();
252            peer.addHelpMenu(helpMenu);
253          }
254      }
255    
256      /**
257       * Destroys this object's native peer.
258       */
259      public void removeNotify()
260      {
261        Enumeration e = menus.elements();
262        while (e.hasMoreElements())
263          {
264            Menu mi = (Menu) e.nextElement();
265            mi.removeNotify();
266          }
267        super.removeNotify();
268      }
269    
270      /**
271       * Returns a list of all shortcuts for the menus in this menu bar.
272       *
273       * @return a list of all shortcuts for the menus in this menu bar
274       */
275      public synchronized Enumeration<MenuShortcut> shortcuts()
276      {
277        Vector shortcuts = new Vector();
278        Enumeration e = menus.elements();
279    
280        while (e.hasMoreElements())
281          {
282            Menu menu = (Menu)e.nextElement();
283            if (menu.getShortcut() != null)
284              shortcuts.addElement(menu.getShortcut());
285          }
286    
287        return shortcuts.elements();
288      }
289    
290      /**
291       * Returns the menu item for the specified shortcut, or <code>null</code>
292       * if no such item exists.
293       *
294       * @param shortcut the shortcut to return the menu item for
295       *
296       * @return the menu item for the specified shortcut
297       */
298      public MenuItem getShortcutMenuItem(MenuShortcut shortcut)
299      {
300        Enumeration e = menus.elements();
301    
302        while (e.hasMoreElements())
303          {
304            Menu menu = (Menu) e.nextElement();
305            MenuShortcut s = menu.getShortcut();
306            if ((s != null) && s.equals(shortcut))
307              return menu;
308          }
309    
310        return null;
311      }
312    
313      /**
314       * Deletes the specified menu shortcut.
315       *
316       * @param shortcut the shortcut to delete
317       */
318      public void deleteShortcut(MenuShortcut shortcut)
319      {
320        MenuItem it;
321        // This is a slow implementation, but it probably doesn't matter.
322        while ((it = getShortcutMenuItem (shortcut)) != null)
323          it.deleteShortcut();
324      }
325    
326      /**
327       * Gets the AccessibleContext associated with this <code>MenuBar</code>.
328       * The context is created, if necessary.
329       *
330       * @return the associated context
331       */
332      public AccessibleContext getAccessibleContext()
333      {
334        // Create the context if this is the first request.
335        if (accessibleContext == null)
336          accessibleContext = new AccessibleAWTMenuBar();
337        return accessibleContext;
338      }
339    
340      /**
341       * Generate a unique name for this <code>MenuBar</code>.
342       *
343       * @return A unique name for this <code>MenuBar</code>.
344       */
345      String generateName()
346      {
347        return "menubar" + getUniqueLong();
348      }
349    
350      private static synchronized long getUniqueLong()
351      {
352        return next_menubar_number++;
353      }
354    
355      /**
356       * This class provides accessibility support for AWT menu bars.
357       *
358       * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
359       */
360      protected class AccessibleAWTMenuBar
361        extends AccessibleAWTMenuComponent
362      {
363    
364        /**
365         * Compatible with JDK 1.4.2 revision 5
366         */
367        private static final long serialVersionUID = -8577604491830083815L;
368    
369        /**
370         * This is the default constructor, which simply calls the default
371         * constructor of the superclass.
372         */
373        protected AccessibleAWTMenuBar()
374        {
375          super();
376        }
377    
378        /**
379         * Returns the accessible role relating to the menu bar.
380         *
381         * @return <code>AccessibleRole.MENU_BAR</code>
382         */
383        public AccessibleRole getAccessibleRole()
384        {
385          return AccessibleRole.MENU_BAR;
386        }
387    
388      }
389    
390    }