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