Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package java.awt;
   26   
   27   import java.io.IOException;
   28   import java.io.ObjectInputStream;
   29   import java.util.Vector;
   30   import java.util.Enumeration;
   31   import java.awt.peer.MenuPeer;
   32   import java.awt.event.KeyEvent;
   33   import javax.accessibility;
   34   
   35   /**
   36    * A <code>Menu</code> object is a pull-down menu component
   37    * that is deployed from a menu bar.
   38    * <p>
   39    * A menu can optionally be a <i>tear-off</i> menu. A tear-off menu
   40    * can be opened and dragged away from its parent menu bar or menu.
   41    * It remains on the screen after the mouse button has been released.
   42    * The mechanism for tearing off a menu is platform dependent, since
   43    * the look and feel of the tear-off menu is determined by its peer.
   44    * On platforms that do not support tear-off menus, the tear-off
   45    * property is ignored.
   46    * <p>
   47    * Each item in a menu must belong to the <code>MenuItem</code>
   48    * class. It can be an instance of <code>MenuItem</code>, a submenu
   49    * (an instance of <code>Menu</code>), or a check box (an instance of
   50    * <code>CheckboxMenuItem</code>).
   51    *
   52    * @author Sami Shaio
   53    * @see     java.awt.MenuItem
   54    * @see     java.awt.CheckboxMenuItem
   55    * @since   JDK1.0
   56    */
   57   public class Menu extends MenuItem implements MenuContainer, Accessible {
   58   
   59       static {
   60           /* ensure that the necessary native libraries are loaded */
   61           Toolkit.loadLibraries();
   62           if (!GraphicsEnvironment.isHeadless()) {
   63               initIDs();
   64           }
   65       }
   66   
   67       /**
   68        * A vector of the items that will be part of the Menu.
   69        *
   70        * @serial
   71        * @see #countItems()
   72        */
   73       Vector              items = new Vector();
   74   
   75       /**
   76        * This field indicates whether the menu has the
   77        * tear of property or not.  It will be set to
   78        * <code>true</code> if the menu has the tear off
   79        * property and it will be set to <code>false</code>
   80        * if it does not.
   81        * A torn off menu can be deleted by a user when
   82        * it is no longer needed.
   83        *
   84        * @serial
   85        * @see #isTearOff()
   86        */
   87       boolean             tearOff;
   88   
   89       /**
   90        * This field will be set to <code>true</code>
   91        * if the Menu in question is actually a help
   92        * menu.  Otherwise it will be set to <code>
   93        * false</code>.
   94        *
   95        * @serial
   96        */
   97       boolean             isHelpMenu;
   98   
   99       private static final String base = "menu";
  100       private static int nameCounter = 0;
  101   
  102       /*
  103        * JDK 1.1 serialVersionUID
  104        */
  105        private static final long serialVersionUID = -8809584163345499784L;
  106   
  107       /**
  108        * Constructs a new menu with an empty label. This menu is not
  109        * a tear-off menu.
  110        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  111        * returns true.
  112        * @see java.awt.GraphicsEnvironment#isHeadless
  113        * @since      JDK1.1
  114        */
  115       public Menu() throws HeadlessException {
  116           this("", false);
  117       }
  118   
  119       /**
  120        * Constructs a new menu with the specified label. This menu is not
  121        * a tear-off menu.
  122        * @param       label the menu's label in the menu bar, or in
  123        *                   another menu of which this menu is a submenu.
  124        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  125        * returns true.
  126        * @see java.awt.GraphicsEnvironment#isHeadless
  127        */
  128       public Menu(String label) throws HeadlessException {
  129           this(label, false);
  130       }
  131   
  132       /**
  133        * Constructs a new menu with the specified label,
  134        * indicating whether the menu can be torn off.
  135        * <p>
  136        * Tear-off functionality may not be supported by all
  137        * implementations of AWT.  If a particular implementation doesn't
  138        * support tear-off menus, this value is silently ignored.
  139        * @param       label the menu's label in the menu bar, or in
  140        *                   another menu of which this menu is a submenu.
  141        * @param       tearOff   if <code>true</code>, the menu
  142        *                   is a tear-off menu.
  143        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  144        * returns true.
  145        * @see java.awt.GraphicsEnvironment#isHeadless
  146        * @since       JDK1.0.
  147        */
  148       public Menu(String label, boolean tearOff) throws HeadlessException {
  149           super(label);
  150           this.tearOff = tearOff;
  151       }
  152   
  153       /**
  154        * Construct a name for this MenuComponent.  Called by getName() when
  155        * the name is null.
  156        */
  157       String constructComponentName() {
  158           synchronized (Menu.class) {
  159               return base + nameCounter++;
  160           }
  161       }
  162   
  163       /**
  164        * Creates the menu's peer.  The peer allows us to modify the
  165        * appearance of the menu without changing its functionality.
  166        */
  167       public void addNotify() {
  168           synchronized (getTreeLock()) {
  169               if (peer == null)
  170                   peer = Toolkit.getDefaultToolkit().createMenu(this);
  171               int nitems = getItemCount();
  172               for (int i = 0 ; i < nitems ; i++) {
  173                   MenuItem mi = getItem(i);
  174                   mi.parent = this;
  175                   mi.addNotify();
  176               }
  177           }
  178       }
  179   
  180       /**
  181        * Removes the menu's peer.  The peer allows us to modify the appearance
  182        * of the menu without changing its functionality.
  183        */
  184       public void removeNotify() {
  185           synchronized (getTreeLock()) {
  186               int nitems = getItemCount();
  187               for (int i = 0 ; i < nitems ; i++) {
  188                   getItem(i).removeNotify();
  189               }
  190               super.removeNotify();
  191           }
  192       }
  193   
  194       /**
  195        * Indicates whether this menu is a tear-off menu.
  196        * <p>
  197        * Tear-off functionality may not be supported by all
  198        * implementations of AWT.  If a particular implementation doesn't
  199        * support tear-off menus, this value is silently ignored.
  200        * @return      <code>true</code> if this is a tear-off menu;
  201        *                         <code>false</code> otherwise.
  202        */
  203       public boolean isTearOff() {
  204           return tearOff;
  205       }
  206   
  207       /**
  208         * Get the number of items in this menu.
  209         * @return     the number of items in this menu.
  210         * @since      JDK1.1
  211         */
  212       public int getItemCount() {
  213           return countItems();
  214       }
  215   
  216       /**
  217        * @deprecated As of JDK version 1.1,
  218        * replaced by <code>getItemCount()</code>.
  219        */
  220       @Deprecated
  221       public int countItems() {
  222           return countItemsImpl();
  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 int countItemsImpl() {
  230           return items.size();
  231       }
  232   
  233       /**
  234        * Gets the item located at the specified index of this menu.
  235        * @param     index the position of the item to be returned.
  236        * @return    the item located at the specified index.
  237        */
  238       public MenuItem getItem(int index) {
  239           return getItemImpl(index);
  240       }
  241   
  242       /*
  243        * This is called by the native code, so client code can't
  244        * be called on the toolkit thread.
  245        */
  246       final MenuItem getItemImpl(int index) {
  247           return (MenuItem)items.elementAt(index);
  248       }
  249   
  250       /**
  251        * Adds the specified menu item to this menu. If the
  252        * menu item has been part of another menu, removes it
  253        * from that menu.
  254        *
  255        * @param       mi   the menu item to be added
  256        * @return      the menu item added
  257        * @see         java.awt.Menu#insert(java.lang.String, int)
  258        * @see         java.awt.Menu#insert(java.awt.MenuItem, int)
  259        */
  260       public MenuItem add(MenuItem mi) {
  261           synchronized (getTreeLock()) {
  262               if (mi.parent != null) {
  263                   mi.parent.remove(mi);
  264               }
  265               items.addElement(mi);
  266               mi.parent = this;
  267               MenuPeer peer = (MenuPeer)this.peer;
  268               if (peer != null) {
  269                   mi.addNotify();
  270                   peer.addItem(mi);
  271               }
  272               return mi;
  273           }
  274       }
  275   
  276       /**
  277        * Adds an item with the specified label to this menu.
  278        *
  279        * @param       label   the text on the item
  280        * @see         java.awt.Menu#insert(java.lang.String, int)
  281        * @see         java.awt.Menu#insert(java.awt.MenuItem, int)
  282        */
  283       public void add(String label) {
  284           add(new MenuItem(label));
  285       }
  286   
  287       /**
  288        * Inserts a menu item into this menu
  289        * at the specified position.
  290        *
  291        * @param         menuitem  the menu item to be inserted.
  292        * @param         index     the position at which the menu
  293        *                          item should be inserted.
  294        * @see           java.awt.Menu#add(java.lang.String)
  295        * @see           java.awt.Menu#add(java.awt.MenuItem)
  296        * @exception     IllegalArgumentException if the value of
  297        *                    <code>index</code> is less than zero
  298        * @since         JDK1.1
  299        */
  300   
  301       public void insert(MenuItem menuitem, int index) {
  302           synchronized (getTreeLock()) {
  303               if (index < 0) {
  304                   throw new IllegalArgumentException("index less than zero.");
  305               }
  306   
  307               int nitems = getItemCount();
  308               Vector tempItems = new Vector();
  309   
  310               /* Remove the item at index, nitems-index times
  311                  storing them in a temporary vector in the
  312                  order they appear on the menu.
  313               */
  314               for (int i = index ; i < nitems; i++) {
  315                   tempItems.addElement(getItem(index));
  316                   remove(index);
  317               }
  318   
  319               add(menuitem);
  320   
  321               /* Add the removed items back to the menu, they are
  322                  already in the correct order in the temp vector.
  323               */
  324               for (int i = 0; i < tempItems.size()  ; i++) {
  325                   add((MenuItem)tempItems.elementAt(i));
  326               }
  327           }
  328       }
  329   
  330       /**
  331        * Inserts a menu item with the specified label into this menu
  332        * at the specified position.  This is a convenience method for
  333        * <code>insert(menuItem, index)</code>.
  334        *
  335        * @param       label the text on the item
  336        * @param       index the position at which the menu item
  337        *                      should be inserted
  338        * @see         java.awt.Menu#add(java.lang.String)
  339        * @see         java.awt.Menu#add(java.awt.MenuItem)
  340        * @exception     IllegalArgumentException if the value of
  341        *                    <code>index</code> is less than zero
  342        * @since       JDK1.1
  343        */
  344   
  345       public void insert(String label, int index) {
  346           insert(new MenuItem(label), index);
  347       }
  348   
  349       /**
  350        * Adds a separator line, or a hypen, to the menu at the current position.
  351        * @see         java.awt.Menu#insertSeparator(int)
  352        */
  353       public void addSeparator() {
  354           add("-");
  355       }
  356   
  357       /**
  358        * Inserts a separator at the specified position.
  359        * @param       index the position at which the
  360        *                       menu separator should be inserted.
  361        * @exception   IllegalArgumentException if the value of
  362        *                       <code>index</code> is less than 0.
  363        * @see         java.awt.Menu#addSeparator
  364        * @since       JDK1.1
  365        */
  366   
  367       public void insertSeparator(int index) {
  368           synchronized (getTreeLock()) {
  369               if (index < 0) {
  370                   throw new IllegalArgumentException("index less than zero.");
  371               }
  372   
  373               int nitems = getItemCount();
  374               Vector tempItems = new Vector();
  375   
  376               /* Remove the item at index, nitems-index times
  377                  storing them in a temporary vector in the
  378                  order they appear on the menu.
  379               */
  380               for (int i = index ; i < nitems; i++) {
  381                   tempItems.addElement(getItem(index));
  382                   remove(index);
  383               }
  384   
  385               addSeparator();
  386   
  387               /* Add the removed items back to the menu, they are
  388                  already in the correct order in the temp vector.
  389               */
  390               for (int i = 0; i < tempItems.size()  ; i++) {
  391                   add((MenuItem)tempItems.elementAt(i));
  392               }
  393           }
  394       }
  395   
  396       /**
  397        * Removes the menu item at the specified index from this menu.
  398        * @param       index the position of the item to be removed.
  399        */
  400       public void remove(int index) {
  401           synchronized (getTreeLock()) {
  402               MenuItem mi = getItem(index);
  403               items.removeElementAt(index);
  404               MenuPeer peer = (MenuPeer)this.peer;
  405               if (peer != null) {
  406                   mi.removeNotify();
  407                   mi.parent = null;
  408                   peer.delItem(index);
  409               }
  410           }
  411       }
  412   
  413       /**
  414        * Removes the specified menu item from this menu.
  415        * @param  item the item to be removed from the menu.
  416        *         If <code>item</code> is <code>null</code>
  417        *         or is not in this menu, this method does
  418        *         nothing.
  419        */
  420       public void remove(MenuComponent item) {
  421           synchronized (getTreeLock()) {
  422               int index = items.indexOf(item);
  423               if (index >= 0) {
  424                   remove(index);
  425               }
  426           }
  427       }
  428   
  429       /**
  430        * Removes all items from this menu.
  431        * @since       JDK1.0.
  432        */
  433       public void removeAll() {
  434           synchronized (getTreeLock()) {
  435               int nitems = getItemCount();
  436               for (int i = nitems-1 ; i >= 0 ; i--) {
  437                   remove(i);
  438               }
  439           }
  440       }
  441   
  442       /*
  443        * Post an ActionEvent to the target of the MenuPeer
  444        * associated with the specified keyboard event (on
  445        * keydown).  Returns true if there is an associated
  446        * keyboard event.
  447        */
  448       boolean handleShortcut(KeyEvent e) {
  449           int nitems = getItemCount();
  450           for (int i = 0 ; i < nitems ; i++) {
  451               MenuItem mi = getItem(i);
  452               if (mi.handleShortcut(e)) {
  453                   return true;
  454               }
  455           }
  456           return false;
  457       }
  458   
  459       MenuItem getShortcutMenuItem(MenuShortcut s) {
  460           int nitems = getItemCount();
  461           for (int i = 0 ; i < nitems ; i++) {
  462               MenuItem mi = getItem(i).getShortcutMenuItem(s);
  463               if (mi != null) {
  464                   return mi;
  465               }
  466           }
  467           return null;
  468       }
  469   
  470       synchronized Enumeration shortcuts() {
  471           Vector shortcuts = new Vector();
  472           int nitems = getItemCount();
  473           for (int i = 0 ; i < nitems ; i++) {
  474               MenuItem mi = getItem(i);
  475               if (mi instanceof Menu) {
  476                   Enumeration e = ((Menu)mi).shortcuts();
  477                   while (e.hasMoreElements()) {
  478                       shortcuts.addElement(e.nextElement());
  479                   }
  480               } else {
  481                   MenuShortcut ms = mi.getShortcut();
  482                   if (ms != null) {
  483                       shortcuts.addElement(ms);
  484                   }
  485               }
  486           }
  487           return shortcuts.elements();
  488       }
  489   
  490       void deleteShortcut(MenuShortcut s) {
  491           int nitems = getItemCount();
  492           for (int i = 0 ; i < nitems ; i++) {
  493               getItem(i).deleteShortcut(s);
  494           }
  495       }
  496   
  497   
  498       /* Serialization support.  A MenuContainer is responsible for
  499        * restoring the parent fields of its children.
  500        */
  501   
  502       /**
  503        * The menu serialized Data Version.
  504        *
  505        * @serial
  506        */
  507       private int menuSerializedDataVersion = 1;
  508   
  509       /**
  510        * Writes default serializable fields to stream.
  511        *
  512        * @param s the <code>ObjectOutputStream</code> to write
  513        * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  514        * @see #readObject(ObjectInputStream)
  515        */
  516       private void writeObject(java.io.ObjectOutputStream s)
  517         throws java.io.IOException
  518       {
  519         s.defaultWriteObject();
  520       }
  521   
  522       /**
  523        * Reads the <code>ObjectInputStream</code>.
  524        * Unrecognized keys or values will be ignored.
  525        *
  526        * @param s the <code>ObjectInputStream</code> to read
  527        * @exception HeadlessException if
  528        *   <code>GraphicsEnvironment.isHeadless</code> returns
  529        *   <code>true</code>
  530        * @see java.awt.GraphicsEnvironment#isHeadless
  531        * @see #writeObject(ObjectOutputStream)
  532        */
  533       private void readObject(ObjectInputStream s)
  534         throws IOException, ClassNotFoundException, HeadlessException
  535       {
  536         // HeadlessException will be thrown from MenuComponent's readObject
  537         s.defaultReadObject();
  538         for(int i = 0; i < items.size(); i++) {
  539           MenuItem item = (MenuItem)items.elementAt(i);
  540           item.parent = this;
  541         }
  542       }
  543   
  544       /**
  545        * Returns a string representing the state of this <code>Menu</code>.
  546        * This method is intended to be used only for debugging purposes, and the
  547        * content and format of the returned string may vary between
  548        * implementations. The returned string may be empty but may not be
  549        * <code>null</code>.
  550        *
  551        * @return the parameter string of this menu
  552        */
  553       public String paramString() {
  554           String str = ",tearOff=" + tearOff+",isHelpMenu=" + isHelpMenu;
  555           return super.paramString() + str;
  556       }
  557   
  558       /**
  559        * Initialize JNI field and method IDs
  560        */
  561       private static native void initIDs();
  562   
  563   
  564   /////////////////
  565   // Accessibility support
  566   ////////////////
  567   
  568       /**
  569        * Gets the AccessibleContext associated with this Menu.
  570        * For menus, the AccessibleContext takes the form of an
  571        * AccessibleAWTMenu.
  572        * A new AccessibleAWTMenu instance is created if necessary.
  573        *
  574        * @return an AccessibleAWTMenu that serves as the
  575        *         AccessibleContext of this Menu
  576        * @since 1.3
  577        */
  578       public AccessibleContext getAccessibleContext() {
  579           if (accessibleContext == null) {
  580               accessibleContext = new AccessibleAWTMenu();
  581           }
  582           return accessibleContext;
  583       }
  584   
  585       /**
  586        * Defined in MenuComponent. Overridden here.
  587        */
  588       int getAccessibleChildIndex(MenuComponent child) {
  589           return items.indexOf(child);
  590       }
  591   
  592       /**
  593        * Inner class of Menu used to provide default support for
  594        * accessibility.  This class is not meant to be used directly by
  595        * application developers, but is instead meant only to be
  596        * subclassed by menu component developers.
  597        * <p>
  598        * This class implements accessibility support for the
  599        * <code>Menu</code> class.  It provides an implementation of the
  600        * Java Accessibility API appropriate to menu user-interface elements.
  601        * @since 1.3
  602        */
  603       protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
  604       {
  605           /*
  606            * JDK 1.3 serialVersionUID
  607            */
  608           private static final long serialVersionUID = 5228160894980069094L;
  609   
  610           /**
  611            * Get the role of this object.
  612            *
  613            * @return an instance of AccessibleRole describing the role of the
  614            * object
  615            */
  616           public AccessibleRole getAccessibleRole() {
  617               return AccessibleRole.MENU;
  618           }
  619   
  620       } // class AccessibleAWTMenu
  621   
  622   }

Home » openjdk-7 » java » awt » [javadoc | source]