Frames | No Frames |
1: /* Choice.java -- Java choice button widget. 2: Copyright (C) 1999, 2000, 2001, 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.event.ItemEvent; 42: import java.awt.event.ItemListener; 43: import java.awt.peer.ChoicePeer; 44: import java.io.Serializable; 45: import java.util.EventListener; 46: import java.util.Vector; 47: 48: import javax.accessibility.Accessible; 49: import javax.accessibility.AccessibleAction; 50: import javax.accessibility.AccessibleContext; 51: import javax.accessibility.AccessibleRole; 52: 53: /** 54: * This class implements a drop down choice list. 55: * 56: * @author Aaron M. Renn (arenn@urbanophile.com) 57: */ 58: public class Choice extends Component 59: implements ItemSelectable, Serializable, Accessible 60: { 61: /** 62: * The number used to generate the name returned by getName. 63: */ 64: private static transient long next_choice_number; 65: 66: // Serialization constant 67: private static final long serialVersionUID = -4075310674757313071L; 68: 69: /** 70: * @serial A list of items for the choice box, which can be <code>null</code>. 71: * This is package-private to avoid an accessor method. 72: */ 73: Vector pItems = new Vector(); 74: 75: /** 76: * @serial The index of the selected item in the choice box. 77: */ 78: private int selectedIndex = -1; 79: 80: /** 81: * ItemListener chain 82: */ 83: private ItemListener item_listeners; 84: 85: /** 86: * This class provides accessibility support for the 87: * combo box. 88: * 89: * @author Jerry Quinn (jlquinn@optonline.net) 90: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 91: */ 92: protected class AccessibleAWTChoice 93: extends AccessibleAWTComponent 94: implements AccessibleAction 95: { 96: 97: /** 98: * Serialization constant to match JDK 1.5 99: */ 100: private static final long serialVersionUID = 7175603582428509322L; 101: 102: /** 103: * Default constructor which simply calls the 104: * super class for generic component accessibility 105: * handling. 106: */ 107: public AccessibleAWTChoice() 108: { 109: super(); 110: } 111: 112: /** 113: * Returns an implementation of the <code>AccessibleAction</code> 114: * interface for this accessible object. In this case, the 115: * current instance is simply returned (with a more appropriate 116: * type), as it also implements the accessible action as well as 117: * the context. 118: * 119: * @return the accessible action associated with this context. 120: * @see javax.accessibility.AccessibleAction 121: */ 122: public AccessibleAction getAccessibleAction() 123: { 124: return this; 125: } 126: 127: /** 128: * Returns the role of this accessible object. 129: * 130: * @return the instance of <code>AccessibleRole</code>, 131: * which describes this object. 132: * @see javax.accessibility.AccessibleRole 133: */ 134: public AccessibleRole getAccessibleRole() 135: { 136: return AccessibleRole.COMBO_BOX; 137: } 138: 139: /** 140: * Returns the number of actions associated with this accessible 141: * object. In this case, it is the number of choices available. 142: * 143: * @return the number of choices available. 144: * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() 145: */ 146: public int getAccessibleActionCount() 147: { 148: return pItems.size(); 149: } 150: 151: /** 152: * Returns a description of the action with the supplied id. 153: * In this case, it is the text used in displaying the particular 154: * choice on-screen. 155: * 156: * @param i the id of the choice whose description should be 157: * retrieved. 158: * @return the <code>String</code> used to describe the choice. 159: * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) 160: */ 161: public String getAccessibleActionDescription(int i) 162: { 163: return (String) pItems.get(i); 164: } 165: 166: /** 167: * Executes the action with the specified id. In this case, 168: * calling this method provides the same behaviour as would 169: * choosing a choice from the list in a visual manner. 170: * 171: * @param i the id of the choice to select. 172: * @return true if a valid choice was specified. 173: * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) 174: */ 175: public boolean doAccessibleAction(int i) 176: { 177: if (i < 0 || i >= pItems.size()) 178: return false; 179: 180: Choice.this.select( i ); 181: 182: return true; 183: } 184: } 185: 186: /** 187: * Initializes a new instance of <code>Choice</code>. 188: * 189: * @exception HeadlessException If GraphicsEnvironment.isHeadless() 190: * returns true 191: */ 192: public Choice() 193: { 194: if (GraphicsEnvironment.isHeadless()) 195: throw new HeadlessException (); 196: } 197: 198: /** 199: * Returns the number of items in the list. 200: * 201: * @return The number of items in the list. 202: */ 203: public int getItemCount() 204: { 205: return countItems (); 206: } 207: 208: /** 209: * Returns the number of items in the list. 210: * 211: * @return The number of items in the list. 212: * 213: * @deprecated This method is deprecated in favor of <code>getItemCount</code>. 214: */ 215: public int countItems() 216: { 217: return pItems.size(); 218: } 219: 220: /** 221: * Returns the item at the specified index in the list. 222: * 223: * @param index The index into the list to return the item from. 224: * 225: * @exception ArrayIndexOutOfBoundsException If the index is invalid. 226: */ 227: public String getItem(int index) 228: { 229: return (String)pItems.elementAt(index); 230: } 231: 232: /** 233: * Adds the specified item to this choice box. 234: * 235: * @param item The item to add. 236: * 237: * @exception NullPointerException If the item's value is null 238: * 239: * @since 1.1 240: */ 241: public synchronized void add(String item) 242: { 243: if (item == null) 244: throw new NullPointerException ("item must be non-null"); 245: 246: pItems.addElement(item); 247: 248: if (peer != null) 249: ((ChoicePeer) peer).add(item, getItemCount() - 1); 250: 251: if (selectedIndex == -1) 252: select( 0 ); 253: } 254: 255: /** 256: * Adds the specified item to this choice box. 257: * 258: * This method is oboslete since Java 2 platform 1.1. Please use 259: * {@link #add(String)} instead. 260: * 261: * @param item The item to add. 262: * 263: * @exception NullPointerException If the item's value is equal to null 264: */ 265: public synchronized void addItem(String item) 266: { 267: add(item); 268: } 269: 270: /** Inserts an item into this Choice. Existing items are shifted 271: * upwards. If the new item is the only item, then it is selected. 272: * If the currently selected item is shifted, then the first item is 273: * selected. If the currently selected item is not shifted, then it 274: * remains selected. 275: * 276: * @param item The item to add. 277: * @param index The index at which the item should be inserted. 278: * 279: * @exception IllegalArgumentException If index is less than 0 280: */ 281: public synchronized void insert(String item, int index) 282: { 283: if (index < 0) 284: throw new IllegalArgumentException ("index may not be less then 0"); 285: 286: if (index > getItemCount ()) 287: index = getItemCount (); 288: 289: pItems.insertElementAt(item, index); 290: 291: if (peer != null) 292: ((ChoicePeer) peer).add (item, index); 293: 294: if (selectedIndex == -1 || selectedIndex >= index) 295: select(0); 296: } 297: 298: /** 299: * Removes the specified item from the choice box. 300: * 301: * @param item The item to remove. 302: * 303: * @exception IllegalArgumentException If the specified item doesn't exist. 304: */ 305: public synchronized void remove(String item) 306: { 307: int index = pItems.indexOf(item); 308: if (index == -1) 309: throw new IllegalArgumentException ("item \"" 310: + item + "\" not found in Choice"); 311: remove(index); 312: } 313: 314: /** 315: * Removes the item at the specified index from the choice box. 316: * 317: * @param index The index of the item to remove. 318: * 319: * @exception IndexOutOfBoundsException If the index is not valid. 320: */ 321: public synchronized void remove(int index) 322: { 323: pItems.removeElementAt(index); 324: 325: if (peer != null) 326: ((ChoicePeer) peer).remove( index ); 327: 328: if( getItemCount() == 0 ) 329: selectedIndex = -1; 330: else 331: { 332: if( selectedIndex > index ) 333: selectedIndex--; 334: else if( selectedIndex == index ) 335: selectedIndex = 0; 336: 337: if( peer != null ) 338: ((ChoicePeer)peer).select( selectedIndex ); 339: } 340: } 341: 342: /** 343: * Removes all of the objects from this choice box. 344: */ 345: public synchronized void removeAll() 346: { 347: if (getItemCount() <= 0) 348: return; 349: 350: pItems.removeAllElements (); 351: 352: if (peer != null) 353: { 354: ChoicePeer cp = (ChoicePeer) peer; 355: cp.removeAll (); 356: } 357: 358: selectedIndex = -1; 359: } 360: 361: /** 362: * Returns the currently selected item, or null if no item is 363: * selected. 364: * 365: * @return The currently selected item. 366: */ 367: public synchronized String getSelectedItem() 368: { 369: return (selectedIndex == -1 370: ? null 371: : ((String)pItems.elementAt(selectedIndex))); 372: } 373: 374: /** 375: * Returns an array with one row containing the selected item. 376: * 377: * @return An array containing the selected item. 378: */ 379: public synchronized Object[] getSelectedObjects() 380: { 381: if (selectedIndex == -1) 382: return null; 383: 384: Object[] objs = new Object[1]; 385: objs[0] = pItems.elementAt(selectedIndex); 386: 387: return objs; 388: } 389: 390: /** 391: * Returns the index of the selected item. 392: * 393: * @return The index of the selected item. 394: */ 395: public int getSelectedIndex() 396: { 397: return selectedIndex; 398: } 399: 400: /** 401: * Forces the item at the specified index to be selected. 402: * 403: * @param index The index of the row to make selected. 404: * 405: * @exception IllegalArgumentException If the specified index is invalid. 406: */ 407: public synchronized void select(int index) 408: { 409: if ((index < 0) || (index >= getItemCount())) 410: throw new IllegalArgumentException("Bad index: " + index); 411: 412: if( selectedIndex == index ) 413: return; 414: 415: selectedIndex = index; 416: if( peer != null ) 417: ((ChoicePeer)peer).select( index ); 418: } 419: 420: /** 421: * Forces the named item to be selected. 422: * 423: * @param item The item to be selected. 424: * 425: * @exception IllegalArgumentException If the specified item does not exist. 426: */ 427: public synchronized void select(String item) 428: { 429: int index = pItems.indexOf(item); 430: if( index >= 0 ) 431: select( index ); 432: } 433: 434: /** 435: * Creates the native peer for this object. 436: */ 437: public void addNotify() 438: { 439: if (peer == null) 440: peer = getToolkit ().createChoice (this); 441: super.addNotify (); 442: } 443: 444: /** 445: * Adds the specified listener to the list of registered listeners for 446: * this object. 447: * 448: * @param listener The listener to add. 449: */ 450: public synchronized void addItemListener(ItemListener listener) 451: { 452: item_listeners = AWTEventMulticaster.add(item_listeners, listener); 453: } 454: 455: /** 456: * Removes the specified listener from the list of registered listeners for 457: * this object. 458: * 459: * @param listener The listener to remove. 460: */ 461: public synchronized void removeItemListener(ItemListener listener) 462: { 463: item_listeners = AWTEventMulticaster.remove(item_listeners, listener); 464: } 465: 466: /** 467: * Processes this event by invoking <code>processItemEvent()</code> if the 468: * event is an instance of <code>ItemEvent</code>, otherwise the event 469: * is passed to the superclass. 470: * 471: * @param event The event to process. 472: */ 473: protected void processEvent(AWTEvent event) 474: { 475: if (event instanceof ItemEvent) 476: processItemEvent((ItemEvent)event); 477: else 478: super.processEvent(event); 479: } 480: 481: void dispatchEventImpl(AWTEvent e) 482: { 483: super.dispatchEventImpl(e); 484: 485: if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST && 486: ( item_listeners != null || 487: ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) ) 488: processEvent(e); 489: } 490: 491: /** 492: * Processes item event by dispatching to any registered listeners. 493: * 494: * @param event The event to process. 495: */ 496: protected void processItemEvent(ItemEvent event) 497: { 498: int index = pItems.indexOf((String) event.getItem()); 499: if (item_listeners != null) 500: item_listeners.itemStateChanged(event); 501: } 502: 503: /** 504: * Returns a debugging string for this object. 505: * 506: * @return A debugging string for this object. 507: */ 508: protected String paramString() 509: { 510: return "selectedIndex=" + selectedIndex + "," + super.paramString(); 511: } 512: 513: /** 514: * Returns an array of all the objects currently registered as FooListeners 515: * upon this Choice. FooListeners are registered using the addFooListener 516: * method. 517: * 518: * @exception ClassCastException If listenerType doesn't specify a class or 519: * interface that implements java.util.EventListener. 520: * 521: * @since 1.3 522: */ 523: public <T extends EventListener> T[] getListeners (Class<T> listenerType) 524: { 525: if (listenerType == ItemListener.class) 526: return AWTEventMulticaster.getListeners (item_listeners, listenerType); 527: 528: return super.getListeners (listenerType); 529: } 530: 531: /** 532: * Returns all registered item listeners. 533: * 534: * @since 1.4 535: */ 536: public ItemListener[] getItemListeners () 537: { 538: return (ItemListener[]) getListeners (ItemListener.class); 539: } 540: 541: /** 542: * Gets the AccessibleContext associated with this <code>Choice</code>. 543: * The context is created, if necessary. 544: * 545: * @return the associated context 546: */ 547: public AccessibleContext getAccessibleContext() 548: { 549: /* Create the context if this is the first request */ 550: if (accessibleContext == null) 551: accessibleContext = new AccessibleAWTChoice(); 552: return accessibleContext; 553: } 554: 555: /** 556: * Generate a unique name for this <code>Choice</code>. 557: * 558: * @return A unique name for this <code>Choice</code>. 559: */ 560: String generateName() 561: { 562: return "choice" + getUniqueLong(); 563: } 564: 565: private static synchronized long getUniqueLong() 566: { 567: return next_choice_number++; 568: } 569: } // class Choice