< prev index next >

src/java.desktop/share/classes/javax/swing/JList.java

Print this page




  85  * for(int i = 0; i < model.getSize(); i++) {
  86  *     System.out.println(model.getElementAt(i));
  87  * }
  88  * }
  89  * </pre>
  90  * <p>
  91  * A {@code ListModel} can be supplied directly to a {@code JList} by way of a
  92  * constructor or the {@code setModel} method. The contents need not be static -
  93  * the number of items, and the values of items can change over time. A correct
  94  * {@code ListModel} implementation notifies the set of
  95  * {@code javax.swing.event.ListDataListener}s that have been added to it, each
  96  * time a change occurs. These changes are characterized by a
  97  * {@code javax.swing.event.ListDataEvent}, which identifies the range of list
  98  * indices that have been modified, added, or removed. {@code JList}'s
  99  * {@code ListUI} is responsible for keeping the visual representation up to
 100  * date with changes, by listening to the model.
 101  * <p>
 102  * Simple, dynamic-content, {@code JList} applications can use the
 103  * {@code DefaultListModel} class to maintain list elements. This class
 104  * implements the {@code ListModel} interface and also provides a
 105  * <code>java.util.Vector</code>-like API. Applications that need a more
 106  * custom <code>ListModel</code> implementation may instead wish to subclass
 107  * {@code AbstractListModel}, which provides basic support for managing and
 108  * notifying listeners. For example, a read-only implementation of
 109  * {@code AbstractListModel}:
 110  * <pre>
 111  * {@code
 112  * // This list model has about 2^16 elements.  Enjoy scrolling.
 113  *
 114  * ListModel<String> bigData = new AbstractListModel<String>() {
 115  *     public int getSize() { return Short.MAX_VALUE; }
 116  *     public String getElementAt(int index) { return "Index " + index; }
 117  * };
 118  * }
 119  * </pre>
 120  * <p>
 121  * The selection state of a {@code JList} is managed by another separate
 122  * model, an instance of {@code ListSelectionModel}. {@code JList} is
 123  * initialized with a selection model on construction, and also contains
 124  * methods to query or set this selection model. Additionally, {@code JList}
 125  * provides convenient methods for easily managing the selection. These methods,
 126  * such as {@code setSelectedIndex} and {@code getSelectedValue}, are cover


 237  *         if (e.getClickCount() == 2) {
 238  *             int index = list.locationToIndex(e.getPoint());
 239  *             System.out.println("Double clicked on Item " + index);
 240  *          }
 241  *     }
 242  * };
 243  * list.addMouseListener(mouseListener);
 244  * </pre>
 245  * <p>
 246  * <strong>Warning:</strong> Swing is not thread safe. For more
 247  * information see <a
 248  * href="package-summary.html#threading">Swing's Threading
 249  * Policy</a>.
 250  * <p>
 251  * <strong>Warning:</strong>
 252  * Serialized objects of this class will not be compatible with
 253  * future Swing releases. The current serialization support is
 254  * appropriate for short term storage or RMI between applications running
 255  * the same version of Swing.  As of 1.4, support for long term storage
 256  * of all JavaBeans&trade;
 257  * has been added to the <code>java.beans</code> package.
 258  * Please see {@link java.beans.XMLEncoder}.
 259  * <p>
 260  * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/list.html">How to Use Lists</a>
 261  * in <a href="http://docs.oracle.com/javase/tutorial/"><em>The Java Tutorial</em></a>
 262  * for further documentation.
 263  *
 264  * @see ListModel
 265  * @see AbstractListModel
 266  * @see DefaultListModel
 267  * @see ListSelectionModel
 268  * @see DefaultListSelectionModel
 269  * @see ListCellRenderer
 270  * @see DefaultListCellRenderer
 271  *
 272  * @param <E> the type of the elements of this list
 273  *
 274  * @beaninfo
 275  *   attribute: isContainer false
 276  * description: A component which allows for the selection of one or more objects from a list.
 277  *


 309      * @see #setLayoutOrientation
 310      * @since 1.4
 311      */
 312     public static final int HORIZONTAL_WRAP = 2;
 313 
 314     private int fixedCellWidth = -1;
 315     private int fixedCellHeight = -1;
 316     private int horizontalScrollIncrement = -1;
 317     private E prototypeCellValue;
 318     private int visibleRowCount = 8;
 319     private Color selectionForeground;
 320     private Color selectionBackground;
 321     private boolean dragEnabled;
 322 
 323     private ListSelectionModel selectionModel;
 324     private ListModel<E> dataModel;
 325     private ListCellRenderer<? super E> cellRenderer;
 326     private ListSelectionListener selectionListener;
 327 
 328     /**
 329      * How to lay out the cells; defaults to <code>VERTICAL</code>.
 330      */
 331     private int layoutOrientation;
 332 
 333     /**
 334      * The drop mode for this component.
 335      */
 336     private DropMode dropMode = DropMode.USE_SELECTION;
 337 
 338     /**
 339      * The drop location.
 340      */
 341     private transient DropLocation dropLocation;
 342 
 343     /**
 344      * A subclass of <code>TransferHandler.DropLocation</code> representing
 345      * a drop location for a <code>JList</code>.
 346      *
 347      * @see #getDropLocation
 348      * @since 1.6
 349      */
 350     public static final class DropLocation extends TransferHandler.DropLocation {
 351         private final int index;
 352         private final boolean isInsert;
 353 
 354         private DropLocation(Point p, int index, boolean isInsert) {
 355             super(p);
 356             this.index = index;
 357             this.isInsert = isInsert;
 358         }
 359 
 360         /**
 361          * Returns the index where dropped data should be placed in the
 362          * list. Interpretation of the value depends on the drop mode set on
 363          * the associated component. If the drop mode is either
 364          * <code>DropMode.USE_SELECTION</code> or <code>DropMode.ON</code>,
 365          * the return value is an index of a row in the list. If the drop mode is
 366          * <code>DropMode.INSERT</code>, the return value refers to the index
 367          * where the data should be inserted. If the drop mode is
 368          * <code>DropMode.ON_OR_INSERT</code>, the value of
 369          * <code>isInsert()</code> indicates whether the index is an index
 370          * of a row, or an insert index.
 371          * <p>
 372          * <code>-1</code> indicates that the drop occurred over empty space,
 373          * and no index could be calculated.
 374          *
 375          * @return the drop index
 376          */
 377         public int getIndex() {
 378             return index;
 379         }
 380 
 381         /**
 382          * Returns whether or not this location represents an insert
 383          * location.
 384          *
 385          * @return whether or not this is an insert location
 386          */
 387         public boolean isInsert() {
 388             return isInsert;
 389         }
 390 
 391         /**
 392          * Returns a string representation of this drop location.


 420         if (dataModel == null) {
 421             throw new IllegalArgumentException("dataModel must be non null");
 422         }
 423 
 424         // Register with the ToolTipManager so that tooltips from the
 425         // renderer show through.
 426         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
 427         toolTipManager.registerComponent(this);
 428 
 429         layoutOrientation = VERTICAL;
 430 
 431         this.dataModel = dataModel;
 432         selectionModel = createSelectionModel();
 433         setAutoscrolls(true);
 434         setOpaque(true);
 435         updateUI();
 436     }
 437 
 438 
 439     /**
 440      * Constructs a <code>JList</code> that displays the elements in
 441      * the specified array. This constructor creates a read-only model
 442      * for the given array, and then delegates to the constructor that
 443      * takes a {@code ListModel}.
 444      * <p>
 445      * Attempts to pass a {@code null} value to this method results in
 446      * undefined behavior and, most likely, exceptions. The created model
 447      * references the given array directly. Attempts to modify the array
 448      * after constructing the list results in undefined behavior.
 449      *
 450      * @param  listData  the array of Objects to be loaded into the data model,
 451      *                   {@code non-null}
 452      */
 453     public JList(final E[] listData)
 454     {
 455         this (
 456             new AbstractListModel<E>() {
 457                 public int getSize() { return listData.length; }
 458                 public E getElementAt(int i) { return listData[i]; }
 459             }
 460         );
 461     }
 462 
 463 
 464     /**
 465      * Constructs a <code>JList</code> that displays the elements in
 466      * the specified <code>Vector</code>. This constructor creates a read-only
 467      * model for the given {@code Vector}, and then delegates to the constructor
 468      * that takes a {@code ListModel}.
 469      * <p>
 470      * Attempts to pass a {@code null} value to this method results in
 471      * undefined behavior and, most likely, exceptions. The created model
 472      * references the given {@code Vector} directly. Attempts to modify the
 473      * {@code Vector} after constructing the list results in undefined behavior.
 474      *
 475      * @param  listData  the <code>Vector</code> to be loaded into the
 476      *                   data model, {@code non-null}
 477      */
 478     public JList(final Vector<? extends E> listData) {
 479         this (
 480             new AbstractListModel<E>() {
 481                 public int getSize() { return listData.size(); }
 482                 public E getElementAt(int i) { return listData.elementAt(i); }
 483             }
 484         );
 485     }
 486 
 487 
 488     /**
 489      * Constructs a <code>JList</code> with an empty, read-only, model.
 490      */
 491     public JList() {
 492         this (
 493             new AbstractListModel<E>() {
 494               public int getSize() { return 0; }
 495               public E getElementAt(int i) { throw new IndexOutOfBoundsException("No Data Model"); }
 496             }
 497         );
 498     }
 499 
 500 
 501     /**
 502      * Returns the {@code ListUI}, the look and feel object that
 503      * renders this component.
 504      *
 505      * @return the <code>ListUI</code> object that renders this component
 506      */
 507     public ListUI getUI() {
 508         return (ListUI)ui;
 509     }
 510 
 511 
 512     /**
 513      * Sets the {@code ListUI}, the look and feel object that
 514      * renders this component.
 515      *
 516      * @param ui  the <code>ListUI</code> object
 517      * @see UIDefaults#getUI
 518      * @beaninfo
 519      *        bound: true
 520      *       hidden: true
 521      *    attribute: visualUpdate true
 522      *  description: The UI object that implements the Component's LookAndFeel.
 523      */
 524     public void setUI(ListUI ui) {
 525         super.setUI(ui);
 526     }
 527 
 528 
 529     /**
 530      * Resets the {@code ListUI} property by setting it to the value provided
 531      * by the current look and feel. If the current cell renderer was installed
 532      * by the developer (rather than the look and feel itself), this also causes
 533      * the cell renderer and its children to be updated, by calling
 534      * {@code SwingUtilities.updateComponentTreeUI} on it.
 535      *
 536      * @see UIManager#getUI
 537      * @see SwingUtilities#updateComponentTreeUI
 538      */
 539     public void updateUI() {
 540         setUI((ListUI)UIManager.getUI(this));
 541 
 542         ListCellRenderer<? super E> renderer = getCellRenderer();
 543         if (renderer instanceof Component) {
 544             SwingUtilities.updateComponentTreeUI((Component)renderer);
 545         }
 546     }
 547 
 548 
 549     /**
 550      * Returns {@code "ListUI"}, the <code>UIDefaults</code> key used to look
 551      * up the name of the {@code javax.swing.plaf.ListUI} class that defines
 552      * the look and feel for this component.
 553      *
 554      * @return the string "ListUI"
 555      * @see JComponent#getUIClassID
 556      * @see UIDefaults#getUI
 557      */
 558     public String getUIClassID() {
 559         return uiClassID;
 560     }
 561 
 562 
 563     /* -----private-----
 564      * This method is called by setPrototypeCellValue and setCellRenderer
 565      * to update the fixedCellWidth and fixedCellHeight properties from the
 566      * current value of prototypeCellValue (if it's non null).
 567      * <p>
 568      * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
 569      * generate PropertyChangeEvents for them.
 570      *


 612     /**
 613      * Sets the {@code prototypeCellValue} property, and then (if the new value
 614      * is {@code non-null}), computes the {@code fixedCellWidth} and
 615      * {@code fixedCellHeight} properties by requesting the cell renderer
 616      * component for the given value (and index 0) from the cell renderer, and
 617      * using that component's preferred size.
 618      * <p>
 619      * This method is useful when the list is too long to allow the
 620      * {@code ListUI} to compute the width/height of each cell, and there is a
 621      * single cell value that is known to occupy as much space as any of the
 622      * others, a so-called prototype.
 623      * <p>
 624      * While all three of the {@code prototypeCellValue},
 625      * {@code fixedCellHeight}, and {@code fixedCellWidth} properties may be
 626      * modified by this method, {@code PropertyChangeEvent} notifications are
 627      * only sent when the {@code prototypeCellValue} property changes.
 628      * <p>
 629      * To see an example which sets this property, see the
 630      * <a href="#prototype_example">class description</a> above.
 631      * <p>
 632      * The default value of this property is <code>null</code>.
 633      * <p>
 634      * This is a JavaBeans bound property.
 635      *
 636      * @param prototypeCellValue  the value on which to base
 637      *                          <code>fixedCellWidth</code> and
 638      *                          <code>fixedCellHeight</code>
 639      * @see #getPrototypeCellValue
 640      * @see #setFixedCellWidth
 641      * @see #setFixedCellHeight
 642      * @see JComponent#addPropertyChangeListener
 643      * @beaninfo
 644      *       bound: true
 645      *   attribute: visualUpdate true
 646      * description: The cell prototype value, used to compute cell width and height.
 647      */
 648     public void setPrototypeCellValue(E prototypeCellValue) {
 649         E oldValue = this.prototypeCellValue;
 650         this.prototypeCellValue = prototypeCellValue;
 651 
 652         /* If the prototypeCellValue has changed and is non-null,
 653          * then recompute fixedCellWidth and fixedCellHeight.
 654          */
 655 
 656         if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
 657             updateFixedCellSize();
 658         }
 659 
 660         firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
 661     }
 662 
 663 
 664     /**
 665      * Returns the value of the {@code fixedCellWidth} property.
 666      *
 667      * @return the fixed cell width
 668      * @see #setFixedCellWidth
 669      */
 670     public int getFixedCellWidth() {
 671         return fixedCellWidth;
 672     }
 673 
 674     /**
 675      * Sets a fixed value to be used for the width of every cell in the list.
 676      * If {@code width} is -1, cell widths are computed in the {@code ListUI}
 677      * by applying <code>getPreferredSize</code> to the cell renderer component
 678      * for each list element.
 679      * <p>
 680      * The default value of this property is {@code -1}.
 681      * <p>
 682      * This is a JavaBeans bound property.
 683      *
 684      * @param width the width to be used for all cells in the list
 685      * @see #setPrototypeCellValue
 686      * @see #setFixedCellWidth
 687      * @see JComponent#addPropertyChangeListener
 688      * @beaninfo
 689      *       bound: true
 690      *   attribute: visualUpdate true
 691      * description: Defines a fixed cell width when greater than zero.
 692      */
 693     public void setFixedCellWidth(int width) {
 694         int oldValue = fixedCellWidth;
 695         fixedCellWidth = width;
 696         firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
 697     }
 698 
 699 
 700     /**
 701      * Returns the value of the {@code fixedCellHeight} property.
 702      *
 703      * @return the fixed cell height
 704      * @see #setFixedCellHeight
 705      */
 706     public int getFixedCellHeight() {
 707         return fixedCellHeight;
 708     }
 709 
 710     /**
 711      * Sets a fixed value to be used for the height of every cell in the list.
 712      * If {@code height} is -1, cell heights are computed in the {@code ListUI}
 713      * by applying <code>getPreferredSize</code> to the cell renderer component
 714      * for each list element.
 715      * <p>
 716      * The default value of this property is {@code -1}.
 717      * <p>
 718      * This is a JavaBeans bound property.
 719      *
 720      * @param height the height to be used for all cells in the list
 721      * @see #setPrototypeCellValue
 722      * @see #setFixedCellWidth
 723      * @see JComponent#addPropertyChangeListener
 724      * @beaninfo
 725      *       bound: true
 726      *   attribute: visualUpdate true
 727      * description: Defines a fixed cell height when greater than zero.
 728      */
 729     public void setFixedCellHeight(int height) {
 730         int oldValue = fixedCellHeight;
 731         fixedCellHeight = height;
 732         firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
 733     }


 735 
 736     /**
 737      * Returns the object responsible for painting list items.
 738      *
 739      * @return the value of the {@code cellRenderer} property
 740      * @see #setCellRenderer
 741      */
 742     @Transient
 743     public ListCellRenderer<? super E> getCellRenderer() {
 744         return cellRenderer;
 745     }
 746 
 747     /**
 748      * Sets the delegate that is used to paint each cell in the list.
 749      * The job of a cell renderer is discussed in detail in the
 750      * <a href="#renderer">class level documentation</a>.
 751      * <p>
 752      * If the {@code prototypeCellValue} property is {@code non-null},
 753      * setting the cell renderer also causes the {@code fixedCellWidth} and
 754      * {@code fixedCellHeight} properties to be re-calculated. Only one
 755      * <code>PropertyChangeEvent</code> is generated however -
 756      * for the <code>cellRenderer</code> property.
 757      * <p>
 758      * The default value of this property is provided by the {@code ListUI}
 759      * delegate, i.e. by the look and feel implementation.
 760      * <p>
 761      * This is a JavaBeans bound property.
 762      *
 763      * @param cellRenderer the <code>ListCellRenderer</code>
 764      *                          that paints list cells
 765      * @see #getCellRenderer
 766      * @beaninfo
 767      *       bound: true
 768      *   attribute: visualUpdate true
 769      * description: The component used to draw the cells.
 770      */
 771     public void setCellRenderer(ListCellRenderer<? super E> cellRenderer) {
 772         ListCellRenderer<? super E> oldValue = this.cellRenderer;
 773         this.cellRenderer = cellRenderer;
 774 
 775         /* If the cellRenderer has changed and prototypeCellValue
 776          * was set, then recompute fixedCellWidth and fixedCellHeight.
 777          */
 778         if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
 779             updateFixedCellSize();
 780         }
 781 
 782         firePropertyChange("cellRenderer", oldValue, cellRenderer);
 783     }


 956      * <pre>
 957      * VERTICAL:          0
 958      *                    1
 959      *                    2
 960      *                    3
 961      *                    4
 962      *
 963      * HORIZONTAL_WRAP:   0  1  2
 964      *                    3  4
 965      *
 966      * VERTICAL_WRAP:     0  3
 967      *                    1  4
 968      *                    2
 969      * </pre>
 970      * <p>
 971      * A description of these layouts follows:
 972      *
 973      * <table border="1"
 974      *  summary="Describes layouts VERTICAL, HORIZONTAL_WRAP, and VERTICAL_WRAP">
 975      *   <tr><th><p style="text-align:left">Value</p></th><th><p style="text-align:left">Description</p></th></tr>
 976      *   <tr><td><code>VERTICAL</code>
 977      *       <td>Cells are layed out vertically in a single column.
 978      *   <tr><td><code>HORIZONTAL_WRAP</code>
 979      *       <td>Cells are layed out horizontally, wrapping to a new row as
 980      *           necessary. If the {@code visibleRowCount} property is less than
 981      *           or equal to zero, wrapping is determined by the width of the
 982      *           list; otherwise wrapping is done in such a way as to ensure
 983      *           {@code visibleRowCount} rows in the list.
 984      *   <tr><td><code>VERTICAL_WRAP</code>
 985      *       <td>Cells are layed out vertically, wrapping to a new column as
 986      *           necessary. If the {@code visibleRowCount} property is less than
 987      *           or equal to zero, wrapping is determined by the height of the
 988      *           list; otherwise wrapping is done at {@code visibleRowCount} rows.
 989      *  </table>
 990      * <p>
 991      * The default value of this property is <code>VERTICAL</code>.
 992      *
 993      * @param layoutOrientation the new layout orientation, one of:
 994      *        {@code VERTICAL}, {@code HORIZONTAL_WRAP} or {@code VERTICAL_WRAP}
 995      * @see #getLayoutOrientation
 996      * @see #setVisibleRowCount
 997      * @see #getScrollableTracksViewportHeight
 998      * @see #getScrollableTracksViewportWidth
 999      * @throws IllegalArgumentException if {@code layoutOrientation} isn't one of the
