1 /*
   2  * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.awt;
  26 
  27 import java.util.Vector;
  28 import java.util.Locale;
  29 import java.util.EventListener;
  30 import java.awt.peer.ListPeer;
  31 import java.awt.event.*;
  32 import java.io.ObjectOutputStream;
  33 import java.io.ObjectInputStream;
  34 import java.io.IOException;
  35 import javax.accessibility.*;
  36 
  37 
  38 /**
  39  * The <code>List</code> component presents the user with a
  40  * scrolling list of text items. The list can be set up so that
  41  * the user can choose either one item or multiple items.
  42  * <p>
  43  * For example, the code&nbsp;.&nbsp;.&nbsp;.
  44  *
  45  * <hr><blockquote><pre>
  46  * List lst = new List(4, false);
  47  * lst.add("Mercury");
  48  * lst.add("Venus");
  49  * lst.add("Earth");
  50  * lst.add("JavaSoft");
  51  * lst.add("Mars");
  52  * lst.add("Jupiter");
  53  * lst.add("Saturn");
  54  * lst.add("Uranus");
  55  * lst.add("Neptune");
  56  * lst.add("Pluto");
  57  * cnt.add(lst);
  58  * </pre></blockquote><hr>
  59  * <p>
  60  * where <code>cnt</code> is a container, produces the following
  61  * scrolling list:
  62  * <p>
  63  * <img src="doc-files/List-1.gif"
  64  * alt="Shows a list containing: Venus, Earth, JavaSoft, and Mars. Javasoft is selected." style="float:center; margin: 7px 10px;">
  65  * <p>
  66  * If the List allows multiple selections, then clicking on
  67  * an item that is already selected deselects it. In the preceding
  68  * example, only one item from the scrolling list can be selected
  69  * at a time, since the second argument when creating the new scrolling
  70  * list is <code>false</code>. If the List does not allow multiple
  71  * selections, selecting an item causes any other selected item
  72  * to be deselected.
  73  * <p>
  74  * Note that the list in the example shown was created with four visible
  75  * rows.  Once the list has been created, the number of visible rows
  76  * cannot be changed.  A default <code>List</code> is created with
  77  * four rows, so that <code>lst = new List()</code> is equivalent to
  78  * <code>list = new List(4, false)</code>.
  79  * <p>
  80  * Beginning with Java&nbsp;1.1, the Abstract Window Toolkit
  81  * sends the <code>List</code> object all mouse, keyboard, and focus events
  82  * that occur over it. (The old AWT event model is being maintained
  83  * only for backwards compatibility, and its use is discouraged.)
  84  * <p>
  85  * When an item is selected or deselected by the user, AWT sends an instance
  86  * of <code>ItemEvent</code> to the list.
  87  * When the user double-clicks on an item in a scrolling list,
  88  * AWT sends an instance of <code>ActionEvent</code> to the
  89  * list following the item event. AWT also generates an action event
  90  * when the user presses the return key while an item in the
  91  * list is selected.
  92  * <p>
  93  * If an application wants to perform some action based on an item
  94  * in this list being selected or activated by the user, it should implement
  95  * <code>ItemListener</code> or <code>ActionListener</code>
  96  * as appropriate and register the new listener to receive
  97  * events from this list.
  98  * <p>
  99  * For multiple-selection scrolling lists, it is considered a better
 100  * user interface to use an external gesture (such as clicking on a
 101  * button) to trigger the action.
 102  * @author      Sami Shaio
 103  * @see         java.awt.event.ItemEvent
 104  * @see         java.awt.event.ItemListener
 105  * @see         java.awt.event.ActionEvent
 106  * @see         java.awt.event.ActionListener
 107  * @since       JDK1.0
 108  */
 109 public class List extends Component implements ItemSelectable, Accessible {
 110     /**
 111      * A vector created to contain items which will become
 112      * part of the List Component.
 113      *
 114      * @serial
 115      * @see #addItem(String)
 116      * @see #getItem(int)
 117      */
 118     Vector<String>      items = new Vector<>();
 119 
 120     /**
 121      * This field will represent the number of visible rows in the
 122      * <code>List</code> Component.  It is specified only once, and
 123      * that is when the list component is actually
 124      * created.  It will never change.
 125      *
 126      * @serial
 127      * @see #getRows()
 128      */
 129     int         rows = 0;
 130 
 131     /**
 132      * <code>multipleMode</code> is a variable that will
 133      * be set to <code>true</code> if a list component is to be set to
 134      * multiple selection mode, that is where the user can
 135      * select more than one item in a list at one time.
 136      * <code>multipleMode</code> will be set to false if the
 137      * list component is set to single selection, that is where
 138      * the user can only select one item on the list at any
 139      * one time.
 140      *
 141      * @serial
 142      * @see #isMultipleMode()
 143      * @see #setMultipleMode(boolean)
 144      */
 145     boolean     multipleMode = false;
 146 
 147     /**
 148      * <code>selected</code> is an array that will contain
 149      * the indices of items that have been selected.
 150      *
 151      * @serial
 152      * @see #getSelectedIndexes()
 153      * @see #getSelectedIndex()
 154      */
 155     int         selected[] = new int[0];
 156 
 157     /**
 158      * This variable contains the value that will be used
 159      * when trying to make a particular list item visible.
 160      *
 161      * @serial
 162      * @see #makeVisible(int)
 163      */
 164     int         visibleIndex = -1;
 165 
 166     transient ActionListener actionListener;
 167     transient ItemListener itemListener;
 168 
 169     private static final String base = "list";
 170     private static int nameCounter = 0;
 171 
 172     /*
 173      * JDK 1.1 serialVersionUID
 174      */
 175      private static final long serialVersionUID = -3304312411574666869L;
 176 
 177     /**
 178      * Creates a new scrolling list.
 179      * By default, there are four visible lines and multiple selections are
 180      * not allowed.  Note that this is a convenience method for
 181      * <code>List(0, false)</code>.  Also note that the number of visible
 182      * lines in the list cannot be changed after it has been created.
 183      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 184      * returns true.
 185      * @see java.awt.GraphicsEnvironment#isHeadless
 186      */
 187     public List() throws HeadlessException {
 188         this(0, false);
 189     }
 190 
 191     /**
 192      * Creates a new scrolling list initialized with the specified
 193      * number of visible lines. By default, multiple selections are
 194      * not allowed.  Note that this is a convenience method for
 195      * <code>List(rows, false)</code>.  Also note that the number
 196      * of visible rows in the list cannot be changed after it has
 197      * been created.
 198      * @param       rows the number of items to show.
 199      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 200      * returns true.
 201      * @see java.awt.GraphicsEnvironment#isHeadless
 202      * @since       JDK1.1
 203      */
 204     public List(int rows) throws HeadlessException {
 205         this(rows, false);
 206     }
 207 
 208     /**
 209      * The default number of visible rows is 4.  A list with
 210      * zero rows is unusable and unsightly.
 211      */
 212     final static int    DEFAULT_VISIBLE_ROWS = 4;
 213 
 214     /**
 215      * Creates a new scrolling list initialized to display the specified
 216      * number of rows. Note that if zero rows are specified, then
 217      * the list will be created with a default of four rows.
 218      * Also note that the number of visible rows in the list cannot
 219      * be changed after it has been created.
 220      * If the value of <code>multipleMode</code> is
 221      * <code>true</code>, then the user can select multiple items from
 222      * the list. If it is <code>false</code>, only one item at a time
 223      * can be selected.
 224      * @param       rows   the number of items to show.
 225      * @param       multipleMode   if <code>true</code>,
 226      *                     then multiple selections are allowed;
 227      *                     otherwise, only one item can be selected at a time.
 228      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 229      * returns true.
 230      * @see java.awt.GraphicsEnvironment#isHeadless
 231      */
 232     public List(int rows, boolean multipleMode) throws HeadlessException {
 233         GraphicsEnvironment.checkHeadless();
 234         this.rows = (rows != 0) ? rows : DEFAULT_VISIBLE_ROWS;
 235         this.multipleMode = multipleMode;
 236     }
 237 
 238     /**
 239      * Construct a name for this component.  Called by
 240      * <code>getName</code> when the name is <code>null</code>.
 241      */
 242     String constructComponentName() {
 243         synchronized (List.class) {
 244             return base + nameCounter++;
 245         }
 246     }
 247 
 248     /**
 249      * Creates the peer for the list.  The peer allows us to modify the
 250      * list's appearance without changing its functionality.
 251      */
 252     public void addNotify() {
 253         synchronized (getTreeLock()) {
 254             if (peer == null)
 255                 peer = getToolkit().createList(this);
 256             super.addNotify();
 257         }
 258     }
 259 
 260     /**
 261      * Removes the peer for this list.  The peer allows us to modify the
 262      * list's appearance without changing its functionality.
 263      */
 264     public void removeNotify() {
 265         synchronized (getTreeLock()) {
 266             ListPeer peer = (ListPeer)this.peer;
 267             if (peer != null) {
 268                 selected = peer.getSelectedIndexes();
 269             }
 270             super.removeNotify();
 271         }
 272     }
 273 
 274     /**
 275      * Gets the number of items in the list.
 276      * @return     the number of items in the list
 277      * @see        #getItem
 278      * @since      JDK1.1
 279      */
 280     public int getItemCount() {
 281         return countItems();
 282     }
 283 
 284     /**
 285      * @return  the number of items in the list
 286      * @deprecated As of JDK version 1.1,
 287      * replaced by <code>getItemCount()</code>.
 288      */
 289     @Deprecated
 290     public int countItems() {
 291         return items.size();
 292     }
 293 
 294     /**
 295      * Gets the item associated with the specified index.
 296      * @return       an item that is associated with
 297      *                    the specified index
 298      * @param        index the position of the item
 299      * @see          #getItemCount
 300      */
 301     public String getItem(int index) {
 302         return getItemImpl(index);
 303     }
 304 
 305     // NOTE: This method may be called by privileged threads.
 306     //       We implement this functionality in a package-private method
 307     //       to insure that it cannot be overridden by client subclasses.
 308     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 309     final String getItemImpl(int index) {
 310         return items.elementAt(index);
 311     }
 312 
 313     /**
 314      * Gets the items in the list.
 315      * @return       a string array containing items of the list
 316      * @see          #select
 317      * @see          #deselect
 318      * @see          #isIndexSelected
 319      * @since        JDK1.1
 320      */
 321     public synchronized String[] getItems() {
 322         String itemCopies[] = new String[items.size()];
 323         items.copyInto(itemCopies);
 324         return itemCopies;
 325     }
 326 
 327     /**
 328      * Adds the specified item to the end of scrolling list.
 329      * @param item the item to be added
 330      * @since JDK1.1
 331      */
 332     public void add(String item) {
 333         addItem(item);
 334     }
 335 
 336     /**
 337      * Adds the specified item to the end of the list
 338      * @param item  the item to be added
 339      * @deprecated      replaced by <code>add(String)</code>.
 340      */
 341     @Deprecated
 342     public void addItem(String item) {
 343         addItem(item, -1);
 344     }
 345 
 346     /**
 347      * Adds the specified item to the the scrolling list
 348      * at the position indicated by the index.  The index is
 349      * zero-based.  If the value of the index is less than zero,
 350      * or if the value of the index is greater than or equal to
 351      * the number of items in the list, then the item is added
 352      * to the end of the list.
 353      * @param       item   the item to be added;
 354      *              if this parameter is <code>null</code> then the item is
 355      *              treated as an empty string, <code>""</code>
 356      * @param       index  the position at which to add the item
 357      * @since       JDK1.1
 358      */
 359     public void add(String item, int index) {
 360         addItem(item, index);
 361     }
 362 
 363     /**
 364      * Adds the specified item to the the list
 365      * at the position indicated by the index.
 366      * @param item   the item to be added
 367      * @param index  the position at which to add the item
 368      * @deprecated   replaced by <code>add(String, int)</code>.
 369      */
 370     @Deprecated
 371     public synchronized void addItem(String item, int index) {
 372         if (index < -1 || index >= items.size()) {
 373             index = -1;
 374         }
 375 
 376         if (item == null) {
 377             item = "";
 378         }
 379 
 380         if (index == -1) {
 381             items.addElement(item);
 382         } else {
 383             items.insertElementAt(item, index);
 384         }
 385 
 386         ListPeer peer = (ListPeer)this.peer;
 387         if (peer != null) {
 388             peer.add(item, index);
 389         }
 390     }
 391 
 392     /**
 393      * Replaces the item at the specified index in the scrolling list
 394      * with the new string.
 395      * @param       newValue   a new string to replace an existing item
 396      * @param       index      the position of the item to replace
 397      * @exception ArrayIndexOutOfBoundsException if <code>index</code>
 398      *          is out of range
 399      */
 400     public synchronized void replaceItem(String newValue, int index) {
 401         remove(index);
 402         add(newValue, index);
 403     }
 404 
 405     /**
 406      * Removes all items from this list.
 407      * @see #remove
 408      * @see #delItems
 409      * @since JDK1.1
 410      */
 411     public void removeAll() {
 412         clear();
 413     }
 414 
 415     /**
 416      * @deprecated As of JDK version 1.1,
 417      * replaced by <code>removeAll()</code>.
 418      */
 419     @Deprecated
 420     public synchronized void clear() {
 421         ListPeer peer = (ListPeer)this.peer;
 422         if (peer != null) {
 423             peer.removeAll();
 424         }
 425         items = new Vector<>();
 426         selected = new int[0];
 427     }
 428 
 429     /**
 430      * Removes the first occurrence of an item from the list.
 431      * If the specified item is selected, and is the only selected
 432      * item in the list, the list is set to have no selection.
 433      * @param        item  the item to remove from the list
 434      * @exception    IllegalArgumentException
 435      *                     if the item doesn't exist in the list
 436      * @since        JDK1.1
 437      */
 438     public synchronized void remove(String item) {
 439         int index = items.indexOf(item);
 440         if (index < 0) {
 441             throw new IllegalArgumentException("item " + item +
 442                                                " not found in list");
 443         } else {
 444             remove(index);
 445         }
 446     }
 447 
 448     /**
 449      * Removes the item at the specified position
 450      * from this scrolling list.
 451      * If the item with the specified position is selected, and is the
 452      * only selected item in the list, the list is set to have no selection.
 453      * @param      position   the index of the item to delete
 454      * @see        #add(String, int)
 455      * @since      JDK1.1
 456      * @exception    ArrayIndexOutOfBoundsException
 457      *               if the <code>position</code> is less than 0 or
 458      *               greater than <code>getItemCount()-1</code>
 459      */
 460     public void remove(int position) {
 461         delItem(position);
 462     }
 463 
 464     /**
 465      * Removes the item at the specified position
 466      * @param  position  the index of the item to delete
 467      * @deprecated     replaced by <code>remove(String)</code>
 468      *                         and <code>remove(int)</code>.
 469      */
 470     @Deprecated
 471     public void delItem(int position) {
 472         delItems(position, position);
 473     }
 474 
 475     /**
 476      * Gets the index of the selected item on the list,
 477      *
 478      * @return        the index of the selected item;
 479      *                if no item is selected, or if multiple items are
 480      *                selected, <code>-1</code> is returned.
 481      * @see           #select
 482      * @see           #deselect
 483      * @see           #isIndexSelected
 484      */
 485     public synchronized int getSelectedIndex() {
 486         int sel[] = getSelectedIndexes();
 487         return (sel.length == 1) ? sel[0] : -1;
 488     }
 489 
 490     /**
 491      * Gets the selected indexes on the list.
 492      *
 493      * @return        an array of the selected indexes on this scrolling list;
 494      *                if no item is selected, a zero-length array is returned.
 495      * @see           #select
 496      * @see           #deselect
 497      * @see           #isIndexSelected
 498      */
 499     public synchronized int[] getSelectedIndexes() {
 500         ListPeer peer = (ListPeer)this.peer;
 501         if (peer != null) {
 502             selected = peer.getSelectedIndexes();
 503         }
 504         return selected.clone();
 505     }
 506 
 507     /**
 508      * Gets the selected item on this scrolling list.
 509      *
 510      * @return        the selected item on the list;
 511      *                if no item is selected, or if multiple items are
 512      *                selected, <code>null</code> is returned.
 513      * @see           #select
 514      * @see           #deselect
 515      * @see           #isIndexSelected
 516      */
 517     public synchronized String getSelectedItem() {
 518         int index = getSelectedIndex();
 519         return (index < 0) ? null : getItem(index);
 520     }
 521 
 522     /**
 523      * Gets the selected items on this scrolling list.
 524      *
 525      * @return        an array of the selected items on this scrolling list;
 526      *                if no item is selected, a zero-length array is returned.
 527      * @see           #select
 528      * @see           #deselect
 529      * @see           #isIndexSelected
 530      */
 531     public synchronized String[] getSelectedItems() {
 532         int sel[] = getSelectedIndexes();
 533         String str[] = new String[sel.length];
 534         for (int i = 0 ; i < sel.length ; i++) {
 535             str[i] = getItem(sel[i]);
 536         }
 537         return str;
 538     }
 539 
 540     /**
 541      * Gets the selected items on this scrolling list in an array of Objects.
 542      * @return        an array of <code>Object</code>s representing the
 543      *                selected items on this scrolling list;
 544      *                if no item is selected, a zero-length array is returned.
 545      * @see #getSelectedItems
 546      * @see ItemSelectable
 547      */
 548     public Object[] getSelectedObjects() {
 549         return getSelectedItems();
 550     }
 551 
 552     /**
 553      * Selects the item at the specified index in the scrolling list.
 554      *<p>
 555      * Note that passing out of range parameters is invalid,
 556      * and will result in unspecified behavior.
 557      *
 558      * <p>Note that this method should be primarily used to
 559      * initially select an item in this component.
 560      * Programmatically calling this method will <i>not</i> trigger
 561      * an <code>ItemEvent</code>.  The only way to trigger an
 562      * <code>ItemEvent</code> is by user interaction.
 563      *
 564      * @param        index the position of the item to select
 565      * @see          #getSelectedItem
 566      * @see          #deselect
 567      * @see          #isIndexSelected
 568      */
 569     public void select(int index) {
 570         // Bug #4059614: select can't be synchronized while calling the peer,
 571         // because it is called from the Window Thread.  It is sufficient to
 572         // synchronize the code that manipulates 'selected' except for the
 573         // case where the peer changes.  To handle this case, we simply
 574         // repeat the selection process.
 575 
 576         ListPeer peer;
 577         do {
 578             peer = (ListPeer)this.peer;
 579             if (peer != null) {
 580                 peer.select(index);
 581                 return;
 582             }
 583 
 584             synchronized(this)
 585             {
 586                 boolean alreadySelected = false;
 587 
 588                 for (int i = 0 ; i < selected.length ; i++) {
 589                     if (selected[i] == index) {
 590                         alreadySelected = true;
 591                         break;
 592                     }
 593                 }
 594 
 595                 if (!alreadySelected) {
 596                     if (!multipleMode) {
 597                         selected = new int[1];
 598                         selected[0] = index;
 599                     } else {
 600                         int newsel[] = new int[selected.length + 1];
 601                         System.arraycopy(selected, 0, newsel, 0,
 602                                          selected.length);
 603                         newsel[selected.length] = index;
 604                         selected = newsel;
 605                     }
 606                 }
 607             }
 608         } while (peer != this.peer);
 609     }
 610 
 611     /**
 612      * Deselects the item at the specified index.
 613      * <p>
 614      * Note that passing out of range parameters is invalid,
 615      * and will result in unspecified behavior.
 616      * <p>
 617      * If the item at the specified index is not selected,
 618      * then the operation is ignored.
 619      * @param        index the position of the item to deselect
 620      * @see          #select
 621      * @see          #getSelectedItem
 622      * @see          #isIndexSelected
 623      */
 624     public synchronized void deselect(int index) {
 625         ListPeer peer = (ListPeer)this.peer;
 626         if (peer != null) {
 627             if (isMultipleMode() || (getSelectedIndex() == index)) {
 628                 peer.deselect(index);
 629             }
 630         }
 631 
 632         for (int i = 0 ; i < selected.length ; i++) {
 633             if (selected[i] == index) {
 634                 int newsel[] = new int[selected.length - 1];
 635                 System.arraycopy(selected, 0, newsel, 0, i);
 636                 System.arraycopy(selected, i+1, newsel, i, selected.length - (i+1));
 637                 selected = newsel;
 638                 return;
 639             }
 640         }
 641     }
 642 
 643     /**
 644      * Determines if the specified item in this scrolling list is
 645      * selected.
 646      * @param      index   the item to be checked
 647      * @return     <code>true</code> if the specified item has been
 648      *                       selected; <code>false</code> otherwise
 649      * @see        #select
 650      * @see        #deselect
 651      * @since      JDK1.1
 652      */
 653     public boolean isIndexSelected(int index) {
 654         return isSelected(index);
 655     }
 656 
 657     /**
 658      * Determines if the specified item in the list is selected.
 659      * @param index  specifies the item to be checked
 660      * @return  {@code true} if the item is selected; otherwise {@code false}
 661      * @deprecated As of JDK version 1.1,
 662      * replaced by <code>isIndexSelected(int)</code>.
 663      */
 664     @Deprecated
 665     public boolean isSelected(int index) {
 666         int sel[] = getSelectedIndexes();
 667         for (int i = 0 ; i < sel.length ; i++) {
 668             if (sel[i] == index) {
 669                 return true;
 670             }
 671         }
 672         return false;
 673     }
 674 
 675     /**
 676      * Gets the number of visible lines in this list.  Note that
 677      * once the <code>List</code> has been created, this number
 678      * will never change.
 679      * @return     the number of visible lines in this scrolling list
 680      */
 681     public int getRows() {
 682         return rows;
 683     }
 684 
 685     /**
 686      * Determines whether this list allows multiple selections.
 687      * @return     <code>true</code> if this list allows multiple
 688      *                 selections; otherwise, <code>false</code>
 689      * @see        #setMultipleMode
 690      * @since      JDK1.1
 691      */
 692     public boolean isMultipleMode() {
 693         return allowsMultipleSelections();
 694     }
 695 
 696     /**
 697      * Determines whether this list allows multiple selections.
 698      * @return  {@code true} if this list allows multiple
 699      *          selections; otherwise {@code false}
 700      * @deprecated As of JDK version 1.1,
 701      * replaced by <code>isMultipleMode()</code>.
 702      */
 703     @Deprecated
 704     public boolean allowsMultipleSelections() {
 705         return multipleMode;
 706     }
 707 
 708     /**
 709      * Sets the flag that determines whether this list
 710      * allows multiple selections.
 711      * When the selection mode is changed from multiple-selection to
 712      * single-selection, the selected items change as follows:
 713      * If a selected item has the location cursor, only that
 714      * item will remain selected.  If no selected item has the
 715      * location cursor, all items will be deselected.
 716      * @param       b   if <code>true</code> then multiple selections
 717      *                      are allowed; otherwise, only one item from
 718      *                      the list can be selected at once
 719      * @see         #isMultipleMode
 720      * @since       JDK1.1
 721      */
 722     public void setMultipleMode(boolean b) {
 723         setMultipleSelections(b);
 724     }
 725 
 726     /**
 727      * Enables or disables multiple selection mode for this list.
 728      * @param b  {@code true} to enable multiple mode, {@code false} otherwise
 729      * @deprecated As of JDK version 1.1,
 730      * replaced by <code>setMultipleMode(boolean)</code>.
 731      */
 732     @Deprecated
 733     public synchronized void setMultipleSelections(boolean b) {
 734         if (b != multipleMode) {
 735             multipleMode = b;
 736             ListPeer peer = (ListPeer)this.peer;
 737             if (peer != null) {
 738                 peer.setMultipleMode(b);
 739             }
 740         }
 741     }
 742 
 743     /**
 744      * Gets the index of the item that was last made visible by
 745      * the method <code>makeVisible</code>.
 746      * @return      the index of the item that was last made visible
 747      * @see         #makeVisible
 748      */
 749     public int getVisibleIndex() {
 750         return visibleIndex;
 751     }
 752 
 753     /**
 754      * Makes the item at the specified index visible.
 755      * @param       index    the position of the item
 756      * @see         #getVisibleIndex
 757      */
 758     public synchronized void makeVisible(int index) {
 759         visibleIndex = index;
 760         ListPeer peer = (ListPeer)this.peer;
 761         if (peer != null) {
 762             peer.makeVisible(index);
 763         }
 764     }
 765 
 766     /**
 767      * Gets the preferred dimensions for a list with the specified
 768      * number of rows.
 769      * @param      rows    number of rows in the list
 770      * @return     the preferred dimensions for displaying this scrolling list
 771      *             given that the specified number of rows must be visible
 772      * @see        java.awt.Component#getPreferredSize
 773      * @since      JDK1.1
 774      */
 775     public Dimension getPreferredSize(int rows) {
 776         return preferredSize(rows);
 777     }
 778 
 779     /**
 780      * Returns the preferred size of this component
 781      * assuming it has the specified number of rows.
 782      * @param rows  the number of rows
 783      * @return  the preferred dimensions for displaying this list
 784      * @deprecated As of JDK version 1.1,
 785      * replaced by <code>getPreferredSize(int)</code>.
 786      */
 787     @Deprecated
 788     public Dimension preferredSize(int rows) {
 789         synchronized (getTreeLock()) {
 790             ListPeer peer = (ListPeer)this.peer;
 791             return (peer != null) ?
 792                        peer.getPreferredSize(rows) :
 793                        super.preferredSize();
 794         }
 795     }
 796 
 797     /**
 798      * Gets the preferred size of this scrolling list.
 799      * @return     the preferred dimensions for displaying this scrolling list
 800      * @see        java.awt.Component#getPreferredSize
 801      * @since      JDK1.1
 802      */
 803     public Dimension getPreferredSize() {
 804         return preferredSize();
 805     }
 806 
 807     /**
 808      * @deprecated As of JDK version 1.1,
 809      * replaced by <code>getPreferredSize()</code>.
 810      */
 811     @Deprecated
 812     public Dimension preferredSize() {
 813         synchronized (getTreeLock()) {
 814             return (rows > 0) ?
 815                        preferredSize(rows) :
 816                        super.preferredSize();
 817         }
 818     }
 819 
 820     /**
 821      * Gets the minimum dimensions for a list with the specified
 822      * number of rows.
 823      * @param      rows    number of rows in the list
 824      * @return     the minimum dimensions for displaying this scrolling list
 825      *             given that the specified number of rows must be visible
 826      * @see        java.awt.Component#getMinimumSize
 827      * @since      JDK1.1
 828      */
 829     public Dimension getMinimumSize(int rows) {
 830         return minimumSize(rows);
 831     }
 832 
 833     /**
 834      * Returns the minimum dimensions for the list
 835      * with the specified number of rows.
 836      * @param  rows  the number of rows in the list
 837      * @return the minimum dimensions for displaying this list
 838      * @deprecated As of JDK version 1.1,
 839      * replaced by <code>getMinimumSize(int)</code>.
 840      */
 841     @Deprecated
 842     public Dimension minimumSize(int rows) {
 843         synchronized (getTreeLock()) {
 844             ListPeer peer = (ListPeer)this.peer;
 845             return (peer != null) ?
 846                        peer.getMinimumSize(rows) :
 847                        super.minimumSize();
 848         }
 849     }
 850 
 851     /**
 852      * Determines the minimum size of this scrolling list.
 853      * @return       the minimum dimensions needed
 854      *                        to display this scrolling list
 855      * @see          java.awt.Component#getMinimumSize()
 856      * @since        JDK1.1
 857      */
 858     public Dimension getMinimumSize() {
 859         return minimumSize();
 860     }
 861 
 862     /**
 863      * @deprecated As of JDK version 1.1,
 864      * replaced by <code>getMinimumSize()</code>.
 865      */
 866     @Deprecated
 867     public Dimension minimumSize() {
 868         synchronized (getTreeLock()) {
 869             return (rows > 0) ? minimumSize(rows) : super.minimumSize();
 870         }
 871     }
 872 
 873     /**
 874      * Adds the specified item listener to receive item events from
 875      * this list.  Item events are sent in response to user input, but not
 876      * in response to calls to <code>select</code> or <code>deselect</code>.
 877      * If listener <code>l</code> is <code>null</code>,
 878      * no exception is thrown and no action is performed.
 879      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 880      * >AWT Threading Issues</a> for details on AWT's threading model.
 881      *
 882      * @param         l the item listener
 883      * @see           #removeItemListener
 884      * @see           #getItemListeners
 885      * @see           #select
 886      * @see           #deselect
 887      * @see           java.awt.event.ItemEvent
 888      * @see           java.awt.event.ItemListener
 889      * @since         JDK1.1
 890      */
 891     public synchronized void addItemListener(ItemListener l) {
 892         if (l == null) {
 893             return;
 894         }
 895         itemListener = AWTEventMulticaster.add(itemListener, l);
 896         newEventsOnly = true;
 897     }
 898 
 899     /**
 900      * Removes the specified item listener so that it no longer
 901      * receives item events from this list.
 902      * If listener <code>l</code> is <code>null</code>,
 903      * no exception is thrown and no action is performed.
 904      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 905      * >AWT Threading Issues</a> for details on AWT's threading model.
 906      *
 907      * @param           l the item listener
 908      * @see             #addItemListener
 909      * @see             #getItemListeners
 910      * @see             java.awt.event.ItemEvent
 911      * @see             java.awt.event.ItemListener
 912      * @since           JDK1.1
 913      */
 914     public synchronized void removeItemListener(ItemListener l) {
 915         if (l == null) {
 916             return;
 917         }
 918         itemListener = AWTEventMulticaster.remove(itemListener, l);
 919     }
 920 
 921     /**
 922      * Returns an array of all the item listeners
 923      * registered on this list.
 924      *
 925      * @return all of this list's <code>ItemListener</code>s
 926      *         or an empty array if no item
 927      *         listeners are currently registered
 928      *
 929      * @see             #addItemListener
 930      * @see             #removeItemListener
 931      * @see             java.awt.event.ItemEvent
 932      * @see             java.awt.event.ItemListener
 933      * @since 1.4
 934      */
 935     public synchronized ItemListener[] getItemListeners() {
 936         return getListeners(ItemListener.class);
 937     }
 938 
 939     /**
 940      * Adds the specified action listener to receive action events from
 941      * this list. Action events occur when a user double-clicks
 942      * on a list item or types Enter when the list has the keyboard
 943      * focus.
 944      * <p>
 945      * If listener <code>l</code> is <code>null</code>,
 946      * no exception is thrown and no action is performed.
 947      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 948      * >AWT Threading Issues</a> for details on AWT's threading model.
 949      *
 950      * @param         l the action listener
 951      * @see           #removeActionListener
 952      * @see           #getActionListeners
 953      * @see           java.awt.event.ActionEvent
 954      * @see           java.awt.event.ActionListener
 955      * @since         JDK1.1
 956      */
 957     public synchronized void addActionListener(ActionListener l) {
 958         if (l == null) {
 959             return;
 960         }
 961         actionListener = AWTEventMulticaster.add(actionListener, l);
 962         newEventsOnly = true;
 963     }
 964 
 965     /**
 966      * Removes the specified action listener so that it no longer
 967      * receives action events from this list. Action events
 968      * occur when a user double-clicks on a list item.
 969      * If listener <code>l</code> is <code>null</code>,
 970      * no exception is thrown and no action is performed.
 971      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 972      * >AWT Threading Issues</a> for details on AWT's threading model.
 973      *
 974      * @param           l     the action listener
 975      * @see             #addActionListener
 976      * @see             #getActionListeners
 977      * @see             java.awt.event.ActionEvent
 978      * @see             java.awt.event.ActionListener
 979      * @since           JDK1.1
 980      */
 981     public synchronized void removeActionListener(ActionListener l) {
 982         if (l == null) {
 983             return;
 984         }
 985         actionListener = AWTEventMulticaster.remove(actionListener, l);
 986     }
 987 
 988     /**
 989      * Returns an array of all the action listeners
 990      * registered on this list.
 991      *
 992      * @return all of this list's <code>ActionListener</code>s
 993      *         or an empty array if no action
 994      *         listeners are currently registered
 995      *
 996      * @see             #addActionListener
 997      * @see             #removeActionListener
 998      * @see             java.awt.event.ActionEvent
 999      * @see             java.awt.event.ActionListener
1000      * @since 1.4
1001      */
1002     public synchronized ActionListener[] getActionListeners() {
1003         return getListeners(ActionListener.class);
1004     }
1005 
1006     /**
1007      * Returns an array of all the objects currently registered
1008      * as <code><em>Foo</em>Listener</code>s
1009      * upon this <code>List</code>.
1010      * <code><em>Foo</em>Listener</code>s are registered using the
1011      * <code>add<em>Foo</em>Listener</code> method.
1012      *
1013      * <p>
1014      * You can specify the <code>listenerType</code> argument
1015      * with a class literal, such as
1016      * <code><em>Foo</em>Listener.class</code>.
1017      * For example, you can query a
1018      * <code>List</code> <code>l</code>
1019      * for its item listeners with the following code:
1020      *
1021      * <pre>ItemListener[] ils = (ItemListener[])(l.getListeners(ItemListener.class));</pre>
1022      *
1023      * If no such listeners exist, this method returns an empty array.
1024      *
1025      * @param listenerType the type of listeners requested; this parameter
1026      *          should specify an interface that descends from
1027      *          <code>java.util.EventListener</code>
1028      * @return an array of all objects registered as
1029      *          <code><em>Foo</em>Listener</code>s on this list,
1030      *          or an empty array if no such
1031      *          listeners have been added
1032      * @exception ClassCastException if <code>listenerType</code>
1033      *          doesn't specify a class or interface that implements
1034      *          <code>java.util.EventListener</code>
1035      *
1036      * @see #getItemListeners
1037      * @since 1.3
1038      */
1039     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
1040         EventListener l = null;
1041         if  (listenerType == ActionListener.class) {
1042             l = actionListener;
1043         } else if  (listenerType == ItemListener.class) {
1044             l = itemListener;
1045         } else {
1046             return super.getListeners(listenerType);
1047         }
1048         return AWTEventMulticaster.getListeners(l, listenerType);
1049     }
1050 
1051     // REMIND: remove when filtering is done at lower level
1052     boolean eventEnabled(AWTEvent e) {
1053         switch(e.id) {
1054           case ActionEvent.ACTION_PERFORMED:
1055             if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
1056                 actionListener != null) {
1057                 return true;
1058             }
1059             return false;
1060           case ItemEvent.ITEM_STATE_CHANGED:
1061             if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
1062                 itemListener != null) {
1063                 return true;
1064             }
1065             return false;
1066           default:
1067             break;
1068         }
1069         return super.eventEnabled(e);
1070     }
1071 
1072     /**
1073      * Processes events on this scrolling list. If an event is
1074      * an instance of <code>ItemEvent</code>, it invokes the
1075      * <code>processItemEvent</code> method. Else, if the
1076      * event is an instance of <code>ActionEvent</code>,
1077      * it invokes <code>processActionEvent</code>.
1078      * If the event is not an item event or an action event,
1079      * it invokes <code>processEvent</code> on the superclass.
1080      * <p>Note that if the event parameter is <code>null</code>
1081      * the behavior is unspecified and may result in an
1082      * exception.
1083      *
1084      * @param        e the event
1085      * @see          java.awt.event.ActionEvent
1086      * @see          java.awt.event.ItemEvent
1087      * @see          #processActionEvent
1088      * @see          #processItemEvent
1089      * @since        JDK1.1
1090      */
1091     protected void processEvent(AWTEvent e) {
1092         if (e instanceof ItemEvent) {
1093             processItemEvent((ItemEvent)e);
1094             return;
1095         } else if (e instanceof ActionEvent) {
1096             processActionEvent((ActionEvent)e);
1097             return;
1098         }
1099         super.processEvent(e);
1100     }
1101 
1102     /**
1103      * Processes item events occurring on this list by
1104      * dispatching them to any registered
1105      * <code>ItemListener</code> objects.
1106      * <p>
1107      * This method is not called unless item events are
1108      * enabled for this component. Item events are enabled
1109      * when one of the following occurs:
1110      * <ul>
1111      * <li>An <code>ItemListener</code> object is registered
1112      * via <code>addItemListener</code>.
1113      * <li>Item events are enabled via <code>enableEvents</code>.
1114      * </ul>
1115      * <p>Note that if the event parameter is <code>null</code>
1116      * the behavior is unspecified and may result in an
1117      * exception.
1118      *
1119      * @param       e the item event
1120      * @see         java.awt.event.ItemEvent
1121      * @see         java.awt.event.ItemListener
1122      * @see         #addItemListener
1123      * @see         java.awt.Component#enableEvents
1124      * @since       JDK1.1
1125      */
1126     protected void processItemEvent(ItemEvent e) {
1127         ItemListener listener = itemListener;
1128         if (listener != null) {
1129             listener.itemStateChanged(e);
1130         }
1131     }
1132 
1133     /**
1134      * Processes action events occurring on this component
1135      * by dispatching them to any registered
1136      * <code>ActionListener</code> objects.
1137      * <p>
1138      * This method is not called unless action events are
1139      * enabled for this component. Action events are enabled
1140      * when one of the following occurs:
1141      * <ul>
1142      * <li>An <code>ActionListener</code> object is registered
1143      * via <code>addActionListener</code>.
1144      * <li>Action events are enabled via <code>enableEvents</code>.
1145      * </ul>
1146      * <p>Note that if the event parameter is <code>null</code>
1147      * the behavior is unspecified and may result in an
1148      * exception.
1149      *
1150      * @param       e the action event
1151      * @see         java.awt.event.ActionEvent
1152      * @see         java.awt.event.ActionListener
1153      * @see         #addActionListener
1154      * @see         java.awt.Component#enableEvents
1155      * @since       JDK1.1
1156      */
1157     protected void processActionEvent(ActionEvent e) {
1158         ActionListener listener = actionListener;
1159         if (listener != null) {
1160             listener.actionPerformed(e);
1161         }
1162     }
1163 
1164     /**
1165      * Returns the parameter string representing the state of this
1166      * scrolling list. This string is useful for debugging.
1167      * @return    the parameter string of this scrolling list
1168      */
1169     protected String paramString() {
1170         return super.paramString() + ",selected=" + getSelectedItem();
1171     }
1172 
1173     /**
1174      * Deletes the list items in the specified index range.
1175      * @param  start  the beginning index of the range to delete
1176      * @param  end    the ending index of the range to delete
1177      * @deprecated As of JDK version 1.1,
1178      * Not for public use in the future.
1179      * This method is expected to be retained only as a package
1180      * private method.
1181      */
1182     @Deprecated
1183     public synchronized void delItems(int start, int end) {
1184         for (int i = end; i >= start; i--) {
1185             items.removeElementAt(i);
1186         }
1187         ListPeer peer = (ListPeer)this.peer;
1188         if (peer != null) {
1189             peer.delItems(start, end);
1190         }
1191     }
1192 
1193     /*
1194      * Serialization support.  Since the value of the selected
1195      * field isn't necessarily up to date, we sync it up with the
1196      * peer before serializing.
1197      */
1198 
1199     /**
1200      * The <code>List</code> component's
1201      * Serialized Data Version.
1202      *
1203      * @serial
1204      */
1205     private int listSerializedDataVersion = 1;
1206 
1207     /**
1208      * Writes default serializable fields to stream.  Writes
1209      * a list of serializable <code>ItemListeners</code>
1210      * and <code>ActionListeners</code> as optional data.
1211      * The non-serializable listeners are detected and
1212      * no attempt is made to serialize them.
1213      *
1214      * @serialData <code>null</code> terminated sequence of 0
1215      *  or more pairs; the pair consists of a <code>String</code>
1216      *  and an <code>Object</code>; the <code>String</code>
1217      *  indicates the type of object and is one of the
1218      *  following:
1219      *  <code>itemListenerK</code> indicating an
1220      *    <code>ItemListener</code> object;
1221      *  <code>actionListenerK</code> indicating an
1222      *    <code>ActionListener</code> object
1223      *
1224      * @param s the <code>ObjectOutputStream</code> to write
1225      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1226      * @see java.awt.Component#itemListenerK
1227      * @see java.awt.Component#actionListenerK
1228      * @see #readObject(ObjectInputStream)
1229      */
1230     private void writeObject(ObjectOutputStream s)
1231       throws IOException
1232     {
1233       synchronized (this) {
1234         ListPeer peer = (ListPeer)this.peer;
1235         if (peer != null) {
1236           selected = peer.getSelectedIndexes();
1237         }
1238       }
1239       s.defaultWriteObject();
1240 
1241       AWTEventMulticaster.save(s, itemListenerK, itemListener);
1242       AWTEventMulticaster.save(s, actionListenerK, actionListener);
1243       s.writeObject(null);
1244     }
1245 
1246     /**
1247      * Reads the <code>ObjectInputStream</code> and if it
1248      * isn't <code>null</code> adds a listener to receive
1249      * both item events and action events (as specified
1250      * by the key stored in the stream) fired by the
1251      * <code>List</code>.
1252      * Unrecognized keys or values will be ignored.
1253      *
1254      * @param s the <code>ObjectInputStream</code> to write
1255      * @exception HeadlessException if
1256      *   <code>GraphicsEnvironment.isHeadless</code> returns
1257      *   <code>true</code>
1258      * @see #removeItemListener(ItemListener)
1259      * @see #addItemListener(ItemListener)
1260      * @see java.awt.GraphicsEnvironment#isHeadless
1261      * @see #writeObject(ObjectOutputStream)
1262      */
1263     private void readObject(ObjectInputStream s)
1264       throws ClassNotFoundException, IOException, HeadlessException
1265     {
1266       GraphicsEnvironment.checkHeadless();
1267       s.defaultReadObject();
1268 
1269       Object keyOrNull;
1270       while(null != (keyOrNull = s.readObject())) {
1271         String key = ((String)keyOrNull).intern();
1272 
1273         if (itemListenerK == key)
1274           addItemListener((ItemListener)(s.readObject()));
1275 
1276         else if (actionListenerK == key)
1277           addActionListener((ActionListener)(s.readObject()));
1278 
1279         else // skip value for unrecognized key
1280           s.readObject();
1281       }
1282     }
1283 
1284 
1285 /////////////////
1286 // Accessibility support
1287 ////////////////
1288 
1289 
1290     /**
1291      * Gets the <code>AccessibleContext</code> associated with this
1292      * <code>List</code>. For lists, the <code>AccessibleContext</code>
1293      * takes the form of an <code>AccessibleAWTList</code>.
1294      * A new <code>AccessibleAWTList</code> instance is created, if necessary.
1295      *
1296      * @return an <code>AccessibleAWTList</code> that serves as the
1297      *         <code>AccessibleContext</code> of this <code>List</code>
1298      * @since 1.3
1299      */
1300     public AccessibleContext getAccessibleContext() {
1301         if (accessibleContext == null) {
1302             accessibleContext = new AccessibleAWTList();
1303         }
1304         return accessibleContext;
1305     }
1306 
1307     /**
1308      * This class implements accessibility support for the
1309      * <code>List</code> class.  It provides an implementation of the
1310      * Java Accessibility API appropriate to list user-interface elements.
1311      * @since 1.3
1312      */
1313     protected class AccessibleAWTList extends AccessibleAWTComponent
1314         implements AccessibleSelection, ItemListener, ActionListener
1315     {
1316         /*
1317          * JDK 1.3 serialVersionUID
1318          */
1319         private static final long serialVersionUID = 7924617370136012829L;
1320 
1321         /**
1322          * Constructs new {@code AccessibleAWTList}
1323          */
1324         public AccessibleAWTList() {
1325             super();
1326             List.this.addActionListener(this);
1327             List.this.addItemListener(this);
1328         }
1329 
1330         public void actionPerformed(ActionEvent event)  {
1331         }
1332 
1333         public void itemStateChanged(ItemEvent event)  {
1334         }
1335 
1336         /**
1337          * Get the state set of this object.
1338          *
1339          * @return an instance of AccessibleState containing the current state
1340          * of the object
1341          * @see AccessibleState
1342          */
1343         public AccessibleStateSet getAccessibleStateSet() {
1344             AccessibleStateSet states = super.getAccessibleStateSet();
1345             if (List.this.isMultipleMode())  {
1346                 states.add(AccessibleState.MULTISELECTABLE);
1347             }
1348             return states;
1349         }
1350 
1351         /**
1352          * Get the role of this object.
1353          *
1354          * @return an instance of AccessibleRole describing the role of the
1355          * object
1356          * @see AccessibleRole
1357          */
1358         public AccessibleRole getAccessibleRole() {
1359             return AccessibleRole.LIST;
1360         }
1361 
1362         /**
1363          * Returns the Accessible child contained at the local coordinate
1364          * Point, if one exists.
1365          *
1366          * @return the Accessible at the specified location, if it exists
1367          */
1368         public Accessible getAccessibleAt(Point p) {
1369             return null; // fredxFIXME Not implemented yet
1370         }
1371 
1372         /**
1373          * Returns the number of accessible children in the object.  If all
1374          * of the children of this object implement Accessible, than this
1375          * method should return the number of children of this object.
1376          *
1377          * @return the number of accessible children in the object.
1378          */
1379         public int getAccessibleChildrenCount() {
1380             return List.this.getItemCount();
1381         }
1382 
1383         /**
1384          * Return the nth Accessible child of the object.
1385          *
1386          * @param i zero-based index of child
1387          * @return the nth Accessible child of the object
1388          */
1389         public Accessible getAccessibleChild(int i) {
1390             synchronized(List.this)  {
1391                 if (i >= List.this.getItemCount()) {
1392                     return null;
1393                 } else {
1394                     return new AccessibleAWTListChild(List.this, i);
1395                 }
1396             }
1397         }
1398 
1399         /**
1400          * Get the AccessibleSelection associated with this object.  In the
1401          * implementation of the Java Accessibility API for this class,
1402          * return this object, which is responsible for implementing the
1403          * AccessibleSelection interface on behalf of itself.
1404          *
1405          * @return this object
1406          */
1407         public AccessibleSelection getAccessibleSelection() {
1408             return this;
1409         }
1410 
1411     // AccessibleSelection methods
1412 
1413         /**
1414          * Returns the number of items currently selected.
1415          * If no items are selected, the return value will be 0.
1416          *
1417          * @return the number of items currently selected.
1418          */
1419          public int getAccessibleSelectionCount() {
1420              return List.this.getSelectedIndexes().length;
1421          }
1422 
1423         /**
1424          * Returns an Accessible representing the specified selected item
1425          * in the object.  If there isn't a selection, or there are
1426          * fewer items selected than the integer passed in, the return
1427          * value will be null.
1428          *
1429          * @param i the zero-based index of selected items
1430          * @return an Accessible containing the selected item
1431          */
1432          public Accessible getAccessibleSelection(int i) {
1433              synchronized(List.this)  {
1434                  int len = getAccessibleSelectionCount();
1435                  if (i < 0 || i >= len) {
1436                      return null;
1437                  } else {
1438                      return getAccessibleChild(List.this.getSelectedIndexes()[i]);
1439                  }
1440              }
1441          }
1442 
1443         /**
1444          * Returns true if the current child of this object is selected.
1445          *
1446          * @param i the zero-based index of the child in this Accessible
1447          * object.
1448          * @see AccessibleContext#getAccessibleChild
1449          */
1450         public boolean isAccessibleChildSelected(int i) {
1451             return List.this.isIndexSelected(i);
1452         }
1453 
1454         /**
1455          * Adds the specified selected item in the object to the object's
1456          * selection.  If the object supports multiple selections,
1457          * the specified item is added to any existing selection, otherwise
1458          * it replaces any existing selection in the object.  If the
1459          * specified item is already selected, this method has no effect.
1460          *
1461          * @param i the zero-based index of selectable items
1462          */
1463          public void addAccessibleSelection(int i) {
1464              List.this.select(i);
1465          }
1466 
1467         /**
1468          * Removes the specified selected item in the object from the object's
1469          * selection.  If the specified item isn't currently selected, this
1470          * method has no effect.
1471          *
1472          * @param i the zero-based index of selectable items
1473          */
1474          public void removeAccessibleSelection(int i) {
1475              List.this.deselect(i);
1476          }
1477 
1478         /**
1479          * Clears the selection in the object, so that nothing in the
1480          * object is selected.
1481          */
1482          public void clearAccessibleSelection() {
1483              synchronized(List.this)  {
1484                  int selectedIndexes[] = List.this.getSelectedIndexes();
1485                  if (selectedIndexes == null)
1486                      return;
1487                  for (int i = selectedIndexes.length - 1; i >= 0; i--) {
1488                      List.this.deselect(selectedIndexes[i]);
1489                  }
1490              }
1491          }
1492 
1493         /**
1494          * Causes every selected item in the object to be selected
1495          * if the object supports multiple selections.
1496          */
1497          public void selectAllAccessibleSelection() {
1498              synchronized(List.this)  {
1499                  for (int i = List.this.getItemCount() - 1; i >= 0; i--) {
1500                      List.this.select(i);
1501                  }
1502              }
1503          }
1504 
1505        /**
1506         * This class implements accessibility support for
1507         * List children.  It provides an implementation of the
1508         * Java Accessibility API appropriate to list children
1509         * user-interface elements.
1510         * @since 1.3
1511         */
1512         protected class AccessibleAWTListChild extends AccessibleAWTComponent
1513             implements Accessible
1514         {
1515             /*
1516              * JDK 1.3 serialVersionUID
1517              */
1518             private static final long serialVersionUID = 4412022926028300317L;
1519 
1520         // [[[FIXME]]] need to finish implementing this!!!
1521 
1522             private List parent;
1523             private int  indexInParent;
1524 
1525             /**
1526              * Constructs new {@code AccessibleAWTListChild} with the given
1527              * parent {@code List} and 0-based index of this object in the parent.
1528              * @param parent         the parent {@code List}
1529              * @param indexInParent  the index in the parent
1530              */
1531             public AccessibleAWTListChild(List parent, int indexInParent)  {
1532                 this.parent = parent;
1533                 this.setAccessibleParent(parent);
1534                 this.indexInParent = indexInParent;
1535             }
1536 
1537             //
1538             // required Accessible methods
1539             //
1540           /**
1541            * Gets the AccessibleContext for this object.  In the
1542            * implementation of the Java Accessibility API for this class,
1543            * return this object, which acts as its own AccessibleContext.
1544            *
1545            * @return this object
1546            */
1547             public AccessibleContext getAccessibleContext() {
1548                 return this;
1549             }
1550 
1551             //
1552             // required AccessibleContext methods
1553             //
1554 
1555             /**
1556              * Get the role of this object.
1557              *
1558              * @return an instance of AccessibleRole describing the role of
1559              * the object
1560              * @see AccessibleRole
1561              */
1562             public AccessibleRole getAccessibleRole() {
1563                 return AccessibleRole.LIST_ITEM;
1564             }
1565 
1566             /**
1567              * Get the state set of this object.  The AccessibleStateSet of an
1568              * object is composed of a set of unique AccessibleState's.  A
1569              * change in the AccessibleStateSet of an object will cause a
1570              * PropertyChangeEvent to be fired for the
1571              * ACCESSIBLE_STATE_PROPERTY property.
1572              *
1573              * @return an instance of AccessibleStateSet containing the
1574              * current state set of the object
1575              * @see AccessibleStateSet
1576              * @see AccessibleState
1577              * @see #addPropertyChangeListener
1578              */
1579             public AccessibleStateSet getAccessibleStateSet() {
1580                 AccessibleStateSet states = super.getAccessibleStateSet();
1581                 if (parent.isIndexSelected(indexInParent)) {
1582                     states.add(AccessibleState.SELECTED);
1583                 }
1584                 return states;
1585             }
1586 
1587             /**
1588              * Gets the locale of the component. If the component does not
1589              * have a locale, then the locale of its parent is returned.
1590              *
1591              * @return This component's locale.  If this component does not have
1592              * a locale, the locale of its parent is returned.
1593              *
1594              * @exception IllegalComponentStateException
1595              * If the Component does not have its own locale and has not yet
1596              * been added to a containment hierarchy such that the locale can
1597              * be determined from the containing parent.
1598              */
1599             public Locale getLocale() {
1600                 return parent.getLocale();
1601             }
1602 
1603             /**
1604              * Get the 0-based index of this object in its accessible parent.
1605              *
1606              * @return the 0-based index of this object in its parent; -1 if
1607              * this object does not have an accessible parent.
1608              *
1609              * @see #getAccessibleParent
1610              * @see #getAccessibleChildrenCount
1611              * @see #getAccessibleChild
1612              */
1613             public int getAccessibleIndexInParent() {
1614                 return indexInParent;
1615             }
1616 
1617             /**
1618              * Returns the number of accessible children of the object.
1619              *
1620              * @return the number of accessible children of the object.
1621              */
1622             public int getAccessibleChildrenCount() {
1623                 return 0;       // list elements can't have children
1624             }
1625 
1626             /**
1627              * Return the specified Accessible child of the object.  The
1628              * Accessible children of an Accessible object are zero-based,
1629              * so the first child of an Accessible child is at index 0, the
1630              * second child is at index 1, and so on.
1631              *
1632              * @param i zero-based index of child
1633              * @return the Accessible child of the object
1634              * @see #getAccessibleChildrenCount
1635              */
1636             public Accessible getAccessibleChild(int i) {
1637                 return null;    // list elements can't have children
1638             }
1639 
1640 
1641             //
1642             // AccessibleComponent delegatation to parent List
1643             //
1644 
1645             /**
1646              * Get the background color of this object.
1647              *
1648              * @return the background color, if supported, of the object;
1649              * otherwise, null
1650              * @see #setBackground
1651              */
1652             public Color getBackground() {
1653                 return parent.getBackground();
1654             }
1655 
1656             /**
1657              * Set the background color of this object.
1658              *
1659              * @param c the new Color for the background
1660              * @see #setBackground
1661              */
1662             public void setBackground(Color c) {
1663                 parent.setBackground(c);
1664             }
1665 
1666             /**
1667              * Get the foreground color of this object.
1668              *
1669              * @return the foreground color, if supported, of the object;
1670              * otherwise, null
1671              * @see #setForeground
1672              */
1673             public Color getForeground() {
1674                 return parent.getForeground();
1675             }
1676 
1677             /**
1678              * Set the foreground color of this object.
1679              *
1680              * @param c the new Color for the foreground
1681              * @see #getForeground
1682              */
1683             public void setForeground(Color c) {
1684                 parent.setForeground(c);
1685             }
1686 
1687             /**
1688              * Get the Cursor of this object.
1689              *
1690              * @return the Cursor, if supported, of the object; otherwise, null
1691              * @see #setCursor
1692              */
1693             public Cursor getCursor() {
1694                 return parent.getCursor();
1695             }
1696 
1697             /**
1698              * Set the Cursor of this object.
1699              * <p>
1700              * The method may have no visual effect if the Java platform
1701              * implementation and/or the native system do not support
1702              * changing the mouse cursor shape.
1703              * @param cursor the new Cursor for the object
1704              * @see #getCursor
1705              */
1706             public void setCursor(Cursor cursor) {
1707                 parent.setCursor(cursor);
1708             }
1709 
1710             /**
1711              * Get the Font of this object.
1712              *
1713              * @return the Font,if supported, for the object; otherwise, null
1714              * @see #setFont
1715              */
1716             public Font getFont() {
1717                 return parent.getFont();
1718             }
1719 
1720             /**
1721              * Set the Font of this object.
1722              *
1723              * @param f the new Font for the object
1724              * @see #getFont
1725              */
1726             public void setFont(Font f) {
1727                 parent.setFont(f);
1728             }
1729 
1730             /**
1731              * Get the FontMetrics of this object.
1732              *
1733              * @param f the Font
1734              * @return the FontMetrics, if supported, the object; otherwise, null
1735              * @see #getFont
1736              */
1737             public FontMetrics getFontMetrics(Font f) {
1738                 return parent.getFontMetrics(f);
1739             }
1740 
1741             /**
1742              * Determine if the object is enabled.  Objects that are enabled
1743              * will also have the AccessibleState.ENABLED state set in their
1744              * AccessibleStateSet.
1745              *
1746              * @return true if object is enabled; otherwise, false
1747              * @see #setEnabled
1748              * @see AccessibleContext#getAccessibleStateSet
1749              * @see AccessibleState#ENABLED
1750              * @see AccessibleStateSet
1751              */
1752             public boolean isEnabled() {
1753                 return parent.isEnabled();
1754             }
1755 
1756             /**
1757              * Set the enabled state of the object.
1758              *
1759              * @param b if true, enables this object; otherwise, disables it
1760              * @see #isEnabled
1761              */
1762             public void setEnabled(boolean b) {
1763                 parent.setEnabled(b);
1764             }
1765 
1766             /**
1767              * Determine if the object is visible.  Note: this means that the
1768              * object intends to be visible; however, it may not be
1769              * showing on the screen because one of the objects that this object
1770              * is contained by is currently not visible.  To determine if an
1771              * object is showing on the screen, use isShowing().
1772              * <p>Objects that are visible will also have the
1773              * AccessibleState.VISIBLE state set in their AccessibleStateSet.
1774              *
1775              * @return true if object is visible; otherwise, false
1776              * @see #setVisible
1777              * @see AccessibleContext#getAccessibleStateSet
1778              * @see AccessibleState#VISIBLE
1779              * @see AccessibleStateSet
1780              */
1781             public boolean isVisible() {
1782                 // [[[FIXME]]] needs to work like isShowing() below
1783                 return false;
1784                 // return parent.isVisible();
1785             }
1786 
1787             /**
1788              * Set the visible state of the object.
1789              *
1790              * @param b if true, shows this object; otherwise, hides it
1791              * @see #isVisible
1792              */
1793             public void setVisible(boolean b) {
1794                 // [[[FIXME]]] should scroll to item to make it show!
1795                 parent.setVisible(b);
1796             }
1797 
1798             /**
1799              * Determine if the object is showing.  This is determined by
1800              * checking the visibility of the object and visibility of the
1801              * object ancestors.
1802              * Note: this will return true even if the object is obscured
1803              * by another (for example, it to object is underneath a menu
1804              * that was pulled down).
1805              *
1806              * @return true if object is showing; otherwise, false
1807              */
1808             public boolean isShowing() {
1809                 // [[[FIXME]]] only if it's showing!!!
1810                 return false;
1811                 // return parent.isShowing();
1812             }
1813 
1814             /**
1815              * Checks whether the specified point is within this object's
1816              * bounds, where the point's x and y coordinates are defined to
1817              * be relative to the coordinate system of the object.
1818              *
1819              * @param p the Point relative to the coordinate system of the
1820              * object
1821              * @return true if object contains Point; otherwise false
1822              * @see #getBounds
1823              */
1824             public boolean contains(Point p) {
1825                 // [[[FIXME]]] - only if p is within the list element!!!
1826                 return false;
1827                 // return parent.contains(p);
1828             }
1829 
1830             /**
1831              * Returns the location of the object on the screen.
1832              *
1833              * @return location of object on screen; null if this object
1834              * is not on the screen
1835              * @see #getBounds
1836              * @see #getLocation
1837              */
1838             public Point getLocationOnScreen() {
1839                 // [[[FIXME]]] sigh
1840                 return null;
1841             }
1842 
1843             /**
1844              * Gets the location of the object relative to the parent in the
1845              * form of a point specifying the object's top-left corner in the
1846              * screen's coordinate space.
1847              *
1848              * @return An instance of Point representing the top-left corner of
1849              * the objects's bounds in the coordinate space of the screen; null
1850              * if this object or its parent are not on the screen
1851              * @see #getBounds
1852              * @see #getLocationOnScreen
1853              */
1854             public Point getLocation() {
1855                 // [[[FIXME]]]
1856                 return null;
1857             }
1858 
1859             /**
1860              * Sets the location of the object relative to the parent.
1861              * @param p the new position for the top-left corner
1862              * @see #getLocation
1863              */
1864             public void setLocation(Point p) {
1865                 // [[[FIXME]]] maybe - can simply return as no-op
1866             }
1867 
1868             /**
1869              * Gets the bounds of this object in the form of a Rectangle object.
1870              * The bounds specify this object's width, height, and location
1871              * relative to its parent.
1872              *
1873              * @return A rectangle indicating this component's bounds; null if
1874              * this object is not on the screen.
1875              * @see #contains
1876              */
1877             public Rectangle getBounds() {
1878                 // [[[FIXME]]]
1879                 return null;
1880             }
1881 
1882             /**
1883              * Sets the bounds of this object in the form of a Rectangle
1884              * object.  The bounds specify this object's width, height, and
1885              * location relative to its parent.
1886              *
1887              * @param r rectangle indicating this component's bounds
1888              * @see #getBounds
1889              */
1890             public void setBounds(Rectangle r) {
1891                 // no-op; not supported
1892             }
1893 
1894             /**
1895              * Returns the size of this object in the form of a Dimension
1896              * object.  The height field of the Dimension object contains this
1897              * objects's height, and the width field of the Dimension object
1898              * contains this object's width.
1899              *
1900              * @return A Dimension object that indicates the size of this
1901              * component; null if this object is not on the screen
1902              * @see #setSize
1903              */
1904             public Dimension getSize() {
1905                 // [[[FIXME]]]
1906                 return null;
1907             }
1908 
1909             /**
1910              * Resizes this object so that it has width and height.
1911              *
1912              * @param d - The dimension specifying the new size of the object.
1913              * @see #getSize
1914              */
1915             public void setSize(Dimension d) {
1916                 // not supported; no-op
1917             }
1918 
1919             /**
1920              * Returns the <code>Accessible</code> child, if one exists,
1921              * contained at the local coordinate <code>Point</code>.
1922              *
1923              * @param p the point relative to the coordinate system of this
1924              *     object
1925              * @return the <code>Accessible</code>, if it exists,
1926              *     at the specified location; otherwise <code>null</code>
1927              */
1928             public Accessible getAccessibleAt(Point p) {
1929                 return null;    // object cannot have children!
1930             }
1931 
1932             /**
1933              * Returns whether this object can accept focus or not.   Objects
1934              * that can accept focus will also have the
1935              * <code>AccessibleState.FOCUSABLE</code> state set in their
1936              * <code>AccessibleStateSet</code>.
1937              *
1938              * @return true if object can accept focus; otherwise false
1939              * @see AccessibleContext#getAccessibleStateSet
1940              * @see AccessibleState#FOCUSABLE
1941              * @see AccessibleState#FOCUSED
1942              * @see AccessibleStateSet
1943              */
1944             public boolean isFocusTraversable() {
1945                 return false;   // list element cannot receive focus!
1946             }
1947 
1948             /**
1949              * Requests focus for this object.  If this object cannot accept
1950              * focus, nothing will happen.  Otherwise, the object will attempt
1951              * to take focus.
1952              * @see #isFocusTraversable
1953              */
1954             public void requestFocus() {
1955                 // nothing to do; a no-op
1956             }
1957 
1958             /**
1959              * Adds the specified focus listener to receive focus events from
1960              * this component.
1961              *
1962              * @param l the focus listener
1963              * @see #removeFocusListener
1964              */
1965             public void addFocusListener(FocusListener l) {
1966                 // nothing to do; a no-op
1967             }
1968 
1969             /**
1970              * Removes the specified focus listener so it no longer receives
1971              * focus events from this component.
1972              *
1973              * @param l the focus listener
1974              * @see #addFocusListener
1975              */
1976             public void removeFocusListener(FocusListener l) {
1977                 // nothing to do; a no-op
1978             }
1979 
1980 
1981 
1982         } // inner class AccessibleAWTListChild
1983 
1984     } // inner class AccessibleAWTList
1985 
1986 }