Frames | No Frames |
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