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