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 @see add 259: * 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: if ((index < 0) || (index > getItemCount())) 324: throw new IllegalArgumentException("Bad index: " + index); 325: 326: pItems.removeElementAt(index); 327: 328: if (peer != null) 329: ((ChoicePeer) peer).remove( index ); 330: 331: if( getItemCount() == 0 ) 332: selectedIndex = -1; 333: else 334: { 335: if( selectedIndex > index ) 336: selectedIndex--; 337: else if( selectedIndex == index ) 338: selectedIndex = 0; 339: 340: if( peer != null ) 341: ((ChoicePeer)peer).select( selectedIndex ); 342: } 343: } 344: 345: /** 346: * Removes all of the objects from this choice box. 347: */ 348: public synchronized void removeAll() 349: { 350: if (getItemCount() <= 0) 351: return; 352: 353: pItems.removeAllElements (); 354: 355: if (peer != null) 356: { 357: ChoicePeer cp = (ChoicePeer) peer; 358: cp.removeAll (); 359: } 360: 361: selectedIndex = -1; 362: } 363: 364: /** 365: * Returns the currently selected item, or null if no item is 366: * selected. 367: * 368: * @return The currently selected item. 369: */ 370: public synchronized String getSelectedItem() 371: { 372: return (selectedIndex == -1 373: ? null 374: : ((String)pItems.elementAt(selectedIndex))); 375: } 376: 377: /** 378: * Returns an array with one row containing the selected item. 379: * 380: * @return An array containing the selected item. 381: */ 382: public synchronized Object[] getSelectedObjects() 383: { 384: if (selectedIndex == -1) 385: return null; 386: 387: Object[] objs = new Object[1]; 388: objs[0] = pItems.elementAt(selectedIndex); 389: 390: return objs; 391: } 392: 393: /** 394: * Returns the index of the selected item. 395: * 396: * @return The index of the selected item. 397: */ 398: public int getSelectedIndex() 399: { 400: return selectedIndex; 401: } 402: 403: /** 404: * Forces the item at the specified index to be selected. 405: * 406: * @param index The index of the row to make selected. 407: * 408: * @exception IllegalArgumentException If the specified index is invalid. 409: */ 410: public synchronized void select(int index) 411: { 412: if ((index < 0) || (index >= getItemCount())) 413: throw new IllegalArgumentException("Bad index: " + index); 414: 415: if( selectedIndex == index ) 416: return; 417: 418: selectedIndex = index; 419: if( peer != null ) 420: ((ChoicePeer)peer).select( index ); 421: } 422: 423: /** 424: * Forces the named item to be selected. 425: * 426: * @param item The item to be selected. 427: * 428: * @exception IllegalArgumentException If the specified item does not exist. 429: */ 430: public synchronized void select(String item) 431: { 432: int index = pItems.indexOf(item); 433: if( index >= 0 ) 434: select( index ); 435: } 436: 437: /** 438: * Creates the native peer for this object. 439: */ 440: public void addNotify() 441: { 442: if (peer == null) 443: peer = getToolkit ().createChoice (this); 444: super.addNotify (); 445: } 446: 447: /** 448: * Adds the specified listener to the list of registered listeners for 449: * this object. 450: * 451: * @param listener The listener to add. 452: */ 453: public synchronized void addItemListener(ItemListener listener) 454: { 455: item_listeners = AWTEventMulticaster.add(item_listeners, listener); 456: } 457: 458: /** 459: * Removes the specified listener from the list of registered listeners for 460: * this object. 461: * 462: * @param listener The listener to remove. 463: */ 464: public synchronized void removeItemListener(ItemListener listener) 465: { 466: item_listeners = AWTEventMulticaster.remove(item_listeners, listener); 467: } 468: 469: /** 470: * Processes this event by invoking <code>processItemEvent()</code> if the 471: * event is an instance of <code>ItemEvent</code>, otherwise the event 472: * is passed to the superclass. 473: * 474: * @param event The event to process. 475: */ 476: protected void processEvent(AWTEvent event) 477: { 478: if (event instanceof ItemEvent) 479: processItemEvent((ItemEvent)event); 480: else 481: super.processEvent(event); 482: } 483: 484: void dispatchEventImpl(AWTEvent e) 485: { 486: super.dispatchEventImpl(e); 487: 488: if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST && 489: ( item_listeners != null || 490: ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) ) 491: processEvent(e); 492: } 493: 494: /** 495: * Processes item event by dispatching to any registered listeners. 496: * 497: * @param event The event to process. 498: */ 499: protected void processItemEvent(ItemEvent event) 500: { 501: int index = pItems.indexOf((String) event.getItem()); 502: if (item_listeners != null) 503: item_listeners.itemStateChanged(event); 504: } 505: 506: /** 507: * Returns a debugging string for this object. 508: * 509: * @return A debugging string for this object. 510: */ 511: protected String paramString() 512: { 513: return "selectedIndex=" + selectedIndex + "," + super.paramString(); 514: } 515: 516: /** 517: * Returns an array of all the objects currently registered as FooListeners 518: * upon this Choice. FooListeners are registered using the addFooListener 519: * method. 520: * 521: * @exception ClassCastException If listenerType doesn't specify a class or 522: * interface that implements java.util.EventListener. 523: * 524: * @since 1.3 525: */ 526: public EventListener[] getListeners (Class listenerType) 527: { 528: if (listenerType == ItemListener.class) 529: return AWTEventMulticaster.getListeners (item_listeners, listenerType); 530: 531: return super.getListeners (listenerType); 532: } 533: 534: /** 535: * Returns all registered item listeners. 536: * 537: * @since 1.4 538: */ 539: public ItemListener[] getItemListeners () 540: { 541: return (ItemListener[]) getListeners (ItemListener.class); 542: } 543: 544: /** 545: * Gets the AccessibleContext associated with this <code>Choice</code>. 546: * The context is created, if necessary. 547: * 548: * @return the associated context 549: */ 550: public AccessibleContext getAccessibleContext() 551: { 552: /* Create the context if this is the first request */ 553: if (accessibleContext == null) 554: accessibleContext = new AccessibleAWTChoice(); 555: return accessibleContext; 556: } 557: 558: /** 559: * Generate a unique name for this <code>Choice</code>. 560: * 561: * @return A unique name for this <code>Choice</code>. 562: */ 563: String generateName() 564: { 565: return "choice" + getUniqueLong(); 566: } 567: 568: private static synchronized long getUniqueLong() 569: { 570: return next_choice_number++; 571: } 572: } // class Choice