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