1000      *         allowable values
1001      * @since 1.4
1002      * @beaninfo
1003      *       bound: true
1004      *   attribute: visualUpdate true
1005      * description: Defines the way list cells are layed out.
1006      *        enum: VERTICAL JList.VERTICAL
1007      *              HORIZONTAL_WRAP JList.HORIZONTAL_WRAP
1008      *              VERTICAL_WRAP JList.VERTICAL_WRAP
1009      */
1010     public void setLayoutOrientation(int layoutOrientation) {
1011         int oldValue = this.layoutOrientation;


1119                                     }
1120                                 }
1121 
1122                             }
1123                             else {
1124                                 last = visIndex;
1125                             }
1126                         }
1127                     } while (visIndex != -1 && last != visIndex);
1128                 }
1129             }
1130         }
1131         return location;
1132     }
1133 
1134 
1135     /**
1136      * Scrolls the list within an enclosing viewport to make the specified
1137      * cell completely visible. This calls {@code scrollRectToVisible} with
1138      * the bounds of the specified cell. For this method to work, the
1139      * {@code JList} must be within a <code>JViewport</code>.
1140      * <p>
1141      * If the given index is outside the list's range of cells, this method
1142      * results in nothing.
1143      *
1144      * @param index  the index of the cell to make visible
1145      * @see JComponent#scrollRectToVisible
1146      * @see #getVisibleRect
1147      */
1148     public void ensureIndexIsVisible(int index) {
1149         Rectangle cellBounds = getCellBounds(index, index);
1150         if (cellBounds != null) {
1151             scrollRectToVisible(cellBounds);
1152         }
1153     }
1154 
1155     /**
1156      * Turns on or off automatic drag handling. In order to enable automatic
1157      * drag handling, this property should be set to {@code true}, and the
1158      * list's {@code TransferHandler} needs to be {@code non-null}.
1159      * The default value of the {@code dragEnabled} property is {@code false}.
1160      * <p>
1161      * The job of honoring this property, and recognizing a user drag gesture,
1162      * lies with the look and feel implementation, and in particular, the list's
1163      * {@code ListUI}. When automatic drag handling is enabled, most look and
1164      * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1165      * drag and drop operation whenever the user presses the mouse button over
1166      * an item and then moves the mouse a few pixels. Setting this property to
1167      * {@code true} can therefore have a subtle effect on how selections behave.
1168      * <p>
1169      * If a look and feel is used that ignores this property, you can still
1170      * begin a drag and drop operation by calling {@code exportAsDrag} on the
1171      * list's {@code TransferHandler}.
1172      *
1173      * @param b whether or not to enable automatic drag handling
1174      * @exception HeadlessException if
1175      *            <code>b</code> is <code>true</code> and
1176      *            <code>GraphicsEnvironment.isHeadless()</code>
1177      *            returns <code>true</code>
1178      * @see java.awt.GraphicsEnvironment#isHeadless
1179      * @see #getDragEnabled
1180      * @see #setTransferHandler
1181      * @see TransferHandler
1182      * @since 1.4
1183      *
1184      * @beaninfo
1185      *  description: determines whether automatic drag handling is enabled
1186      *        bound: false
1187      */
1188     public void setDragEnabled(boolean b) {
1189         if (b && GraphicsEnvironment.isHeadless()) {
1190             throw new HeadlessException();
1191         }
1192         dragEnabled = b;
1193     }
1194 
1195     /**
1196      * Returns whether or not automatic drag handling is enabled.
1197      *
1198      * @return the value of the {@code dragEnabled} property
1199      * @see #setDragEnabled
1200      * @since 1.4
1201      */
1202     public boolean getDragEnabled() {
1203         return dragEnabled;
1204     }
1205 
1206     /**
1207      * Sets the drop mode for this component. For backward compatibility,
1208      * the default for this property is <code>DropMode.USE_SELECTION</code>.
1209      * Usage of one of the other modes is recommended, however, for an
1210      * improved user experience. <code>DropMode.ON</code>, for instance,
1211      * offers similar behavior of showing items as selected, but does so without
1212      * affecting the actual selection in the list.
1213      * <p>
1214      * <code>JList</code> supports the following drop modes:
1215      * <ul>
1216      *    <li><code>DropMode.USE_SELECTION</code></li>
1217      *    <li><code>DropMode.ON</code></li>
1218      *    <li><code>DropMode.INSERT</code></li>
1219      *    <li><code>DropMode.ON_OR_INSERT</code></li>
1220      * </ul>
1221      * The drop mode is only meaningful if this component has a
1222      * <code>TransferHandler</code> that accepts drops.
1223      *
1224      * @param dropMode the drop mode to use
1225      * @throws IllegalArgumentException if the drop mode is unsupported
1226      *         or <code>null</code>
1227      * @see #getDropMode
1228      * @see #getDropLocation
1229      * @see #setTransferHandler
1230      * @see TransferHandler
1231      * @since 1.6
1232      */
1233     public final void setDropMode(DropMode dropMode) {
1234         if (dropMode != null) {
1235             switch (dropMode) {
1236                 case USE_SELECTION:
1237                 case ON:
1238                 case INSERT:
1239                 case ON_OR_INSERT:
1240                     this.dropMode = dropMode;
1241                     return;
1242             }
1243         }
1244 
1245         throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for list");
1246     }
1247 
1248     /**
1249      * Returns the drop mode for this component.
1250      *
1251      * @return the drop mode for this component
1252      * @see #setDropMode
1253      * @since 1.6
1254      */
1255     public final DropMode getDropMode() {
1256         return dropMode;
1257     }
1258 
1259     /**
1260      * Calculates a drop location in this component, representing where a
1261      * drop at the given point should insert data.
1262      *
1263      * @param p the point to calculate a drop location for
1264      * @return the drop location, or <code>null</code>
1265      */
1266     DropLocation dropLocationForPoint(Point p) {
1267         DropLocation location = null;
1268         Rectangle rect = null;
1269 
1270         int index = locationToIndex(p);
1271         if (index != -1) {
1272             rect = getCellBounds(index, index);
1273         }
1274 
1275         switch(dropMode) {
1276             case USE_SELECTION:
1277             case ON:
1278                 location = new DropLocation(p,
1279                     (rect != null && rect.contains(p)) ? index : -1,
1280                     false);
1281 
1282                 break;
1283             case INSERT:
1284                 if (index == -1) {


1347     }
1348 
1349     /**
1350      * Called to set or clear the drop location during a DnD operation.
1351      * In some cases, the component may need to use it's internal selection
1352      * temporarily to indicate the drop location. To help facilitate this,
1353      * this method returns and accepts as a parameter a state object.
1354      * This state object can be used to store, and later restore, the selection
1355      * state. Whatever this method returns will be passed back to it in
1356      * future calls, as the state parameter. If it wants the DnD system to
1357      * continue storing the same state, it must pass it back every time.
1358      * Here's how this is used:
1359      * <p>
1360      * Let's say that on the first call to this method the component decides
1361      * to save some state (because it is about to use the selection to show
1362      * a drop index). It can return a state object to the caller encapsulating
1363      * any saved selection state. On a second call, let's say the drop location
1364      * is being changed to something else. The component doesn't need to
1365      * restore anything yet, so it simply passes back the same state object
1366      * to have the DnD system continue storing it. Finally, let's say this
1367      * method is messaged with <code>null</code>. This means DnD
1368      * is finished with this component for now, meaning it should restore
1369      * state. At this point, it can use the state parameter to restore
1370      * said state, and of course return <code>null</code> since there's
1371      * no longer anything to store.
1372      *
1373      * @param location the drop location (as calculated by
1374      *        <code>dropLocationForPoint</code>) or <code>null</code>
1375      *        if there's no longer a valid drop location
1376      * @param state the state object saved earlier for this component,
1377      *        or <code>null</code>
1378      * @param forDrop whether or not the method is being called because an
1379      *        actual drop occurred
1380      * @return any saved state for this component, or <code>null</code> if none
1381      */
1382     Object setDropLocation(TransferHandler.DropLocation location,
1383                            Object state,
1384                            boolean forDrop) {
1385 
1386         Object retVal = null;
1387         DropLocation listLocation = (DropLocation)location;
1388 
1389         if (dropMode == DropMode.USE_SELECTION) {
1390             if (listLocation == null) {
1391                 if (!forDrop && state != null) {
1392                     setSelectedIndices(((int[][])state)[0]);
1393 
1394                     int anchor = ((int[][])state)[1][0];
1395                     int lead = ((int[][])state)[1][1];
1396 
1397                     SwingUtilities2.setLeadAnchorWithoutSelection(
1398                             getSelectionModel(), lead, anchor);
1399                 }
1400             } else {


1414                 } else {
1415                     setSelectionInterval(index, index);
1416                 }
1417             }
1418         }
1419 
1420         DropLocation old = dropLocation;
1421         dropLocation = listLocation;
1422         firePropertyChange("dropLocation", old, dropLocation);
1423 
1424         return retVal;
1425     }
1426 
1427     /**
1428      * Returns the location that this component should visually indicate
1429      * as the drop location during a DnD operation over the component,
1430      * or {@code null} if no location is to currently be shown.
1431      * <p>
1432      * This method is not meant for querying the drop location
1433      * from a {@code TransferHandler}, as the drop location is only
1434      * set after the {@code TransferHandler}'s <code>canImport</code>
1435      * has returned and has allowed for the location to be shown.
1436      * <p>
1437      * When this property changes, a property change event with
1438      * name "dropLocation" is fired by the component.
1439      * <p>
1440      * By default, responsibility for listening for changes to this property
1441      * and indicating the drop location visually lies with the list's
1442      * {@code ListUI}, which may paint it directly and/or install a cell
1443      * renderer to do so. Developers wishing to implement custom drop location
1444      * painting and/or replace the default cell renderer, may need to honor
1445      * this property.
1446      *
1447      * @return the drop location
1448      * @see #setDropMode
1449      * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1450      * @since 1.6
1451      */
1452     public final DropLocation getDropLocation() {
1453         return dropLocation;
1454     }


1497                     }
1498                 }
1499 
1500                 if (string != null && string.startsWith(prefix)) {
1501                     return index;
1502                 }
1503             }
1504             index = (index + increment + max) % max;
1505         } while (index != startIndex);
1506         return -1;
1507     }
1508 
1509     /**
1510      * Returns the tooltip text to be used for the given event. This overrides
1511      * {@code JComponent}'s {@code getToolTipText} to first check the cell
1512      * renderer component for the cell over which the event occurred, returning
1513      * its tooltip text, if any. This implementation allows you to specify
1514      * tooltip text on the cell level, by using {@code setToolTipText} on your
1515      * cell renderer component.
1516      * <p>
1517      * <strong>Note:</strong> For <code>JList</code> to properly display the
1518      * tooltips of its renderers in this manner, <code>JList</code> must be a
1519      * registered component with the <code>ToolTipManager</code>. This registration
1520      * is done automatically in the constructor. However, if at a later point
1521      * <code>JList</code> is unregistered, by way of a call to
1522      * {@code setToolTipText(null)}, tips from the renderers will no longer display.
1523      *
1524      * @param event the {@code MouseEvent} to fetch the tooltip text for
1525      * @see JComponent#setToolTipText
1526      * @see JComponent#getToolTipText
1527      */
1528     public String getToolTipText(MouseEvent event) {
1529         if(event != null) {
1530             Point p = event.getPoint();
1531             int index = locationToIndex(p);
1532             ListCellRenderer<? super E> r = getCellRenderer();
1533             Rectangle cellBounds;
1534 
1535             if (index != -1 && r != null && (cellBounds =
1536                                getCellBounds(index, index)) != null &&
1537                                cellBounds.contains(p.x, p.y)) {
1538                 ListSelectionModel lsm = getSelectionModel();
1539                 Component rComponent = r.getListCellRendererComponent(
1540                            this, getModel().getElementAt(index), index,
1541                            lsm.isSelectedIndex(index),


1624      * in the list's {@code ListUI}. It returns {@code null} if the list has
1625      * no {@code ListUI}.
1626      *
1627      * @param index0 the first index in the range
1628      * @param index1 the second index in the range
1629      * @return the bounding rectangle for the range of cells, or {@code null}
1630      */
1631     public Rectangle getCellBounds(int index0, int index1) {
1632         ListUI ui = getUI();
1633         return (ui != null) ? ui.getCellBounds(this, index0, index1) : null;
1634     }
1635 
1636 
1637     /**
1638      * --- ListModel Support ---
1639      */
1640 
1641 
1642     /**
1643      * Returns the data model that holds the list of items displayed
1644      * by the <code>JList</code> component.
1645      *
1646      * @return the <code>ListModel</code> that provides the displayed
1647      *                          list of items
1648      * @see #setModel
1649      */
1650     public ListModel<E> getModel() {
1651         return dataModel;
1652     }
1653 
1654     /**
1655      * Sets the model that represents the contents or "value" of the
1656      * list, notifies property change listeners, and then clears the
1657      * list's selection.
1658      * <p>
1659      * This is a JavaBeans bound property.
1660      *
1661      * @param model  the <code>ListModel</code> that provides the
1662      *                                          list of items for display
1663      * @exception IllegalArgumentException  if <code>model</code> is
1664      *                                          <code>null</code>
1665      * @see #getModel
1666      * @see #clearSelection
1667      * @beaninfo
1668      *       bound: true
1669      *   attribute: visualUpdate true
1670      * description: The object that contains the data to be drawn by this JList.
1671      */
1672     public void setModel(ListModel<E> model) {
1673         if (model == null) {
1674             throw new IllegalArgumentException("model must be non null");
1675         }
1676         ListModel<E> oldValue = dataModel;
1677         dataModel = model;
1678         firePropertyChange("model", oldValue, dataModel);
1679         clearSelection();
1680     }
1681 
1682 
1683     /**
1684      * Constructs a read-only <code>ListModel</code> from an array of items,
1685      * and calls {@code setModel} with this model.
1686      * <p>
1687      * Attempts to pass a {@code null} value to this method results in
1688      * undefined behavior and, most likely, exceptions. The created model
1689      * references the given array directly. Attempts to modify the array
1690      * after invoking this method results in undefined behavior.
1691      *
1692      * @param listData an array of {@code E} containing the items to
1693      *        display in the list
1694      * @see #setModel
1695      */
1696     public void setListData(final E[] listData) {
1697         setModel (
1698             new AbstractListModel<E>() {
1699                 public int getSize() { return listData.length; }
1700                 public E getElementAt(int i) { return listData[i]; }
1701             }
1702         );
1703     }
1704 
1705 
1706     /**
1707      * Constructs a read-only <code>ListModel</code> from a <code>Vector</code>
1708      * and calls {@code setModel} with this model.
1709      * <p>
1710      * Attempts to pass a {@code null} value to this method results in
1711      * undefined behavior and, most likely, exceptions. The created model
1712      * references the given {@code Vector} directly. Attempts to modify the
1713      * {@code Vector} after invoking this method results in undefined behavior.
1714      *
1715      * @param listData a <code>Vector</code> containing the items to
1716      *                                          display in the list
1717      * @see #setModel
1718      */
1719     public void setListData(final Vector<? extends E> listData) {
1720         setModel (
1721             new AbstractListModel<E>() {
1722                 public int getSize() { return listData.size(); }
1723                 public E getElementAt(int i) { return listData.elementAt(i); }
1724             }
1725         );
1726     }
1727 
1728 
1729     /**
1730      * --- ListSelectionModel delegations and extensions ---
1731      */
1732 
1733 
1734     /**
1735      * Returns an instance of {@code DefaultListSelectionModel}; called
1736      * during construction to initialize the list's selection model
1737      * property.
1738      *
1739      * @return a {@code DefaultListSelecitonModel}, used to initialize
1740      *         the list's selection model property during construction
1741      * @see #setSelectionModel
1742      * @see DefaultListSelectionModel
1743      */
1744     protected ListSelectionModel createSelectionModel() {
1745         return new DefaultListSelectionModel();
1746     }
1747 
1748 
1749     /**
1750      * Returns the current selection model. The selection model maintains the
1751      * selection state of the list. See the class level documentation for more
1752      * details.
1753      *
1754      * @return the <code>ListSelectionModel</code> that maintains the
1755      *         list's selections
1756      *
1757      * @see #setSelectionModel
1758      * @see ListSelectionModel
1759      */
1760     public ListSelectionModel getSelectionModel() {
1761         return selectionModel;
1762     }
1763 
1764 
1765     /**
1766      * Notifies {@code ListSelectionListener}s added directly to the list
1767      * of selection changes made to the selection model. {@code JList}
1768      * listens for changes made to the selection in the selection model,
1769      * and forwards notification to listeners added to the list directly,
1770      * by calling this method.
1771      * <p>
1772      * This method constructs a {@code ListSelectionEvent} with this list
1773      * as the source, and the specified arguments, and sends it to the
1774      * registered {@code ListSelectionListeners}.


1849     public void removeListSelectionListener(ListSelectionListener listener) {
1850         listenerList.remove(ListSelectionListener.class, listener);
1851     }
1852 
1853 
1854     /**
1855      * Returns an array of all the {@code ListSelectionListener}s added
1856      * to this {@code JList} by way of {@code addListSelectionListener}.
1857      *
1858      * @return all of the {@code ListSelectionListener}s on this list, or
1859      *         an empty array if no listeners have been added
1860      * @see #addListSelectionListener
1861      * @since 1.4
1862      */
1863     public ListSelectionListener[] getListSelectionListeners() {
1864         return listenerList.getListeners(ListSelectionListener.class);
1865     }
1866 
1867 
1868     /**
1869      * Sets the <code>selectionModel</code> for the list to a
1870      * non-<code>null</code> <code>ListSelectionModel</code>
1871      * implementation. The selection model handles the task of making single
1872      * selections, selections of contiguous ranges, and non-contiguous
1873      * selections.
1874      * <p>
1875      * This is a JavaBeans bound property.
1876      *
1877      * @param selectionModel  the <code>ListSelectionModel</code> that
1878      *                          implements the selections
1879      * @exception IllegalArgumentException   if <code>selectionModel</code>
1880      *                                          is <code>null</code>
1881      * @see #getSelectionModel
1882      * @beaninfo
1883      *       bound: true
1884      * description: The selection model, recording which cells are selected.
1885      */
1886     public void setSelectionModel(ListSelectionModel selectionModel) {
1887         if (selectionModel == null) {
1888             throw new IllegalArgumentException("selectionModel must be non null");
1889         }
1890 
1891         /* Remove the forwarding ListSelectionListener from the old
1892          * selectionModel, and add it to the new one, if necessary.
1893          */
1894         if (selectionListener != null) {
1895             this.selectionModel.removeListSelectionListener(selectionListener);
1896             selectionModel.addListSelectionListener(selectionListener);
1897         }
1898 
1899         ListSelectionModel oldValue = this.selectionModel;
1900         this.selectionModel = selectionModel;


2863      */
2864     public AccessibleContext getAccessibleContext() {
2865         if (accessibleContext == null) {
2866             accessibleContext = new AccessibleJList();
2867         }
2868         return accessibleContext;
2869     }
2870 
2871     /**
2872      * This class implements accessibility support for the
2873      * {@code JList} class. It provides an implementation of the
2874      * Java Accessibility API appropriate to list user-interface
2875      * elements.
2876      * <p>
2877      * <strong>Warning:</strong>
2878      * Serialized objects of this class will not be compatible with
2879      * future Swing releases. The current serialization support is
2880      * appropriate for short term storage or RMI between applications running
2881      * the same version of Swing.  As of 1.4, support for long term storage
2882      * of all JavaBeans&trade;
2883      * has been added to the <code>java.beans</code> package.
2884      * Please see {@link java.beans.XMLEncoder}.
2885      */
2886     @SuppressWarnings("serial") // Same-version serialization only
2887     protected class AccessibleJList extends AccessibleJComponent
2888         implements AccessibleSelection, PropertyChangeListener,
2889         ListSelectionListener, ListDataListener {
2890 
2891         int leadSelectionIndex;
2892 
2893         /**
2894          * Constructs an {@code AccessibleJList}.
2895          */
2896         public AccessibleJList() {
2897             super();
2898             JList.this.addPropertyChangeListener(this);
2899             JList.this.getSelectionModel().addListSelectionListener(this);
2900             JList.this.getModel().addListDataListener(this);
2901             leadSelectionIndex = JList.this.getLeadSelectionIndex();
2902         }
2903 


3031             AccessibleStateSet states = super.getAccessibleStateSet();
3032             if (selectionModel.getSelectionMode() !=
3033                 ListSelectionModel.SINGLE_SELECTION) {
3034                 states.add(AccessibleState.MULTISELECTABLE);
3035             }
3036             return states;
3037         }
3038 
3039         /**
3040          * Get the role of this object.
3041          *
3042          * @return an instance of AccessibleRole describing the role of the
3043          * object
3044          * @see AccessibleRole
3045          */
3046         public AccessibleRole getAccessibleRole() {
3047             return AccessibleRole.LIST;
3048         }
3049 
3050         /**
3051          * Returns the <code>Accessible</code> child contained at
3052          * the local coordinate <code>Point</code>, if one exists.
3053          * Otherwise returns <code>null</code>.
3054          *
3055          * @return the <code>Accessible</code> at the specified
3056          *    location, if it exists
3057          */
3058         public Accessible getAccessibleAt(Point p) {
3059             int i = locationToIndex(p);
3060             if (i >= 0) {
3061                 return new AccessibleJListChild(JList.this, i);
3062             } else {
3063                 return null;
3064             }
3065         }
3066 
3067         /**
3068          * Returns the number of accessible children in the object.  If all
3069          * of the children of this object implement Accessible, than this
3070          * method should return the number of children of this object.
3071          *
3072          * @return the number of accessible children in the object.
3073          */
3074         public int getAccessibleChildrenCount() {
3075             return getModel().getSize();


3101             return this;
3102         }
3103 
3104 
3105     // AccessibleSelection methods
3106 
3107         /**
3108          * Returns the number of items currently selected.
3109          * If no items are selected, the return value will be 0.
3110          *
3111          * @return the number of items currently selected.
3112          */
3113          public int getAccessibleSelectionCount() {
3114              return JList.this.getSelectedIndices().length;
3115          }
3116 
3117         /**
3118          * Returns an Accessible representing the specified selected item
3119          * in the object.  If there isn't a selection, or there are
3120          * fewer items selected than the integer passed in, the return
3121          * value will be <code>null</code>.
3122          *
3123          * @param i the zero-based index of selected items
3124          * @return an Accessible containing the selected item
3125          */
3126          public Accessible getAccessibleSelection(int i) {
3127              int len = getAccessibleSelectionCount();
3128              if (i < 0 || i >= len) {
3129                  return null;
3130              } else {
3131                  return getAccessibleChild(JList.this.getSelectedIndices()[i]);
3132              }
3133          }
3134 
3135         /**
3136          * Returns true if the current child of this object is selected.
3137          *
3138          * @param i the zero-based index of the child in this Accessible
3139          * object.
3140          * @see AccessibleContext#getAccessibleChild
3141          */


3708                         c.addFocusListener(l);
3709                     }
3710                 }
3711             }
3712 
3713             public void removeFocusListener(FocusListener l) {
3714                 AccessibleContext ac = getCurrentAccessibleContext();
3715                 if (ac instanceof AccessibleComponent) {
3716                     ((AccessibleComponent) ac).removeFocusListener(l);
3717                 } else {
3718                     Component c = getCurrentComponent();
3719                     if (c != null) {
3720                         c.removeFocusListener(l);
3721                     }
3722                 }
3723             }
3724 
3725             // TIGER - 4733624
3726             /**
3727              * Returns the icon for the element renderer, as the only item
3728              * of an array of <code>AccessibleIcon</code>s or a <code>null</code> array
3729              * if the renderer component contains no icons.
3730              *
3731              * @return an array containing the accessible icon
3732              *         or a <code>null</code> array if none
3733              * @since 1.3
3734              */
3735             public AccessibleIcon [] getAccessibleIcon() {
3736                 AccessibleContext ac = getCurrentAccessibleContext();
3737                 if (ac != null) {
3738                     return ac.getAccessibleIcon();
3739                 } else {
3740                     return null;
3741                 }
3742             }
3743         } // inner class AccessibleJListChild
3744     } // inner class AccessibleJList
3745 }


  85  * for(int i = 0; i < model.getSize(); i++) {
  86  *     System.out.println(model.getElementAt(i));
  87  * }
  88  * }
  89  * </pre>
  90  * <p>
  91  * A {@code ListModel} can be supplied directly to a {@code JList} by way of a
  92  * constructor or the {@code setModel} method. The contents need not be static -
  93  * the number of items, and the values of items can change over time. A correct
  94  * {@code ListModel} implementation notifies the set of
  95  * {@code javax.swing.event.ListDataListener}s that have been added to it, each
  96  * time a change occurs. These changes are characterized by a
  97  * {@code javax.swing.event.ListDataEvent}, which identifies the range of list
  98  * indices that have been modified, added, or removed. {@code JList}'s
  99  * {@code ListUI} is responsible for keeping the visual representation up to
 100  * date with changes, by listening to the model.
 101  * <p>
 102  * Simple, dynamic-content, {@code JList} applications can use the
 103  * {@code DefaultListModel} class to maintain list elements. This class
 104  * implements the {@code ListModel} interface and also provides a
 105  * {@code java.util.Vector}-like API. Applications that need a more
 106  * custom {@code ListModel} implementation may instead wish to subclass
 107  * {@code AbstractListModel}, which provides basic support for managing and
 108  * notifying listeners. For example, a read-only implementation of
 109  * {@code AbstractListModel}:
 110  * <pre>
 111  * {@code
 112  * // This list model has about 2^16 elements.  Enjoy scrolling.
 113  *
 114  * ListModel<String> bigData = new AbstractListModel<String>() {
 115  *     public int getSize() { return Short.MAX_VALUE; }
 116  *     public String getElementAt(int index) { return "Index " + index; }
 117  * };
 118  * }
 119  * </pre>
 120  * <p>
 121  * The selection state of a {@code JList} is managed by another separate
 122  * model, an instance of {@code ListSelectionModel}. {@code JList} is
 123  * initialized with a selection model on construction, and also contains
 124  * methods to query or set this selection model. Additionally, {@code JList}
 125  * provides convenient methods for easily managing the selection. These methods,
 126  * such as {@code setSelectedIndex} and {@code getSelectedValue}, are cover


 237  *         if (e.getClickCount() == 2) {
 238  *             int index = list.locationToIndex(e.getPoint());
 239  *             System.out.println("Double clicked on Item " + index);
 240  *          }
 241  *     }
 242  * };
 243  * list.addMouseListener(mouseListener);
 244  * </pre>
 245  * <p>
 246  * <strong>Warning:</strong> Swing is not thread safe. For more
 247  * information see <a
 248  * href="package-summary.html#threading">Swing's Threading
 249  * Policy</a>.
 250  * <p>
 251  * <strong>Warning:</strong>
 252  * Serialized objects of this class will not be compatible with
 253  * future Swing releases. The current serialization support is
 254  * appropriate for short term storage or RMI between applications running
 255  * the same version of Swing.  As of 1.4, support for long term storage
 256  * of all JavaBeans&trade;
 257  * has been added to the {@code java.beans} package.
 258  * Please see {@link java.beans.XMLEncoder}.
 259  * <p>
 260  * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/list.html">How to Use Lists</a>
 261  * in <a href="http://docs.oracle.com/javase/tutorial/"><em>The Java Tutorial</em></a>
 262  * for further documentation.
 263  *
 264  * @see ListModel
 265  * @see AbstractListModel
 266  * @see DefaultListModel
 267  * @see ListSelectionModel
 268  * @see DefaultListSelectionModel
 269  * @see ListCellRenderer
 270  * @see DefaultListCellRenderer
 271  *
 272  * @param <E> the type of the elements of this list
 273  *
 274  * @beaninfo
 275  *   attribute: isContainer false
 276  * description: A component which allows for the selection of one or more objects from a list.
 277  *


 309      * @see #setLayoutOrientation
 310      * @since 1.4
 311      */
 312     public static final int HORIZONTAL_WRAP = 2;
 313 
 314     private int fixedCellWidth = -1;
 315     private int fixedCellHeight = -1;
 316     private int horizontalScrollIncrement = -1;
 317     private E prototypeCellValue;
 318     private int visibleRowCount = 8;
 319     private Color selectionForeground;
 320     private Color selectionBackground;
 321     private boolean dragEnabled;
 322 
 323     private ListSelectionModel selectionModel;
 324     private ListModel<E> dataModel;
 325     private ListCellRenderer<? super E> cellRenderer;
 326     private ListSelectionListener selectionListener;
 327 
 328     /**
 329      * How to lay out the cells; defaults to {@code VERTICAL}.
 330      */
 331     private int layoutOrientation;
 332 
 333     /**
 334      * The drop mode for this component.
 335      */
 336     private DropMode dropMode = DropMode.USE_SELECTION;
 337 
 338     /**
 339      * The drop location.
 340      */
 341     private transient DropLocation dropLocation;
 342 
 343     /**
 344      * A subclass of {@code TransferHandler.DropLocation} representing
 345      * a drop location for a {@code JList}.
 346      *
 347      * @see #getDropLocation
 348      * @since 1.6
 349      */
 350     public static final class DropLocation extends TransferHandler.DropLocation {
 351         private final int index;
 352         private final boolean isInsert;
 353 
 354         private DropLocation(Point p, int index, boolean isInsert) {
 355             super(p);
 356             this.index = index;
 357             this.isInsert = isInsert;
 358         }
 359 
 360         /**
 361          * Returns the index where dropped data should be placed in the
 362          * list. Interpretation of the value depends on the drop mode set on
 363          * the associated component. If the drop mode is either
 364          * {@code DropMode.USE_SELECTION} or {@code DropMode.ON},
 365          * the return value is an index of a row in the list. If the drop mode is
 366          * {@code DropMode.INSERT}, the return value refers to the index
 367          * where the data should be inserted. If the drop mode is
 368          * {@code DropMode.ON_OR_INSERT}, the value of
 369          * {@code isInsert()} indicates whether the index is an index
 370          * of a row, or an insert index.
 371          * <p>
 372          * {@code -1} indicates that the drop occurred over empty space,
 373          * and no index could be calculated.
 374          *
 375          * @return the drop index
 376          */
 377         public int getIndex() {
 378             return index;
 379         }
 380 
 381         /**
 382          * Returns whether or not this location represents an insert
 383          * location.
 384          *
 385          * @return whether or not this is an insert location
 386          */
 387         public boolean isInsert() {
 388             return isInsert;
 389         }
 390 
 391         /**
 392          * Returns a string representation of this drop location.


 420         if (dataModel == null) {
 421             throw new IllegalArgumentException("dataModel must be non null");
 422         }
 423 
 424         // Register with the ToolTipManager so that tooltips from the
 425         // renderer show through.
 426         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
 427         toolTipManager.registerComponent(this);
 428 
 429         layoutOrientation = VERTICAL;
 430 
 431         this.dataModel = dataModel;
 432         selectionModel = createSelectionModel();
 433         setAutoscrolls(true);
 434         setOpaque(true);
 435         updateUI();
 436     }
 437 
 438 
 439     /**
 440      * Constructs a {@code JList} that displays the elements in
 441      * the specified array. This constructor creates a read-only model
 442      * for the given array, and then delegates to the constructor that
 443      * takes a {@code ListModel}.
 444      * <p>
 445      * Attempts to pass a {@code null} value to this method results in
 446      * undefined behavior and, most likely, exceptions. The created model
 447      * references the given array directly. Attempts to modify the array
 448      * after constructing the list results in undefined behavior.
 449      *
 450      * @param  listData  the array of Objects to be loaded into the data model,
 451      *                   {@code non-null}
 452      */
 453     public JList(final E[] listData)
 454     {
 455         this (
 456             new AbstractListModel<E>() {
 457                 public int getSize() { return listData.length; }
 458                 public E getElementAt(int i) { return listData[i]; }
 459             }
 460         );
 461     }
 462 
 463 
 464     /**
 465      * Constructs a {@code JList} that displays the elements in
 466      * the specified {@code Vector}. This constructor creates a read-only
 467      * model for the given {@code Vector}, and then delegates to the constructor
 468      * that takes a {@code ListModel}.
 469      * <p>
 470      * Attempts to pass a {@code null} value to this method results in
 471      * undefined behavior and, most likely, exceptions. The created model
 472      * references the given {@code Vector} directly. Attempts to modify the
 473      * {@code Vector} after constructing the list results in undefined behavior.
 474      *
 475      * @param  listData  the {@code Vector} to be loaded into the
 476      *                   data model, {@code non-null}
 477      */
 478     public JList(final Vector<? extends E> listData) {
 479         this (
 480             new AbstractListModel<E>() {
 481                 public int getSize() { return listData.size(); }
 482                 public E getElementAt(int i) { return listData.elementAt(i); }
 483             }
 484         );
 485     }
 486 
 487 
 488     /**
 489      * Constructs a {@code JList} with an empty, read-only, model.
 490      */
 491     public JList() {
 492         this (
 493             new AbstractListModel<E>() {
 494               public int getSize() { return 0; }
 495               public E getElementAt(int i) { throw new IndexOutOfBoundsException("No Data Model"); }
 496             }
 497         );
 498     }
 499 
 500 
 501     /**
 502      * Returns the {@code ListUI}, the look and feel object that
 503      * renders this component.
 504      *
 505      * @return the {@code ListUI} object that renders this component
 506      */
 507     public ListUI getUI() {
 508         return (ListUI)ui;
 509     }
 510 
 511 
 512     /**
 513      * Sets the {@code ListUI}, the look and feel object that
 514      * renders this component.
 515      *
 516      * @param ui  the {@code ListUI} object
 517      * @see UIDefaults#getUI
 518      * @beaninfo
 519      *        bound: true
 520      *       hidden: true
 521      *    attribute: visualUpdate true
 522      *  description: The UI object that implements the Component's LookAndFeel.
 523      */
 524     public void setUI(ListUI ui) {
 525         super.setUI(ui);
 526     }
 527 
 528 
 529     /**
 530      * Resets the {@code ListUI} property by setting it to the value provided
 531      * by the current look and feel. If the current cell renderer was installed
 532      * by the developer (rather than the look and feel itself), this also causes
 533      * the cell renderer and its children to be updated, by calling
 534      * {@code SwingUtilities.updateComponentTreeUI} on it.
 535      *
 536      * @see UIManager#getUI
 537      * @see SwingUtilities#updateComponentTreeUI
 538      */
 539     public void updateUI() {
 540         setUI((ListUI)UIManager.getUI(this));
 541 
 542         ListCellRenderer<? super E> renderer = getCellRenderer();
 543         if (renderer instanceof Component) {
 544             SwingUtilities.updateComponentTreeUI((Component)renderer);
 545         }
 546     }
 547 
 548 
 549     /**
 550      * Returns {@code "ListUI"}, the {@code UIDefaults} key used to look
 551      * up the name of the {@code javax.swing.plaf.ListUI} class that defines
 552      * the look and feel for this component.
 553      *
 554      * @return the string "ListUI"
 555      * @see JComponent#getUIClassID
 556      * @see UIDefaults#getUI
 557      */
 558     public String getUIClassID() {
 559         return uiClassID;
 560     }
 561 
 562 
 563     /* -----private-----
 564      * This method is called by setPrototypeCellValue and setCellRenderer
 565      * to update the fixedCellWidth and fixedCellHeight properties from the
 566      * current value of prototypeCellValue (if it's non null).
 567      * <p>
 568      * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
 569      * generate PropertyChangeEvents for them.
 570      *


 612     /**
 613      * Sets the {@code prototypeCellValue} property, and then (if the new value
 614      * is {@code non-null}), computes the {@code fixedCellWidth} and
 615      * {@code fixedCellHeight} properties by requesting the cell renderer
 616      * component for the given value (and index 0) from the cell renderer, and
 617      * using that component's preferred size.
 618      * <p>
 619      * This method is useful when the list is too long to allow the
 620      * {@code ListUI} to compute the width/height of each cell, and there is a
 621      * single cell value that is known to occupy as much space as any of the
 622      * others, a so-called prototype.
 623      * <p>
 624      * While all three of the {@code prototypeCellValue},
 625      * {@code fixedCellHeight}, and {@code fixedCellWidth} properties may be
 626      * modified by this method, {@code PropertyChangeEvent} notifications are
 627      * only sent when the {@code prototypeCellValue} property changes.
 628      * <p>
 629      * To see an example which sets this property, see the
 630      * <a href="#prototype_example">class description</a> above.
 631      * <p>
 632      * The default value of this property is {@code null}.
 633      * <p>
 634      * This is a JavaBeans bound property.
 635      *
 636      * @param prototypeCellValue  the value on which to base
 637      *                          {@code fixedCellWidth} and
 638      *                          {@code fixedCellHeight}
 639      * @see #getPrototypeCellValue
 640      * @see #setFixedCellWidth
 641      * @see #setFixedCellHeight
 642      * @see JComponent#addPropertyChangeListener
 643      * @beaninfo
 644      *       bound: true
 645      *   attribute: visualUpdate true
 646      * description: The cell prototype value, used to compute cell width and height.
 647      */
 648     public void setPrototypeCellValue(E prototypeCellValue) {
 649         E oldValue = this.prototypeCellValue;
 650         this.prototypeCellValue = prototypeCellValue;
 651 
 652         /* If the prototypeCellValue has changed and is non-null,
 653          * then recompute fixedCellWidth and fixedCellHeight.
 654          */
 655 
 656         if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
 657             updateFixedCellSize();
 658         }
 659 
 660         firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
 661     }
 662 
 663 
 664     /**
 665      * Returns the value of the {@code fixedCellWidth} property.
 666      *
 667      * @return the fixed cell width
 668      * @see #setFixedCellWidth
 669      */
 670     public int getFixedCellWidth() {
 671         return fixedCellWidth;
 672     }
 673 
 674     /**
 675      * Sets a fixed value to be used for the width of every cell in the list.
 676      * If {@code width} is -1, cell widths are computed in the {@code ListUI}
 677      * by applying {@code getPreferredSize} to the cell renderer component
 678      * for each list element.
 679      * <p>
 680      * The default value of this property is {@code -1}.
 681      * <p>
 682      * This is a JavaBeans bound property.
 683      *
 684      * @param width the width to be used for all cells in the list
 685      * @see #setPrototypeCellValue
 686      * @see #setFixedCellWidth
 687      * @see JComponent#addPropertyChangeListener
 688      * @beaninfo
 689      *       bound: true
 690      *   attribute: visualUpdate true
 691      * description: Defines a fixed cell width when greater than zero.
 692      */
 693     public void setFixedCellWidth(int width) {
 694         int oldValue = fixedCellWidth;
 695         fixedCellWidth = width;
 696         firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
 697     }
 698 
 699 
 700     /**
 701      * Returns the value of the {@code fixedCellHeight} property.
 702      *
 703      * @return the fixed cell height
 704      * @see #setFixedCellHeight
 705      */
 706     public int getFixedCellHeight() {
 707         return fixedCellHeight;
 708     }
 709 
 710     /**
 711      * Sets a fixed value to be used for the height of every cell in the list.
 712      * If {@code height} is -1, cell heights are computed in the {@code ListUI}
 713      * by applying {@code getPreferredSize} to the cell renderer component
 714      * for each list element.
 715      * <p>
 716      * The default value of this property is {@code -1}.
 717      * <p>
 718      * This is a JavaBeans bound property.
 719      *
 720      * @param height the height to be used for all cells in the list
 721      * @see #setPrototypeCellValue
 722      * @see #setFixedCellWidth
 723      * @see JComponent#addPropertyChangeListener
 724      * @beaninfo
 725      *       bound: true
 726      *   attribute: visualUpdate true
 727      * description: Defines a fixed cell height when greater than zero.
 728      */
 729     public void setFixedCellHeight(int height) {
 730         int oldValue = fixedCellHeight;
 731         fixedCellHeight = height;
 732         firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
 733     }


 735 
 736     /**
 737      * Returns the object responsible for painting list items.
 738      *
 739      * @return the value of the {@code cellRenderer} property
 740      * @see #setCellRenderer
 741      */
 742     @Transient
 743     public ListCellRenderer<? super E> getCellRenderer() {
 744         return cellRenderer;
 745     }
 746 
 747     /**
 748      * Sets the delegate that is used to paint each cell in the list.
 749      * The job of a cell renderer is discussed in detail in the
 750      * <a href="#renderer">class level documentation</a>.
 751      * <p>
 752      * If the {@code prototypeCellValue} property is {@code non-null},
 753      * setting the cell renderer also causes the {@code fixedCellWidth} and
 754      * {@code fixedCellHeight} properties to be re-calculated. Only one
 755      * {@code PropertyChangeEvent} is generated however -
 756      * for the {@code cellRenderer} property.
 757      * <p>
 758      * The default value of this property is provided by the {@code ListUI}
 759      * delegate, i.e. by the look and feel implementation.
 760      * <p>
 761      * This is a JavaBeans bound property.
 762      *
 763      * @param cellRenderer the {@code ListCellRenderer}
 764      *                          that paints list cells
 765      * @see #getCellRenderer
 766      * @beaninfo
 767      *       bound: true
 768      *   attribute: visualUpdate true
 769      * description: The component used to draw the cells.
 770      */
 771     public void setCellRenderer(ListCellRenderer<? super E> cellRenderer) {
 772         ListCellRenderer<? super E> oldValue = this.cellRenderer;
 773         this.cellRenderer = cellRenderer;
 774 
 775         /* If the cellRenderer has changed and prototypeCellValue
 776          * was set, then recompute fixedCellWidth and fixedCellHeight.
 777          */
 778         if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
 779             updateFixedCellSize();
 780         }
 781 
 782         firePropertyChange("cellRenderer", oldValue, cellRenderer);
 783     }


 956      * <pre>
 957      * VERTICAL:          0
 958      *                    1
 959      *                    2
 960      *                    3
 961      *                    4
 962      *
 963      * HORIZONTAL_WRAP:   0  1  2
 964      *                    3  4
 965      *
 966      * VERTICAL_WRAP:     0  3
 967      *                    1  4
 968      *                    2
 969      * </pre>
 970      * <p>
 971      * A description of these layouts follows:
 972      *
 973      * <table border="1"
 974      *  summary="Describes layouts VERTICAL, HORIZONTAL_WRAP, and VERTICAL_WRAP">
 975      *   <tr><th><p style="text-align:left">Value</p></th><th><p style="text-align:left">Description</p></th></tr>
 976      *   <tr><td>{@code VERTICAL}
 977      *       <td>Cells are layed out vertically in a single column.
 978      *   <tr><td>{@code HORIZONTAL_WRAP}
 979      *       <td>Cells are layed out horizontally, wrapping to a new row as
 980      *           necessary. If the {@code visibleRowCount} property is less than
 981      *           or equal to zero, wrapping is determined by the width of the
 982      *           list; otherwise wrapping is done in such a way as to ensure
 983      *           {@code visibleRowCount} rows in the list.
 984      *   <tr><td>{@code VERTICAL_WRAP}
 985      *       <td>Cells are layed out vertically, wrapping to a new column as
 986      *           necessary. If the {@code visibleRowCount} property is less than
 987      *           or equal to zero, wrapping is determined by the height of the
 988      *           list; otherwise wrapping is done at {@code visibleRowCount} rows.
 989      *  </table>
 990      * <p>
 991      * The default value of this property is {@code VERTICAL}.
 992      *
 993      * @param layoutOrientation the new layout orientation, one of:
 994      *        {@code VERTICAL}, {@code HORIZONTAL_WRAP} or {@code VERTICAL_WRAP}
 995      * @see #getLayoutOrientation
 996      * @see #setVisibleRowCount
 997      * @see #getScrollableTracksViewportHeight
 998      * @see #getScrollableTracksViewportWidth
 999      * @throws IllegalArgumentException if {@code layoutOrientation} isn't one of the
