Source for java.awt.List

   1: /* List.java -- A listbox widget
   2:    Copyright (C) 1999, 2002, 2004  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.ActionEvent;
  42: import java.awt.event.ActionListener;
  43: import java.awt.event.ItemEvent;
  44: import java.awt.event.ItemListener;
  45: import java.awt.peer.ListPeer;
  46: import java.util.EventListener;
  47: import java.util.Vector;
  48: 
  49: import javax.accessibility.Accessible;
  50: import javax.accessibility.AccessibleContext;
  51: import javax.accessibility.AccessibleRole;
  52: import javax.accessibility.AccessibleSelection;
  53: import javax.accessibility.AccessibleState;
  54: import javax.accessibility.AccessibleStateSet;
  55: 
  56: /**
  57:   * Class that implements a listbox widget
  58:   *
  59:   * @author Aaron M. Renn (arenn@urbanophile.com)
  60:   */
  61: public class List extends Component
  62:   implements ItemSelectable, Accessible
  63: {
  64: 
  65: /*
  66:  * Static Variables
  67:  */
  68: 
  69: /**
  70:  * The number used to generate the name returned by getName.
  71:  */
  72: private static transient long next_list_number;  
  73: 
  74: // Serialization constant
  75: private static final long serialVersionUID = -3304312411574666869L;
  76: 
  77: /*************************************************************************/
  78: 
  79: /*
  80:  * Instance Variables
  81:  */
  82: 
  83: // FIXME: Need read/writeObject
  84: 
  85: /**
  86:   * @serial The items in the list.
  87:   */
  88: private Vector items = new Vector();
  89: 
  90: /**
  91:   * @serial Indicates whether or not multiple items can be selected
  92:   * simultaneously.
  93:   */
  94: private boolean multipleMode;
  95: 
  96: /**
  97:   * @serial The number of rows in the list.  This is set on creation
  98:   * only and cannot be modified.
  99:   */
 100: private int rows;
 101: 
 102: /**
 103:   * @serial An array of the item indices that are selected.
 104:   */
 105: private int[] selected;
 106: 
 107: /**
 108:   * @serial An index value used by <code>makeVisible()</code> and
 109:   * <code>getVisibleIndex</code>.
 110:   */
 111: private int visibleIndex;
 112: 
 113: // The list of ItemListeners for this object.
 114: private ItemListener item_listeners;
 115: 
 116: // The list of ActionListeners for this object.
 117: private ActionListener action_listeners;
 118: 
 119: 
 120: /*************************************************************************/
 121: 
 122: /*
 123:  * Constructors
 124:  */
 125: 
 126: /**
 127:   * Initializes a new instance of <code>List</code> with no visible lines
 128:   * and multi-select disabled.
 129:   *
 130:   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 131:   */
 132: public
 133: List()
 134: {
 135:   this(4, false);
 136: }
 137: 
 138: /*************************************************************************/
 139: 
 140: /**
 141:   * Initializes a new instance of <code>List</code> with the specified
 142:   * number of visible lines and multi-select disabled.
 143:   *
 144:   * @param rows The number of visible rows in the list.
 145:   *
 146:   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 147:   */
 148: public
 149: List(int rows)
 150: {
 151:   this(rows, false);
 152: }
 153: 
 154: /*************************************************************************/
 155: 
 156: /**
 157:   * Initializes a new instance of <code>List</code> with the specified
 158:   * number of lines and the specified multi-select setting.
 159:   *
 160:   * @param rows The number of visible rows in the list.
 161:   * @param multipleMode <code>true</code> if multiple lines can be selected
 162:   * simultaneously, <code>false</code> otherwise.
 163:   *
 164:   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 165:   */
 166: public 
 167: List(int rows, boolean multipleMode)
 168: {
 169:   if (rows == 0)
 170:     this.rows = 4;
 171:   else
 172:     this.rows = rows;
 173:   
 174:   this.multipleMode = multipleMode;
 175:   selected = new int[0];
 176: 
 177:   if (GraphicsEnvironment.isHeadless())
 178:     throw new HeadlessException ();
 179: }
 180: 
 181: /*************************************************************************/
 182: 
 183: /*
 184:  * Instance Variables
 185:  */
 186: 
 187: /**
 188:   * Returns the number of items in this list.
 189:   *
 190:   * @return The number of items in this list.
 191:   */
 192: public int
 193: getItemCount()
 194: {
 195:   return countItems ();
 196: }
 197: 
 198: /*************************************************************************/
 199: 
 200: /**
 201:   * Returns the number of items in this list.
 202:   *
 203:   * @return The number of items in this list.
 204:   *
 205:   * @deprecated This method is deprecated in favor of
 206:   * <code>getItemCount()</code>
 207:   */
 208: public int
 209: countItems()
 210: {
 211:   return items.size ();
 212: }
 213: 
 214: /*************************************************************************/
 215: 
 216: /**
 217:   * Returns the complete list of items.
 218:   *
 219:   * @return The complete list of items in the list.
 220:   */
 221: public synchronized String[]
 222: getItems()
 223: {
 224:   String[] l_items = new String[getItemCount()];
 225:  
 226:   items.copyInto(l_items);
 227:   return(l_items);
 228: }
 229: 
 230: /*************************************************************************/
 231: 
 232: /**
 233:   * Returns the item at the specified index.
 234:   *
 235:   * @param index The index of the item to retrieve.
 236:   *
 237:   * @exception IndexOutOfBoundsException If the index value is not valid.
 238:   */
 239: public String
 240: getItem(int index)
 241: {
 242:   return((String)items.elementAt(index));
 243: }
 244: 
 245: /*************************************************************************/
 246: 
 247: /**
 248:   * Returns the number of visible rows in the list.
 249:   *
 250:   * @return The number of visible rows in the list.
 251:   */
 252: public int
 253: getRows()
 254: {
 255:   return(rows);
 256: }
 257: 
 258: /*************************************************************************/
 259: 
 260: /**
 261:   * Tests whether or not multi-select mode is enabled.
 262:   *
 263:   * @return <code>true</code> if multi-select mode is enabled,
 264:   * <code>false</code> otherwise.
 265:   */
 266: public boolean
 267: isMultipleMode()
 268: {
 269:   return allowsMultipleSelections ();
 270: }
 271: 
 272: /*************************************************************************/
 273: 
 274: /**
 275:   * Tests whether or not multi-select mode is enabled.
 276:   *
 277:   * @return <code>true</code> if multi-select mode is enabled,
 278:   * <code>false</code> otherwise.
 279:   *
 280:   * @deprecated This method is deprecated in favor of 
 281:   * <code>isMultipleMode()</code>.
 282:   */
 283: public boolean
 284: allowsMultipleSelections()
 285: {
 286:   return multipleMode;
 287: }
 288: 
 289: /*************************************************************************/
 290: 
 291: /**
 292:   * This method enables or disables multiple selection mode for this
 293:   * list.
 294:   *
 295:   * @param multipleMode <code>true</code> to enable multiple mode,
 296:   * <code>false</code> otherwise.
 297:   */
 298: public void
 299: setMultipleMode(boolean multipleMode)
 300: {
 301:   setMultipleSelections (multipleMode);
 302: }
 303: 
 304: /*************************************************************************/
 305: 
 306: /**
 307:   * This method enables or disables multiple selection mode for this
 308:   * list.
 309:   *
 310:   * @param multipleMode <code>true</code> to enable multiple mode,
 311:   * <code>false</code> otherwise.
 312:   *
 313:   * @deprecated
 314:   */
 315: public void
 316: setMultipleSelections(boolean multipleMode)
 317: {
 318:   this.multipleMode = multipleMode;
 319: 
 320:   ListPeer peer = (ListPeer) getPeer ();
 321:   if (peer != null)
 322:     peer.setMultipleMode (multipleMode);
 323: }
 324: 
 325: /*************************************************************************/
 326: 
 327: /**
 328:   * Returns the minimum size of this component.
 329:   *
 330:   * @return The minimum size of this component.
 331:   */
 332: public Dimension
 333: getMinimumSize()
 334: {
 335:   return getMinimumSize (getRows ());
 336: }
 337: 
 338: /*************************************************************************/
 339: 
 340: /**
 341:   * Returns the minimum size of this component.
 342:   *
 343:   * @return The minimum size of this component.
 344:   *
 345:   * @deprecated This method is deprecated in favor of
 346:   * <code>getMinimumSize</code>.
 347:   */
 348: public Dimension
 349: minimumSize()
 350: {
 351:   return minimumSize (getRows ());
 352: }
 353: 
 354: /*************************************************************************/
 355: 
 356: /**
 357:   * Returns the minimum size of this component assuming it had the specified
 358:   * number of rows.
 359:   *
 360:   * @param rows The number of rows to size for.
 361:   *
 362:   * @return The minimum size of this component.
 363:   */
 364: public Dimension
 365: getMinimumSize(int rows)
 366: {
 367:   return minimumSize (rows);
 368: }
 369: 
 370: /*************************************************************************/
 371: 
 372: /**
 373:   * Returns the minimum size of this component assuming it had the specified
 374:   * number of rows.
 375:   *
 376:   * @param rows The number of rows to size for.
 377:   *
 378:   * @return The minimum size of this component.
 379:   *
 380:   * @deprecated This method is deprecated in favor of 
 381:   * <code>getMinimumSize(int)</code>>
 382:   */
 383: public Dimension
 384: minimumSize(int rows)
 385: {
 386:   ListPeer peer = (ListPeer) getPeer ();
 387:   if (peer != null)
 388:     return peer.minimumSize (rows);
 389:   else
 390:     return new Dimension (0, 0);
 391: }
 392: 
 393: /*************************************************************************/
 394: 
 395: /**
 396:   * Returns the preferred size of this component.
 397:   *
 398:   * @return The preferred size of this component.
 399:   */
 400: public Dimension
 401: getPreferredSize()
 402: {
 403:   return getPreferredSize (getRows ());
 404: }
 405: 
 406: /*************************************************************************/
 407: 
 408: /**
 409:   * Returns the preferred size of this component.
 410:   *
 411:   * @return The preferred size of this component.
 412:   *
 413:   * @deprecated This method is deprecated in favor of
 414:   * <code>getPreferredSize</code>.
 415:   */
 416: public Dimension
 417: preferredSize()
 418: {
 419:   return preferredSize (getRows ());
 420: }
 421: 
 422: /*************************************************************************/
 423: 
 424: /**
 425:   * Returns the preferred size of this component assuming it had the specified
 426:   * number of rows.
 427:   *
 428:   * @param rows The number of rows to size for.
 429:   *
 430:   * @return The preferred size of this component.
 431:   */
 432: public Dimension
 433: getPreferredSize(int rows)
 434: {
 435:   return preferredSize (rows);
 436: }
 437: 
 438: /*************************************************************************/
 439: 
 440: /**
 441:   * Returns the preferred size of this component assuming it had the specified
 442:   * number of rows.
 443:   *
 444:   * @param rows The number of rows to size for.
 445:   *
 446:   * @return The preferred size of this component.
 447:   *
 448:   * @deprecated This method is deprecated in favor of 
 449:   * <code>getPreferredSize(int)</code>>
 450:   */
 451: public Dimension
 452: preferredSize(int rows)
 453: {
 454:   ListPeer peer = (ListPeer) getPeer ();
 455:   if (peer != null)
 456:     return peer.preferredSize (rows);
 457:   else
 458:     return getSize();
 459: }
 460: 
 461: /*************************************************************************/
 462: 
 463: /**
 464:   * This method adds the specified item to the end of the list.
 465:   *
 466:   * @param item The item to add to the list.
 467:   */
 468: public void
 469: add(String item)
 470: {
 471:   add (item, -1);
 472: }
 473: 
 474: /*************************************************************************/
 475: 
 476: /**
 477:   * This method adds the specified item to the end of the list.
 478:   *
 479:   * @param item The item to add to the list.
 480:   *
 481:   * @deprecated Use add() instead.
 482:   */
 483: public void
 484: addItem(String item)
 485: {
 486:   addItem (item, -1);
 487: }
 488: 
 489: /*************************************************************************/
 490: 
 491: /**
 492:   * Adds the specified item to the specified location in the list.
 493:   * If the desired index is -1 or greater than the number of rows
 494:   * in the list, then the item is added to the end.
 495:   *
 496:   * @param item The item to add to the list.
 497:   * @param index The location in the list to add the item, or -1 to add
 498:   * to the end.
 499:   */
 500: public void
 501: add(String item, int index)
 502: {
 503:   addItem (item, index);
 504: }
 505: 
 506: /*************************************************************************/
 507: 
 508: /**
 509:   * Adds the specified item to the specified location in the list.
 510:   * If the desired index is -1 or greater than the number of rows
 511:   * in the list, then the item is added to the end.
 512:   *
 513:   * @param item The item to add to the list.
 514:   * @param index The location in the list to add the item, or -1 to add
 515:   * to the end.
 516:   *
 517:   * @deprecated Use add() instead.
 518:   */
 519: public void
 520: addItem(String item, int index)
 521: {
 522:   if ((index == -1) || (index >= items.size ()))
 523:     items.addElement (item);
 524:   else
 525:     items.insertElementAt (item, index);
 526: 
 527:   ListPeer peer = (ListPeer) getPeer ();
 528:   if (peer != null)
 529:     peer.add (item, index);
 530: }
 531: 
 532: /*************************************************************************/
 533: 
 534: /**
 535:   * Deletes the item at the specified index.
 536:   *
 537:   * @param index The index of the item to delete.
 538:   *
 539:   * @exception IllegalArgumentException If the index is not valid
 540:   *
 541:   * @deprecated
 542:   */
 543: public void
 544: delItem(int index) throws IllegalArgumentException
 545: {
 546:   items.removeElementAt (index);
 547: 
 548:   ListPeer peer = (ListPeer) getPeer ();
 549:   if (peer != null)
 550:     peer.delItems (index, index);
 551: }
 552: 
 553: /*************************************************************************/
 554: 
 555: /**
 556:   * Deletes the item at the specified index.
 557:   *
 558:   * @param index The index of the item to delete.
 559:   *
 560:   * @exception IllegalArgumentException If the index is not valid
 561:   */
 562: public void
 563: remove(int index) throws IllegalArgumentException
 564: {
 565:   delItem (index);
 566: }
 567: 
 568: /*************************************************************************/
 569: 
 570: /**
 571:   * Deletes all items in the specified index range.
 572:   *
 573:   * @param start The beginning index of the range to delete.
 574:   * @param end The ending index of the range to delete.
 575:   *
 576:   * @exception IllegalArgumentException If the indexes are not valid
 577:   *
 578:   * @deprecated This method is deprecated for some unknown reason.
 579:   */
 580: public synchronized void
 581: delItems(int start, int end) throws IllegalArgumentException
 582: {
 583:   if ((start < 0) || (start >= items.size()))
 584:     throw new IllegalArgumentException("Bad list start index value: " + start);
 585: 
 586:   if ((start < 0) || (start >= items.size()))
 587:     throw new IllegalArgumentException("Bad list start index value: " + start);
 588: 
 589:   if (start > end)
 590:     throw new IllegalArgumentException("Start is greater than end!");
 591: 
 592:   // We must run the loop in reverse direction.
 593:   for (int i = end; i >= start; --i)
 594:     items.removeElementAt (i);
 595:   if (peer != null)
 596:     {
 597:       ListPeer l = (ListPeer) peer;
 598:       l.delItems (start, end);
 599:     }
 600: }
 601: 
 602: /*************************************************************************/
 603: 
 604: /**
 605:   * Deletes the first occurrence of the specified item from the list.
 606:   *
 607:   * @param item The item to delete.
 608:   *
 609:   * @exception IllegalArgumentException If the specified item does not exist.
 610:   */
 611: public synchronized void
 612: remove(String item) throws IllegalArgumentException
 613: {
 614:   int index = items.indexOf(item);
 615:   if (index == -1)
 616:     throw new IllegalArgumentException("List element to delete not found");
 617: 
 618:   remove(index);
 619: }
 620: 
 621: /*************************************************************************/
 622: 
 623: /**
 624:   * Deletes all of the items from the list.
 625:   */
 626: public synchronized void
 627: removeAll()
 628: {
 629:   clear ();
 630: }
 631: 
 632: /*************************************************************************/
 633: 
 634: /**
 635:   * Deletes all of the items from the list.
 636:   * 
 637:   * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
 638:   */
 639: public void
 640: clear()
 641: {
 642:   items.clear();
 643: 
 644:   ListPeer peer = (ListPeer) getPeer ();
 645:   if (peer != null)
 646:     peer.removeAll ();
 647: }
 648: 
 649: /*************************************************************************/
 650: 
 651: /**
 652:   * Replaces the item at the specified index with the specified item.
 653:   *
 654:   * @param item The new item value.
 655:   * @param index The index of the item to replace.
 656:   *
 657:   * @exception ArrayIndexOutOfBoundsException If the index is not valid.
 658:   */
 659: public synchronized void
 660: replaceItem(String item, int index) throws ArrayIndexOutOfBoundsException
 661: {
 662:   if ((index < 0) || (index >= items.size()))
 663:     throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);
 664: 
 665:   items.insertElementAt(item, index + 1);
 666:   items.removeElementAt (index);
 667: 
 668:   if (peer != null)
 669:     {
 670:       ListPeer l = (ListPeer) peer;
 671: 
 672:       /* We add first and then remove so that the selected
 673:      item remains the same */
 674:       l.add (item, index + 1);
 675:       l.delItems (index, index);
 676:     }
 677: }
 678: 
 679: /*************************************************************************/
 680: 
 681: /**
 682:   * Returns the index of the currently selected item.  -1 will be returned
 683:   * if there are no selected rows or if there are multiple selected rows.
 684:   *
 685:   * @return The index of the selected row.
 686:   */
 687: public synchronized int
 688: getSelectedIndex()
 689: {
 690:   if (peer != null)
 691:     {
 692:       ListPeer l = (ListPeer) peer;
 693:       selected = l.getSelectedIndexes ();
 694:     }
 695: 
 696:   if (selected == null || selected.length != 1)
 697:     return -1;
 698:   return selected[0];
 699: }
 700: 
 701: /*************************************************************************/
 702: 
 703: /**
 704:   * Returns an array containing the indexes of the rows that are 
 705:   * currently selected.
 706:   *
 707:   * @return A list of indexes of selected rows.
 708:   */
 709: public synchronized int[]
 710: getSelectedIndexes()
 711: {
 712:   if (peer != null)
 713:     {
 714:       ListPeer l = (ListPeer) peer;
 715:       selected = l.getSelectedIndexes ();
 716:     }
 717:   return selected;
 718: }
 719: 
 720: /*************************************************************************/
 721: 
 722: /**
 723:   * Returns the item that is currently selected, or <code>null</code> if there 
 724:   * is no item selected.  FIXME: What happens if multiple items selected?
 725:   *
 726:   * @return The selected item, or <code>null</code> if there is no
 727:   * selected item.
 728:   */
 729: public synchronized String
 730: getSelectedItem()
 731: {
 732:   int index = getSelectedIndex();
 733:   if (index == -1)
 734:     return(null);
 735: 
 736:   return((String)items.elementAt(index));
 737: }
 738: 
 739: /*************************************************************************/
 740: 
 741: /**
 742:   * Returns the list of items that are currently selected in this list.
 743:   *
 744:   * @return The list of currently selected items.
 745:   */
 746: public synchronized String[]
 747: getSelectedItems()
 748: {
 749:   int[] indexes = getSelectedIndexes();
 750:   if (indexes == null)
 751:     return(new String[0]);
 752: 
 753:   String[] retvals = new String[indexes.length];
 754:   if (retvals.length > 0)
 755:     for (int i = 0 ; i < retvals.length; i++)
 756:        retvals[i] = (String)items.elementAt(indexes[i]);
 757: 
 758:   return(retvals);
 759: }
 760: 
 761: /*************************************************************************/
 762: 
 763: /**
 764:   * Returns the list of items that are currently selected in this list as
 765:   * an array of type <code>Object[]</code> instead of <code>String[]</code>.
 766:   *
 767:   * @return The list of currently selected items.
 768:   */
 769: public synchronized Object[]
 770: getSelectedObjects()
 771: {
 772:   int[] indexes = getSelectedIndexes();
 773:   if (indexes == null)
 774:     return(new Object[0]);
 775: 
 776:   Object[] retvals = new Object[indexes.length];
 777:   if (retvals.length > 0)
 778:     for (int i = 0 ; i < retvals.length; i++)
 779:        retvals[i] = items.elementAt(indexes[i]);
 780: 
 781:   return(retvals);
 782: }
 783: 
 784: /*************************************************************************/
 785: 
 786: /**
 787:   * Tests whether or not the specified index is selected.
 788:   *
 789:   * @param index The index to test.
 790:   *
 791:   * @return <code>true</code> if the index is selected, <code>false</code>
 792:   * otherwise.
 793:   */
 794: public boolean
 795: isIndexSelected(int index)
 796: {
 797:   return isSelected (index);
 798: }
 799: 
 800: /*************************************************************************/
 801: 
 802: /**
 803:   * Tests whether or not the specified index is selected.
 804:   *
 805:   * @param index The index to test.
 806:   *
 807:   * @return <code>true</code> if the index is selected, <code>false</code>
 808:   * otherwise.
 809:   *
 810:   * @deprecated This method is deprecated in favor of
 811:   * <code>isIndexSelected(int)</code>.
 812:   */
 813: public boolean
 814: isSelected(int index)
 815: {
 816:   int[] indexes = getSelectedIndexes ();
 817: 
 818:   for (int i = 0; i < indexes.length; i++)
 819:     if (indexes[i] == index)
 820:       return true;
 821: 
 822:   return false;
 823: }
 824: 
 825: /*************************************************************************/
 826: 
 827: /**
 828:   * This method ensures that the item at the specified index is visible.
 829:   *
 830:   * @param index The index of the item to be made visible.
 831:   */
 832: public synchronized void
 833: makeVisible(int index) throws IllegalArgumentException
 834: {
 835:   visibleIndex = index;
 836:   if (peer != null)
 837:     {
 838:       ListPeer l = (ListPeer) peer;
 839:       l.makeVisible (index);
 840:     }
 841: }
 842: 
 843: /*************************************************************************/
 844: 
 845: /**
 846:   * Returns the index of the last item that was made visible via the
 847:   * <code>makeVisible()</code> method.
 848:   *
 849:   * @return The index of the last item made visible via the 
 850:   * <code>makeVisible()</code> method.
 851:   */
 852: public int
 853: getVisibleIndex()
 854: {
 855:   return(visibleIndex);
 856: }
 857: 
 858: /*************************************************************************/
 859: 
 860: /**
 861:   * Makes the item at the specified index selected.
 862:   *
 863:   * @param index The index of the item to select.
 864:   */
 865: public synchronized void
 866: select(int index)
 867: {
 868:   ListPeer lp = (ListPeer)getPeer();
 869:   if (lp != null)
 870:     lp.select(index);
 871: }
 872: 
 873: /*************************************************************************/
 874: 
 875: /**
 876:   * Makes the item at the specified index not selected.
 877:   *
 878:   * @param index The index of the item to unselect.
 879:   */
 880: public synchronized void
 881: deselect(int index)
 882: {
 883:   ListPeer lp = (ListPeer)getPeer();
 884:   if (lp != null)
 885:     lp.deselect(index);
 886: }
 887: 
 888: /*************************************************************************/
 889: 
 890: /**
 891:   * Notifies this object to create its native peer.
 892:   */
 893: public void
 894: addNotify()
 895: {
 896:   if (peer == null)
 897:     peer = getToolkit ().createList (this);
 898:   super.addNotify ();
 899: }
 900: 
 901: /*************************************************************************/
 902: 
 903: /**
 904:   * Notifies this object to destroy its native peer.
 905:   */
 906: public void
 907: removeNotify()
 908: {
 909:   super.removeNotify();
 910: }
 911: 
 912: /*************************************************************************/
 913: 
 914: /**
 915:   * Adds the specified <code>ActionListener</code> to the list of
 916:   * registered listeners for this object.
 917:   *
 918:   * @param listener The listener to add.
 919:   */
 920: public synchronized void
 921: addActionListener(ActionListener listener)
 922: {
 923:   action_listeners = AWTEventMulticaster.add(action_listeners, listener);
 924: }
 925: 
 926: /*************************************************************************/
 927: 
 928: /**
 929:   * Removes the specified <code>ActionListener</code> from the list of
 930:   * registers listeners for this object.
 931:   *
 932:   * @param listener The listener to remove.
 933:   */
 934: public synchronized void
 935: removeActionListener(ActionListener listener)
 936: {
 937:   action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
 938: }
 939: 
 940: /*************************************************************************/
 941: 
 942: /**
 943:   * Adds the specified <code>ItemListener</code> to the list of
 944:   * registered listeners for this object.
 945:   *
 946:   * @param listener The listener to add.
 947:   */
 948: public synchronized void
 949: addItemListener(ItemListener listener)
 950: {
 951:   item_listeners = AWTEventMulticaster.add(item_listeners, listener);
 952: }
 953: 
 954: /*************************************************************************/
 955: 
 956: /**
 957:   * Removes the specified <code>ItemListener</code> from the list of
 958:   * registers listeners for this object.
 959:   *
 960:   * @param listener The listener to remove.
 961:   */
 962: public synchronized void
 963: removeItemListener(ItemListener listener)
 964: {
 965:   item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
 966: }
 967: 
 968: /*************************************************************************/
 969: 
 970: /**
 971:   * Processes the specified event for this object.  If the event is an
 972:   * instance of <code>ActionEvent</code> then the
 973:   * <code>processActionEvent()</code> method is called.  Similarly, if the
 974:   * even is an instance of <code>ItemEvent</code> then the
 975:   * <code>processItemEvent()</code> method is called.  Otherwise the
 976:   * superclass method is called to process this event.
 977:   *
 978:   * @param event The event to process.
 979:   */
 980: protected void
 981: processEvent(AWTEvent event)
 982: {
 983:   if (event instanceof ActionEvent)
 984:     processActionEvent((ActionEvent)event);
 985:   else if (event instanceof ItemEvent)
 986:     processItemEvent((ItemEvent)event);
 987:   else
 988:     super.processEvent(event);
 989: }
 990: 
 991: /*************************************************************************/
 992: 
 993: /**
 994:   * This method processes the specified event by dispatching it to any
 995:   * registered listeners.  Note that this method will only get called if
 996:   * action events are enabled.  This will happen automatically if any
 997:   * listeners are added, or it can be done "manually" by calling
 998:   * the <code>enableEvents()</code> method.
 999:   *
1000:   * @param event The event to process.
1001:   */
1002: protected void 
1003: processActionEvent(ActionEvent event)
1004: {
1005:   if (action_listeners != null)
1006:     action_listeners.actionPerformed(event);
1007: }
1008: 
1009: /*************************************************************************/
1010: 
1011: /**
1012:   * This method processes the specified event by dispatching it to any
1013:   * registered listeners.  Note that this method will only get called if
1014:   * item events are enabled.  This will happen automatically if any
1015:   * listeners are added, or it can be done "manually" by calling
1016:   * the <code>enableEvents()</code> method.
1017:   *
1018:   * @param event The event to process.
1019:   */
1020: protected void 
1021: processItemEvent(ItemEvent event)
1022: {
1023:   if (item_listeners != null)
1024:     item_listeners.itemStateChanged(event);
1025: }
1026: 
1027: void
1028: dispatchEventImpl(AWTEvent e)
1029: {
1030:   if (e.id <= ItemEvent.ITEM_LAST
1031:       && e.id >= ItemEvent.ITEM_FIRST
1032:       && (item_listeners != null 
1033:       || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
1034:     processEvent(e);
1035:   else if (e.id <= ActionEvent.ACTION_LAST 
1036:        && e.id >= ActionEvent.ACTION_FIRST
1037:        && (action_listeners != null 
1038:            || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
1039:     processEvent(e);
1040:   else
1041:     super.dispatchEventImpl(e);
1042: }
1043: 
1044: /*************************************************************************/
1045: 
1046: /**
1047:   * Returns a debugging string for this object.
1048:   *
1049:   * @return A debugging string for this object.
1050:   */
1051: protected String
1052: paramString()
1053: {
1054:   return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
1055: }
1056: 
1057:   /**
1058:    * Returns an array of all the objects currently registered as FooListeners
1059:    * upon this <code>List</code>. FooListeners are registered using the 
1060:    * addFooListener method.
1061:    *
1062:    * @exception ClassCastException If listenerType doesn't specify a class or
1063:    * interface that implements java.util.EventListener.
1064:    */
1065:   public EventListener[] getListeners (Class listenerType)
1066:   {
1067:     if (listenerType == ActionListener.class)
1068:       return AWTEventMulticaster.getListeners (action_listeners, listenerType);
1069:     
1070:     if (listenerType == ItemListener.class)
1071:       return AWTEventMulticaster.getListeners (item_listeners, listenerType);
1072: 
1073:     return super.getListeners (listenerType);
1074:   }
1075: 
1076:   /**
1077:    * Returns all action listeners registered to this object.
1078:    */
1079:   public ActionListener[] getActionListeners ()
1080:   {
1081:     return (ActionListener[]) getListeners (ActionListener.class);
1082:   }
1083:   
1084:   /**
1085:    * Returns all action listeners registered to this object.
1086:    */
1087:   public ItemListener[] getItemListeners ()
1088:   {
1089:     return (ItemListener[]) getListeners (ItemListener.class);
1090:   }
1091:   
1092:   // Accessibility internal class 
1093:   protected class AccessibleAWTList extends AccessibleAWTComponent
1094:     implements AccessibleSelection, ItemListener, ActionListener
1095:   {
1096:     private static final long serialVersionUID = 7924617370136012829L;
1097: 
1098:     protected class AccessibleAWTListChild extends AccessibleAWTComponent
1099:       implements Accessible
1100:     {
1101:       private static final long serialVersionUID = 4412022926028300317L;
1102:       
1103:       // Field names are fixed by serialization spec.
1104:       private List parent;
1105:       private int indexInParent;
1106:       
1107:       public AccessibleAWTListChild(List parent, int indexInParent)
1108:       {
1109:         this.parent = parent;
1110:         this.indexInParent = indexInParent;
1111:         if (parent == null)
1112:           this.indexInParent = -1;
1113:       }
1114:       
1115:       /* (non-Javadoc)
1116:        * @see javax.accessibility.Accessible#getAccessibleContext()
1117:        */
1118:       public AccessibleContext getAccessibleContext()
1119:       {
1120:         return this;
1121:       }
1122:       
1123:       public AccessibleRole getAccessibleRole()
1124:       {
1125:         return AccessibleRole.LIST_ITEM;
1126:       }
1127:       
1128:       public AccessibleStateSet getAccessibleStateSet()
1129:       {
1130:         AccessibleStateSet states = super.getAccessibleStateSet();
1131:         if (parent.isIndexSelected(indexInParent))
1132:           states.add(AccessibleState.SELECTED);
1133:         return states;
1134:       }
1135:       
1136:       public int getAccessibleIndexInParent()
1137:       {
1138:         return indexInParent;
1139:       }
1140: 
1141:     }
1142:     
1143:     public AccessibleAWTList()
1144:     {
1145:       addItemListener(this);
1146:       addActionListener(this);
1147:     }
1148:     
1149:     public AccessibleRole getAccessibleRole()
1150:     {
1151:       return AccessibleRole.LIST;
1152:     }
1153:     
1154:     public AccessibleStateSet getAccessibleStateSet()
1155:     {
1156:       AccessibleStateSet states = super.getAccessibleStateSet();
1157:       states.add(AccessibleState.SELECTABLE);
1158:       if (isMultipleMode())
1159:         states.add(AccessibleState.MULTISELECTABLE);
1160:       return states;
1161:     }
1162: 
1163:     public int getAccessibleChildrenCount()
1164:     {
1165:       return getItemCount();
1166:     }
1167: 
1168:     public Accessible getAccessibleChild(int i)
1169:     {
1170:       if (i >= getItemCount())
1171:         return null;
1172:       return new AccessibleAWTListChild(List.this, i);
1173:     }
1174:     
1175:     /* (non-Javadoc)
1176:      * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount()
1177:      */
1178:     public int getAccessibleSelectionCount()
1179:     {
1180:       return getSelectedIndexes().length;
1181:     }
1182: 
1183:     /* (non-Javadoc)
1184:      * @see javax.accessibility.AccessibleSelection#getAccessibleSelection()
1185:      */
1186:     public AccessibleSelection getAccessibleSelection()
1187:     {
1188:       return this;
1189:     }
1190: 
1191:     /* (non-Javadoc)
1192:      * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int)
1193:      */
1194:     public Accessible getAccessibleSelection(int i)
1195:     {
1196:       int[] items = getSelectedIndexes();
1197:       if (i >= items.length)
1198:         return null;
1199:       return new AccessibleAWTListChild(List.this, items[i]);
1200:     }
1201: 
1202:     /* (non-Javadoc)
1203:      * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int)
1204:      */
1205:     public boolean isAccessibleChildSelected(int i)
1206:     {
1207:       return isIndexSelected(i);
1208:     }
1209: 
1210:     /* (non-Javadoc)
1211:      * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int)
1212:      */
1213:     public void addAccessibleSelection(int i)
1214:     {
1215:       select(i);
1216:     }
1217: 
1218:     /* (non-Javadoc)
1219:      * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int)
1220:      */
1221:     public void removeAccessibleSelection(int i)
1222:     {
1223:       deselect(i);
1224:     }
1225: 
1226:     /* (non-Javadoc)
1227:      * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection()
1228:      */
1229:     public void clearAccessibleSelection()
1230:     {
1231:       for (int i = 0; i < getItemCount(); i++)
1232:         deselect(i);
1233:     }
1234: 
1235:     /* (non-Javadoc)
1236:      * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection()
1237:      */
1238:     public void selectAllAccessibleSelection()
1239:     {
1240:       if (isMultipleMode())
1241:         for (int i = 0; i < getItemCount(); i++)
1242:           select(i);
1243:     }
1244: 
1245:     /* (non-Javadoc)
1246:      * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
1247:      */
1248:     public void itemStateChanged(ItemEvent event)
1249:     {
1250:     }
1251: 
1252:     /* (non-Javadoc)
1253:      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
1254:      */
1255:     public void actionPerformed(ActionEvent event)
1256:     {
1257:     }
1258:     
1259:   }
1260: 
1261:   /**
1262:    * Gets the AccessibleContext associated with this <code>List</code>.
1263:    * The context is created, if necessary.
1264:    *
1265:    * @return the associated context
1266:    */
1267:   public AccessibleContext getAccessibleContext()
1268:   {
1269:     /* Create the context if this is the first request */
1270:     if (accessibleContext == null)
1271:       accessibleContext = new AccessibleAWTList();
1272:     return accessibleContext;
1273:   }
1274:   
1275:   /**
1276:    * Generate a unique name for this <code>List</code>.
1277:    *
1278:    * @return A unique name for this <code>List</code>.
1279:    */
1280:   String generateName()
1281:   {
1282:     return "list" + getUniqueLong();
1283:   }
1284: 
1285:   private static synchronized long getUniqueLong()
1286:   {
1287:     return next_list_number++;
1288:   }
1289: } // class List