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