1000      *         allowable values
1001      * @since 1.4
1002      * @beaninfo
1003      *       bound: true
1004      *   attribute: visualUpdate true
1005      * description: Defines the way list cells are layed out.
1006      *        enum: VERTICAL JList.VERTICAL
1007      *              HORIZONTAL_WRAP JList.HORIZONTAL_WRAP
1008      *              VERTICAL_WRAP JList.VERTICAL_WRAP
1009      */
1010     public void setLayoutOrientation(int layoutOrientation) {
1011         int oldValue = this.layoutOrientation;


1119                                     }
1120                                 }
1121 
1122                             }
1123                             else {
1124                                 last = visIndex;
1125                             }
1126                         }
1127                     } while (visIndex != -1 && last != visIndex);
1128                 }
1129             }
1130         }
1131         return location;
1132     }
1133 
1134 
1135     /**
1136      * Scrolls the list within an enclosing viewport to make the specified
1137      * cell completely visible. This calls {@code scrollRectToVisible} with
1138      * the bounds of the specified cell. For this method to work, the
1139      * {@code JList} must be within a {@code JViewport}.
1140      * <p>
1141      * If the given index is outside the list's range of cells, this method
1142      * results in nothing.
1143      *
1144      * @param index  the index of the cell to make visible
1145      * @see JComponent#scrollRectToVisible
1146      * @see #getVisibleRect
1147      */
1148     public void ensureIndexIsVisible(int index) {
1149         Rectangle cellBounds = getCellBounds(index, index);
1150         if (cellBounds != null) {
1151             scrollRectToVisible(cellBounds);
1152         }
1153     }
1154 
1155     /**
1156      * Turns on or off automatic drag handling. In order to enable automatic
1157      * drag handling, this property should be set to {@code true}, and the
1158      * list's {@code TransferHandler} needs to be {@code non-null}.
1159      * The default value of the {@code dragEnabled} property is {@code false}.
1160      * <p>
1161      * The job of honoring this property, and recognizing a user drag gesture,
1162      * lies with the look and feel implementation, and in particular, the list's
1163      * {@code ListUI}. When automatic drag handling is enabled, most look and
1164      * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1165      * drag and drop operation whenever the user presses the mouse button over
1166      * an item and then moves the mouse a few pixels. Setting this property to
1167      * {@code true} can therefore have a subtle effect on how selections behave.
1168      * <p>
1169      * If a look and feel is used that ignores this property, you can still
1170      * begin a drag and drop operation by calling {@code exportAsDrag} on the
1171      * list's {@code TransferHandler}.
1172      *
1173      * @param b whether or not to enable automatic drag handling
1174      * @exception HeadlessException if
1175      *            {@code b} is {@code true} and
1176      *            {@code GraphicsEnvironment.isHeadless()}
1177      *            returns {@code true}
1178      * @see java.awt.GraphicsEnvironment#isHeadless
1179      * @see #getDragEnabled
1180      * @see #setTransferHandler
1181      * @see TransferHandler
1182      * @since 1.4
1183      *
1184      * @beaninfo
1185      *  description: determines whether automatic drag handling is enabled
1186      *        bound: false
1187      */
1188     public void setDragEnabled(boolean b) {
1189         if (b && GraphicsEnvironment.isHeadless()) {
1190             throw new HeadlessException();
1191         }
1192         dragEnabled = b;
1193     }
1194 
1195     /**
1196      * Returns whether or not automatic drag handling is enabled.
1197      *
1198      * @return the value of the {@code dragEnabled} property
1199      * @see #setDragEnabled
1200      * @since 1.4
1201      */
1202     public boolean getDragEnabled() {
1203         return dragEnabled;
1204     }
1205 
1206     /**
1207      * Sets the drop mode for this component. For backward compatibility,
1208      * the default for this property is {@code DropMode.USE_SELECTION}.
1209      * Usage of one of the other modes is recommended, however, for an
1210      * improved user experience. {@code DropMode.ON}, for instance,
1211      * offers similar behavior of showing items as selected, but does so without
1212      * affecting the actual selection in the list.
1213      * <p>
1214      * {@code JList} supports the following drop modes:
1215      * <ul>
1216      *    <li>{@code DropMode.USE_SELECTION}</li>
1217      *    <li>{@code DropMode.ON}</li>
1218      *    <li>{@code DropMode.INSERT}</li>
1219      *    <li>{@code DropMode.ON_OR_INSERT}</li>
1220      * </ul>
1221      * The drop mode is only meaningful if this component has a
1222      * {@code TransferHandler} that accepts drops.
1223      *
1224      * @param dropMode the drop mode to use
1225      * @throws IllegalArgumentException if the drop mode is unsupported
1226      *         or {@code null}
1227      * @see #getDropMode
1228      * @see #getDropLocation
1229      * @see #setTransferHandler
1230      * @see TransferHandler
1231      * @since 1.6
1232      */
1233     public final void setDropMode(DropMode dropMode) {
1234         if (dropMode != null) {
1235             switch (dropMode) {
1236                 case USE_SELECTION:
1237                 case ON:
1238                 case INSERT:
1239                 case ON_OR_INSERT:
1240                     this.dropMode = dropMode;
1241                     return;
1242             }
1243         }
1244 
1245         throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for list");
1246     }
1247 
1248     /**
1249      * Returns the drop mode for this component.
1250      *
1251      * @return the drop mode for this component
1252      * @see #setDropMode
1253      * @since 1.6
1254      */
1255     public final DropMode getDropMode() {
1256         return dropMode;
1257     }
1258 
1259     /**
1260      * Calculates a drop location in this component, representing where a
1261      * drop at the given point should insert data.
1262      *
1263      * @param p the point to calculate a drop location for
1264      * @return the drop location, or {@code null}
1265      */
1266     DropLocation dropLocationForPoint(Point p) {
1267         DropLocation location = null;
1268         Rectangle rect = null;
1269 
1270         int index = locationToIndex(p);
1271         if (index != -1) {
1272             rect = getCellBounds(index, index);
1273         }
1274 
1275         switch(dropMode) {
1276             case USE_SELECTION:
1277             case ON:
1278                 location = new DropLocation(p,
1279                     (rect != null && rect.contains(p)) ? index : -1,
1280                     false);
1281 
1282                 break;
1283             case INSERT:
1284                 if (index == -1) {


1347     }
1348 
1349     /**
1350      * Called to set or clear the drop location during a DnD operation.
1351      * In some cases, the component may need to use it's internal selection
1352      * temporarily to indicate the drop location. To help facilitate this,
1353      * this method returns and accepts as a parameter a state object.
1354      * This state object can be used to store, and later restore, the selection
1355      * state. Whatever this method returns will be passed back to it in
1356      * future calls, as the state parameter. If it wants the DnD system to
1357      * continue storing the same state, it must pass it back every time.
1358      * Here's how this is used:
1359      * <p>
1360      * Let's say that on the first call to this method the component decides
1361      * to save some state (because it is about to use the selection to show
1362      * a drop index). It can return a state object to the caller encapsulating
1363      * any saved selection state. On a second call, let's say the drop location
1364      * is being changed to something else. The component doesn't need to
1365      * restore anything yet, so it simply passes back the same state object
1366      * to have the DnD system continue storing it. Finally, let's say this
1367      * method is messaged with {@code null}. This means DnD
1368      * is finished with this component for now, meaning it should restore
1369      * state. At this point, it can use the state parameter to restore
1370      * said state, and of course return {@code null} since there's
1371      * no longer anything to store.
1372      *
1373      * @param location the drop location (as calculated by
1374      *        {@code dropLocationForPoint}) or {@code null}
1375      *        if there's no longer a valid drop location
1376      * @param state the state object saved earlier for this component,
1377      *        or {@code null}
1378      * @param forDrop whether or not the method is being called because an
1379      *        actual drop occurred
1380      * @return any saved state for this component, or {@code null} if none
1381      */
1382     Object setDropLocation(TransferHandler.DropLocation location,
1383                            Object state,
1384                            boolean forDrop) {
1385 
1386         Object retVal = null;
1387         DropLocation listLocation = (DropLocation)location;
1388 
1389         if (dropMode == DropMode.USE_SELECTION) {
1390             if (listLocation == null) {
1391                 if (!forDrop && state != null) {
1392                     setSelectedIndices(((int[][])state)[0]);
1393 
1394                     int anchor = ((int[][])state)[1][0];
1395                     int lead = ((int[][])state)[1][1];
1396 
1397                     SwingUtilities2.setLeadAnchorWithoutSelection(
1398                             getSelectionModel(), lead, anchor);
1399                 }
1400             } else {


1414                 } else {
1415                     setSelectionInterval(index, index);
1416                 }
1417             }
1418         }
1419 
1420         DropLocation old = dropLocation;
1421         dropLocation = listLocation;
1422         firePropertyChange("dropLocation", old, dropLocation);
1423 
1424         return retVal;
1425     }
1426 
1427     /**
1428      * Returns the location that this component should visually indicate
1429      * as the drop location during a DnD operation over the component,
1430      * or {@code null} if no location is to currently be shown.
1431      * <p>
1432      * This method is not meant for querying the drop location
1433      * from a {@code TransferHandler}, as the drop location is only
1434      * set after the {@code TransferHandler}'s {@code canImport}
1435      * has returned and has allowed for the location to be shown.
1436      * <p>
1437      * When this property changes, a property change event with
1438      * name "dropLocation" is fired by the component.
1439      * <p>
1440      * By default, responsibility for listening for changes to this property
1441      * and indicating the drop location visually lies with the list's
1442      * {@code ListUI}, which may paint it directly and/or install a cell
1443      * renderer to do so. Developers wishing to implement custom drop location
1444      * painting and/or replace the default cell renderer, may need to honor
1445      * this property.
1446      *
1447      * @return the drop location
1448      * @see #setDropMode
1449      * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1450      * @since 1.6
1451      */
1452     public final DropLocation getDropLocation() {
1453         return dropLocation;
1454     }


1497                     }
1498                 }
1499 
1500                 if (string != null && string.startsWith(prefix)) {
1501                     return index;
1502                 }
1503             }
1504             index = (index + increment + max) % max;
1505         } while (index != startIndex);
1506         return -1;
1507     }
1508 
1509     /**
1510      * Returns the tooltip text to be used for the given event. This overrides
1511      * {@code JComponent}'s {@code getToolTipText} to first check the cell
1512      * renderer component for the cell over which the event occurred, returning
1513      * its tooltip text, if any. This implementation allows you to specify
1514      * tooltip text on the cell level, by using {@code setToolTipText} on your
1515      * cell renderer component.
1516      * <p>
1517      * <strong>Note:</strong> For {@code JList} to properly display the
1518      * tooltips of its renderers in this manner, {@code JList} must be a
1519      * registered component with the {@code ToolTipManager}. This registration
1520      * is done automatically in the constructor. However, if at a later point
1521      * {@code JList} is unregistered, by way of a call to
1522      * {@code setToolTipText(null)}, tips from the renderers will no longer display.
1523      *
1524      * @param event the {@code MouseEvent} to fetch the tooltip text for
1525      * @see JComponent#setToolTipText
1526      * @see JComponent#getToolTipText
1527      */
1528     public String getToolTipText(MouseEvent event) {
1529         if(event != null) {
1530             Point p = event.getPoint();
1531             int index = locationToIndex(p);
1532             ListCellRenderer<? super E> r = getCellRenderer();
1533             Rectangle cellBounds;
1534 
1535             if (index != -1 && r != null && (cellBounds =
1536                                getCellBounds(index, index)) != null &&
1537                                cellBounds.contains(p.x, p.y)) {
1538                 ListSelectionModel lsm = getSelectionModel();
1539                 Component rComponent = r.getListCellRendererComponent(
1540                            this, getModel().getElementAt(index), index,
1541                            lsm.isSelectedIndex(index),


1624      * in the list's {@code ListUI}. It returns {@code null} if the list has
1625      * no {@code ListUI}.
1626      *
1627      * @param index0 the first index in the range
1628      * @param index1 the second index in the range
1629      * @return the bounding rectangle for the range of cells, or {@code null}
1630      */
1631     public Rectangle getCellBounds(int index0, int index1) {
1632         ListUI ui = getUI();
1633         return (ui != null) ? ui.getCellBounds(this, index0, index1) : null;
1634     }
1635 
1636 
1637     /**
1638      * --- ListModel Support ---
1639      */
1640 
1641 
1642     /**
1643      * Returns the data model that holds the list of items displayed
1644      * by the {@code JList} component.
1645      *
1646      * @return the {@code ListModel} that provides the displayed
1647      *                          list of items
1648      * @see #setModel
1649      */
1650     public ListModel<E> getModel() {
1651         return dataModel;
1652     }
1653 
1654     /**
1655      * Sets the model that represents the contents or "value" of the
1656      * list, notifies property change listeners, and then clears the
1657      * list's selection.
1658      * <p>
1659      * This is a JavaBeans bound property.
1660      *
1661      * @param model  the {@code ListModel} that provides the
1662      *                                          list of items for display
1663      * @exception IllegalArgumentException  if {@code model} is
1664      *                                          {@code null}
1665      * @see #getModel
1666      * @see #clearSelection
1667      * @beaninfo
1668      *       bound: true
1669      *   attribute: visualUpdate true
1670      * description: The object that contains the data to be drawn by this JList.
1671      */
1672     public void setModel(ListModel<E> model) {
1673         if (model == null) {
1674             throw new IllegalArgumentException("model must be non null");
1675         }
1676         ListModel<E> oldValue = dataModel;
1677         dataModel = model;
1678         firePropertyChange("model", oldValue, dataModel);
1679         clearSelection();
1680     }
1681 
1682 
1683     /**
1684      * Constructs a read-only {@code ListModel} from an array of items,
1685      * and calls {@code setModel} with this model.
1686      * <p>
1687      * Attempts to pass a {@code null} value to this method results in
1688      * undefined behavior and, most likely, exceptions. The created model
1689      * references the given array directly. Attempts to modify the array
1690      * after invoking this method results in undefined behavior.
1691      *
1692      * @param listData an array of {@code E} containing the items to
1693      *        display in the list
1694      * @see #setModel
1695      */
1696     public void setListData(final E[] listData) {
1697         setModel (
1698             new AbstractListModel<E>() {
1699                 public int getSize() { return listData.length; }
1700                 public E getElementAt(int i) { return listData[i]; }
1701             }
1702         );
1703     }
1704 
1705 
1706     /**
1707      * Constructs a read-only {@code ListModel} from a {@code Vector}
1708      * and calls {@code setModel} with this model.
1709      * <p>
1710      * Attempts to pass a {@code null} value to this method results in
1711      * undefined behavior and, most likely, exceptions. The created model
1712      * references the given {@code Vector} directly. Attempts to modify the
1713      * {@code Vector} after invoking this method results in undefined behavior.
1714      *
1715      * @param listData a {@code Vector} containing the items to
1716      *                                          display in the list
1717      * @see #setModel
1718      */
1719     public void setListData(final Vector<? extends E> listData) {
1720         setModel (
1721             new AbstractListModel<E>() {
1722                 public int getSize() { return listData.size(); }
1723                 public E getElementAt(int i) { return listData.elementAt(i); }
1724             }
1725         );
1726     }
1727 
1728 
1729     /**
1730      * --- ListSelectionModel delegations and extensions ---
1731      */
1732 
1733 
1734     /**
1735      * Returns an instance of {@code DefaultListSelectionModel}; called
1736      * during construction to initialize the list's selection model
1737      * property.
1738      *
1739      * @return a {@code DefaultListSelecitonModel}, used to initialize
1740      *         the list's selection model property during construction
1741      * @see #setSelectionModel
1742      * @see DefaultListSelectionModel
1743      */
1744     protected ListSelectionModel createSelectionModel() {
1745         return new DefaultListSelectionModel();
1746     }
1747 
1748 
1749     /**
1750      * Returns the current selection model. The selection model maintains the
1751      * selection state of the list. See the class level documentation for more
1752      * details.
1753      *
1754      * @return the {@code ListSelectionModel} that maintains the
1755      *         list's selections
1756      *
1757      * @see #setSelectionModel
1758      * @see ListSelectionModel
1759      */
1760     public ListSelectionModel getSelectionModel() {
1761         return selectionModel;
1762     }
1763 
1764 
1765     /**
1766      * Notifies {@code ListSelectionListener}s added directly to the list
1767      * of selection changes made to the selection model. {@code JList}
1768      * listens for changes made to the selection in the selection model,
1769      * and forwards notification to listeners added to the list directly,
1770      * by calling this method.
1771      * <p>
1772      * This method constructs a {@code ListSelectionEvent} with this list
1773      * as the source, and the specified arguments, and sends it to the
1774      * registered {@code ListSelectionListeners}.


1849     public void removeListSelectionListener(ListSelectionListener listener) {
1850         listenerList.remove(ListSelectionListener.class, listener);
1851     }
1852 
1853 
1854     /**
1855      * Returns an array of all the {@code ListSelectionListener}s added
1856      * to this {@code JList} by way of {@code addListSelectionListener}.
1857      *
1858      * @return all of the {@code ListSelectionListener}s on this list, or
1859      *         an empty array if no listeners have been added
1860      * @see #addListSelectionListener
1861      * @since 1.4
1862      */
1863     public ListSelectionListener[] getListSelectionListeners() {
1864         return listenerList.getListeners(ListSelectionListener.class);
1865     }
1866 
1867 
1868     /**
1869      * Sets the {@code selectionModel} for the list to a
1870      * non-{@code null ListSelectionModel}
1871      * implementation. The selection model handles the task of making single
1872      * selections, selections of contiguous ranges, and non-contiguous
1873      * selections.
1874      * <p>
1875      * This is a JavaBeans bound property.
1876      *
1877      * @param selectionModel  the {@code ListSelectionModel} that
1878      *                          implements the selections
1879      * @exception IllegalArgumentException   if {@code selectionModel}
1880      *                                          is {@code null}
1881      * @see #getSelectionModel
1882      * @beaninfo
1883      *       bound: true
1884      * description: The selection model, recording which cells are selected.
1885      */
1886     public void setSelectionModel(ListSelectionModel selectionModel) {
1887         if (selectionModel == null) {
1888             throw new IllegalArgumentException("selectionModel must be non null");
1889         }
1890 
1891         /* Remove the forwarding ListSelectionListener from the old
1892          * selectionModel, and add it to the new one, if necessary.
1893          */
1894         if (selectionListener != null) {
1895             this.selectionModel.removeListSelectionListener(selectionListener);
1896             selectionModel.addListSelectionListener(selectionListener);
1897         }
1898 
1899         ListSelectionModel oldValue = this.selectionModel;
1900         this.selectionModel = selectionModel;


2863      */
2864     public AccessibleContext getAccessibleContext() {
2865         if (accessibleContext == null) {
2866             accessibleContext = new AccessibleJList();
2867         }
2868         return accessibleContext;
2869     }
2870 
2871     /**
2872      * This class implements accessibility support for the
2873      * {@code JList} class. It provides an implementation of the
2874      * Java Accessibility API appropriate to list user-interface
2875      * elements.
2876      * <p>
2877      * <strong>Warning:</strong>
2878      * Serialized objects of this class will not be compatible with
2879      * future Swing releases. The current serialization support is
2880      * appropriate for short term storage or RMI between applications running
2881      * the same version of Swing.  As of 1.4, support for long term storage
2882      * of all JavaBeans&trade;
2883      * has been added to the {@code java.beans} package.
2884      * Please see {@link java.beans.XMLEncoder}.
2885      */
2886     @SuppressWarnings("serial") // Same-version serialization only
2887     protected class AccessibleJList extends AccessibleJComponent
2888         implements AccessibleSelection, PropertyChangeListener,
2889         ListSelectionListener, ListDataListener {
2890 
2891         int leadSelectionIndex;
2892 
2893         /**
2894          * Constructs an {@code AccessibleJList}.
2895          */
2896         public AccessibleJList() {
2897             super();
2898             JList.this.addPropertyChangeListener(this);
2899             JList.this.getSelectionModel().addListSelectionListener(this);
2900             JList.this.getModel().addListDataListener(this);
2901             leadSelectionIndex = JList.this.getLeadSelectionIndex();
2902         }
2903 


3031             AccessibleStateSet states = super.getAccessibleStateSet();
3032             if (selectionModel.getSelectionMode() !=
3033                 ListSelectionModel.SINGLE_SELECTION) {
3034                 states.add(AccessibleState.MULTISELECTABLE);
3035             }
3036             return states;
3037         }
3038 
3039         /**
3040          * Get the role of this object.
3041          *
3042          * @return an instance of AccessibleRole describing the role of the
3043          * object
3044          * @see AccessibleRole
3045          */
3046         public AccessibleRole getAccessibleRole() {
3047             return AccessibleRole.LIST;
3048         }
3049 
3050         /**
3051          * Returns the {@code Accessible} child contained at
3052          * the local coordinate {@code Point}, if one exists.
3053          * Otherwise returns {@code null}.
3054          *
3055          * @return the {@code Accessible} at the specified
3056          *    location, if it exists
3057          */
3058         public Accessible getAccessibleAt(Point p) {
3059             int i = locationToIndex(p);
3060             if (i >= 0) {
3061                 return new AccessibleJListChild(JList.this, i);
3062             } else {
3063                 return null;
3064             }
3065         }
3066 
3067         /**
3068          * Returns the number of accessible children in the object.  If all
3069          * of the children of this object implement Accessible, than this
3070          * method should return the number of children of this object.
3071          *
3072          * @return the number of accessible children in the object.
3073          */
3074         public int getAccessibleChildrenCount() {
3075             return getModel().getSize();


3101             return this;
3102         }
3103 
3104 
3105     // AccessibleSelection methods
3106 
3107         /**
3108          * Returns the number of items currently selected.
3109          * If no items are selected, the return value will be 0.
3110          *
3111          * @return the number of items currently selected.
3112          */
3113          public int getAccessibleSelectionCount() {
3114              return JList.this.getSelectedIndices().length;
3115          }
3116 
3117         /**
3118          * Returns an Accessible representing the specified selected item
3119          * in the object.  If there isn't a selection, or there are
3120          * fewer items selected than the integer passed in, the return
3121          * value will be {@code null}.
3122          *
3123          * @param i the zero-based index of selected items
3124          * @return an Accessible containing the selected item
3125          */
3126          public Accessible getAccessibleSelection(int i) {
3127              int len = getAccessibleSelectionCount();
3128              if (i < 0 || i >= len) {
3129                  return null;
3130              } else {
3131                  return getAccessibleChild(JList.this.getSelectedIndices()[i]);
3132              }
3133          }
3134 
3135         /**
3136          * Returns true if the current child of this object is selected.
3137          *
3138          * @param i the zero-based index of the child in this Accessible
3139          * object.
3140          * @see AccessibleContext#getAccessibleChild
3141          */


3708                         c.addFocusListener(l);
3709                     }
3710                 }
3711             }
3712 
3713             public void removeFocusListener(FocusListener l) {
3714                 AccessibleContext ac = getCurrentAccessibleContext();
3715                 if (ac instanceof AccessibleComponent) {
3716                     ((AccessibleComponent) ac).removeFocusListener(l);
3717                 } else {
3718                     Component c = getCurrentComponent();
3719                     if (c != null) {
3720                         c.removeFocusListener(l);
3721                     }
3722                 }
3723             }
3724 
3725             // TIGER - 4733624
3726             /**
3727              * Returns the icon for the element renderer, as the only item
3728              * of an array of {@code AccessibleIcon}s or a {@code null} array
3729              * if the renderer component contains no icons.
3730              *
3731              * @return an array containing the accessible icon
3732              *         or a {@code null} array if none
3733              * @since 1.3
3734              */
3735             public AccessibleIcon [] getAccessibleIcon() {
3736                 AccessibleContext ac = getCurrentAccessibleContext();
3737                 if (ac != null) {
3738                     return ac.getAccessibleIcon();
3739                 } else {
3740                     return null;
3741                 }
3742             }
3743         } // inner class AccessibleJListChild
3744     } // inner class AccessibleJList
3745 }
< prev index next >