Source for java.awt.List

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