Source for java.awt.Menu

   1: /* Menu.java -- A Java AWT Menu
   2:    Copyright (C) 1999, 2002, 2004, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt;
  40: 
  41: import java.awt.peer.MenuPeer;
  42: import java.io.Serializable;
  43: import java.util.Enumeration;
  44: import java.util.Vector;
  45: 
  46: import javax.accessibility.AccessibleContext;
  47: import javax.accessibility.AccessibleRole;
  48: 
  49: /**
  50:   * This class represents a pull down or tear off menu in Java's AWT.
  51:   *
  52:   * @author Aaron M. Renn (arenn@urbanophile.com)
  53:   */
  54: public class Menu extends MenuItem implements MenuContainer, Serializable
  55: {
  56: 
  57:   /**
  58:    * The number used to generate the name returned by getName.
  59:    */
  60:   private static transient long next_menu_number;
  61: 
  62:   // Serialization Constant
  63:   private static final long serialVersionUID = -8809584163345499784L;
  64: 
  65:   /**
  66:     * @serial The actual items in the menu
  67:     */
  68:   private Vector items = new Vector();
  69: 
  70:   /**
  71:    * @serial Flag indicating whether or not this menu is a tear off
  72:    */
  73:   private boolean tearOff;
  74: 
  75:   /**
  76:    * @serial Indicates whether or not this is a help menu.
  77:    */
  78:   private boolean isHelpMenu;
  79: 
  80:   /*
  81:    * @serial Unused in this implementation, but present in Sun's
  82:    * serialization spec.  Value obtained via reflection.
  83:    */
  84:   private int menuSerializedDataVersion = 1;
  85: 
  86:   static final transient String separatorLabel = "-";
  87: 
  88:   /**
  89:    * Initializes a new instance of <code>Menu</code> with no label and that
  90:    * is not a tearoff;
  91:    *
  92:    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
  93:    */
  94:   public Menu()
  95:   {
  96:   }
  97: 
  98:   /**
  99:    * Initializes a new instance of <code>Menu</code> that is not a tearoff and
 100:    * that has the specified label.
 101:    *
 102:    * @param label The menu label.
 103:    *
 104:    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 105:    */
 106:   public Menu(String label)
 107:   {
 108:     this(label, false);
 109:   }
 110: 
 111:   /**
 112:    * Initializes a new instance of <code>Menu</code> with the specified
 113:    * label and tearoff status.
 114:    *
 115:    * @param label The label for this menu
 116:    * @param isTearOff <code>true</code> if this menu is a tear off menu,
 117:    * <code>false</code> otherwise.
 118:    *
 119:    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 120:    */
 121:   public Menu(String label, boolean isTearOff)
 122:   {
 123:     super(label);
 124: 
 125:     tearOff = isTearOff;
 126: 
 127:     if (label.equals("Help"))
 128:       isHelpMenu = true;
 129: 
 130:     if (GraphicsEnvironment.isHeadless())
 131:       throw new HeadlessException();
 132:   }
 133: 
 134:   /**
 135:    * Tests whether or not this menu is a tearoff.
 136:    *
 137:    * @return <code>true</code> if this menu is a tearoff, <code>false</code>
 138:    * otherwise.
 139:    */
 140:   public boolean isTearOff()
 141:   {
 142:     return(tearOff);
 143:   }
 144: 
 145:   /**
 146:    * Returns the number of items in this menu.
 147:    *
 148:    * @return The number of items in this menu.
 149:    */
 150:   public int getItemCount()
 151:   {
 152:     return countItems();
 153:   }
 154: 
 155:   /**
 156:    * Returns the number of items in this menu.
 157:    *
 158:    * @return The number of items in this menu.
 159:    *
 160:    * @deprecated As of JDK 1.1, replaced by getItemCount().
 161:    */
 162:   public int countItems()
 163:   {
 164:     return items.size();
 165:   }
 166:  
 167:   /**
 168:    * Returns the item at the specified index.
 169:    * 
 170:    * @param index  the item index.
 171:    *
 172:    * @return The item at the specified index.
 173:    *
 174:    * @exception ArrayIndexOutOfBoundsException If the index value is not valid.
 175:    */
 176:   public MenuItem getItem(int index)
 177:   {
 178:     return((MenuItem) items.elementAt(index));
 179:   }
 180: 
 181:   /**
 182:    * Adds the specified item to this menu.  If it was previously part of
 183:    * another menu, it is first removed from that menu.
 184:    *
 185:    * @param item The new item to add.
 186:    *
 187:    * @return The item that was added.
 188:    */
 189:   public MenuItem add(MenuItem item)
 190:   {
 191:     MenuContainer parent = item.getParent();
 192:     if (parent != null)
 193:       parent.remove(item);
 194: 
 195:     items.addElement(item);
 196:     item.setParent(this);
 197: 
 198:     if (peer != null)
 199:       {
 200:         item.addNotify();
 201:         MenuPeer mp = (MenuPeer) peer;
 202:         mp.addItem(item);
 203:       }
 204: 
 205:     return item;
 206:   }
 207: 
 208:   /**
 209:    * Add an item with the specified label to this menu.
 210:    *
 211:    * @param label The label of the menu item to add.
 212:    */
 213:   public void add(String label)
 214:   {
 215:     add(new MenuItem(label));
 216:   }
 217: 
 218:   /**
 219:    * Inserts the specified menu item into this menu at the specified index.  If
 220:    * the index is greater than or equal to the number of items already in the
 221:    * menu, the new item is added as the last item in the menu.
 222:    *
 223:    * @param item The menu item to add (<code>null</code> not permitted).
 224:    * @param index The index of the menu item (>= 0).
 225:    *
 226:    * @throws IllegalArgumentException if the index is less than zero.
 227:    * @throws NullPointerException if <code>item</code> is <code>null</code>.
 228:    */
 229:   public void insert(MenuItem item, int index)
 230:   {
 231:     if (index < 0)
 232:       throw new IllegalArgumentException("Index is less than zero");
 233: 
 234:     int count = getItemCount();
 235: 
 236:     if (index >= count)
 237:       add(item);
 238:     else
 239:       {
 240:         MenuContainer parent = item.getParent();
 241:         if (parent != null)
 242:           parent.remove(item);
 243:       
 244:         items.insertElementAt(item, index);
 245:         item.setParent(this);
 246: 
 247:         MenuPeer peer = (MenuPeer) getPeer();
 248:         if (peer == null)
 249:           return;
 250: 
 251:         for (int i = count - 1; i >= index; i--)
 252:           peer.delItem(i);
 253: 
 254:         item.addNotify();
 255:         peer.addItem(item);
 256: 
 257:         // bear in mind that count is the number of items *before* the new
 258:         // item was added
 259:         for (int i = index + 1; i <= count; i++)
 260:           peer.addItem((MenuItem) items.elementAt(i));
 261:       }
 262: 
 263:   }
 264: 
 265:   /**
 266:    * Inserts an item with the specified label into this menu at the specified 
 267:    * index.  If the index is greater than or equal to the number of items 
 268:    * already in the menu, the new item is added as the last item in the menu.
 269:    *
 270:    * @param label The label of the item to add.
 271:    * @param index The index of the menu item (>= 0).
 272:    *
 273:    * @throws IllegalArgumentException If the index is less than zero.
 274:    */
 275:   public void insert(String label, int index)
 276:   {
 277:     insert(new MenuItem(label), index);
 278:   }
 279: 
 280:   /**
 281:    * Adds a separator bar at the current menu location.
 282:    */
 283:   public void addSeparator()
 284:   {
 285:     add(new MenuItem(separatorLabel));
 286:   }
 287: 
 288:   /**
 289:    * Inserts a separator bar at the specified index value.
 290:    *
 291:    * @param index The index at which to insert a separator bar.
 292:    *
 293:    * @exception IllegalArgumentException If the index is less than zero.
 294:    * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
 295:    */
 296:   public void insertSeparator(int index)
 297:   {
 298:     insert(new MenuItem(separatorLabel), index);
 299:   }
 300: 
 301:   /**
 302:    * Deletes the item at the specified index from this menu.
 303:    *
 304:    * @param index The index of the item to remove.
 305:    * 
 306:    * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
 307:    */
 308:   public synchronized void remove(int index)
 309:   {
 310:     MenuItem item = (MenuItem) items.remove(index);
 311: 
 312:     MenuPeer mp = (MenuPeer) getPeer();
 313:     if (mp != null)
 314:       {
 315:         mp.delItem(index);
 316:         item.removeNotify();
 317:       }
 318:     item.setParent(null);
 319:   }
 320: 
 321:   /**
 322:    * Removes the specifed item from the menu.  If the specified component
 323:    * does not exist, this method does nothing.
 324:    *
 325:    * @param item The component to remove.
 326:    */
 327:   public void remove(MenuComponent item)
 328:   {
 329:     int index = items.indexOf(item);
 330:     if (index == -1)
 331:       return;
 332: 
 333:     remove(index);
 334:   }
 335: 
 336:   /**
 337:    * Removes all the elements from this menu.
 338:    */
 339:   public synchronized void removeAll()
 340:   {
 341:     int count = getItemCount();
 342:     for(int i = 0; i < count; i++)
 343:       {
 344:         // We must always remove item 0.
 345:         remove(0);
 346:       }
 347:   }
 348: 
 349:   /**
 350:    * Creates the native peer for this object.
 351:    */
 352:   public void addNotify()
 353:   {
 354:     MenuPeer peer = (MenuPeer) getPeer();
 355:     if (peer == null)
 356:       {
 357:         peer = getToolkit().createMenu(this);
 358:         setPeer(peer);
 359:       }
 360: 
 361:     Enumeration e = items.elements();
 362:     while (e.hasMoreElements())
 363:     {
 364:       MenuItem mi = (MenuItem)e.nextElement();
 365:       mi.addNotify();
 366:       peer.addItem(mi);
 367:     }
 368: 
 369:     super.addNotify();
 370:   }
 371: 
 372:   /**
 373:    * Destroys the native peer for this object.
 374:    */
 375:   public void removeNotify()
 376:   {
 377:     Enumeration e = items.elements();
 378:     while (e.hasMoreElements())
 379:     {
 380:       MenuItem mi = (MenuItem) e.nextElement();
 381:       mi.removeNotify();
 382:     }
 383:     super.removeNotify();
 384:   }
 385: 
 386:   /**
 387:    * Returns a debugging string for this menu.
 388:    *
 389:    * @return A debugging string for this menu.
 390:    */
 391:   public String paramString()
 392:   {
 393:     return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu
 394:         + super.paramString());
 395:   }
 396: 
 397:   /**
 398:    * Basic Accessibility class for Menu.  Details get provided in derived
 399:    * classes.
 400:    */
 401:   protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
 402:   {
 403:     private static final long serialVersionUID = 5228160894980069094L;
 404: 
 405:     protected AccessibleAWTMenu()
 406:     {
 407:     }
 408:     
 409:     public AccessibleRole getAccessibleRole()
 410:     {
 411:       return AccessibleRole.MENU;
 412:     }
 413:   }
 414: 
 415:   /**
 416:    * Gets the AccessibleContext associated with this <code>Menu</code>.
 417:    * The context is created, if necessary.
 418:    *
 419:    * @return the associated context
 420:    */
 421:   public AccessibleContext getAccessibleContext()
 422:   {
 423:     /* Create the context if this is the first request */
 424:     if (accessibleContext == null)
 425:       accessibleContext = new AccessibleAWTMenu();
 426:     return accessibleContext;
 427:   }
 428:   
 429:   /**
 430:    * Generate a unique name for this <code>Menu</code>.
 431:    *
 432:    * @return A unique name for this <code>Menu</code>.
 433:    */
 434:   String generateName()
 435:   {
 436:     return "menu" + getUniqueLong();
 437:   }
 438: 
 439:   private static synchronized long getUniqueLong()
 440:   {
 441:     return next_menu_number++;
 442:   }
 443:   
 444: } // class Menu