5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.swing;
27
28 import java.awt.*;
29 import java.awt.event.*;
30
31 import java.util.Vector;
32 import java.util.Locale;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
36
37 import java.beans.PropertyChangeEvent;
38 import java.beans.PropertyChangeListener;
39 import java.beans.Transient;
40
41 import javax.swing.event.*;
42 import javax.accessibility.*;
43 import javax.swing.plaf.*;
44 import javax.swing.text.Position;
45
46 import java.io.ObjectOutputStream;
47 import java.io.ObjectInputStream;
48 import java.io.IOException;
49 import java.io.Serializable;
50
51 import sun.swing.SwingUtilities2;
52 import sun.swing.SwingUtilities2.Section;
53 import static sun.swing.SwingUtilities2.Section.*;
54
55
56 /**
57 * A component that displays a list of objects and allows the user to select
58 * one or more items. A separate model, {@code ListModel}, maintains the
59 * contents of the list.
60 * <p>
61 * It's easy to display an array or Vector of objects, using the {@code JList}
62 * constructor that automatically builds a read-only {@code ListModel} instance
63 * for you:
64 * <pre>
65 * {@code
66 * // Create a JList that displays strings from an array
67 *
68 * String[] data = {"one", "two", "three", "four"};
69 * JList<String> myList = new JList<String>(data);
70 *
71 * // Create a JList that displays the superclasses of JList.class, by
72 * // creating it with a Vector populated with this data
73 *
74 * Vector<Class<?>> superClasses = new Vector<Class<?>>();
75 * Class<JList> rootClass = javax.swing.JList.class;
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™
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 *
278 * @author Hans Muller
279 * @since 1.2
280 */
281 @SuppressWarnings("serial") // Same-version serialization only
282 public class JList<E> extends JComponent implements Scrollable, Accessible
283 {
284 /**
285 * @see #getUIClassID
286 * @see #readObject
287 */
288 private static final String uiClassID = "ListUI";
289
290 /**
291 * Indicates a vertical layout of cells, in a single column;
292 * the default layout.
293 * @see #setLayoutOrientation
294 * @since 1.4
295 */
296 public static final int VERTICAL = 0;
297
298 /**
299 * Indicates a "newspaper style" layout with cells flowing vertically
300 * then horizontally.
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 *
571 * @see #setPrototypeCellValue
572 * @see #setCellRenderer
573 */
574 private void updateFixedCellSize()
575 {
576 ListCellRenderer<? super E> cr = getCellRenderer();
577 E value = getPrototypeCellValue();
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 }
734
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 }
784
785
786 /**
787 * Returns the color used to draw the foreground of selected items.
788 * {@code DefaultListCellRenderer} uses this color to draw the foreground
789 * of items in the selected state, as do the renderers installed by most
790 * {@code ListUI} implementations.
801 /**
802 * Sets the color used to draw the foreground of selected items, which
803 * cell renderers can use to render text and graphics.
804 * {@code DefaultListCellRenderer} uses this color to draw the foreground
805 * of items in the selected state, as do the renderers installed by most
806 * {@code ListUI} implementations.
807 * <p>
808 * The default value of this property is defined by the look and feel
809 * implementation.
810 * <p>
811 * This is a JavaBeans bound property.
812 *
813 * @param selectionForeground the {@code Color} to use in the foreground
814 * for selected list items
815 * @see #getSelectionForeground
816 * @see #setSelectionBackground
817 * @see #setForeground
818 * @see #setBackground
819 * @see #setFont
820 * @see DefaultListCellRenderer
821 * @beaninfo
822 * bound: true
823 * attribute: visualUpdate true
824 * description: The foreground color of selected cells.
825 */
826 public void setSelectionForeground(Color selectionForeground) {
827 Color oldValue = this.selectionForeground;
828 this.selectionForeground = selectionForeground;
829 firePropertyChange("selectionForeground", oldValue, selectionForeground);
830 }
831
832
833 /**
834 * Returns the color used to draw the background of selected items.
835 * {@code DefaultListCellRenderer} uses this color to draw the background
836 * of items in the selected state, as do the renderers installed by most
837 * {@code ListUI} implementations.
838 *
839 * @return the color to draw the background of selected items
840 * @see #setSelectionBackground
841 * @see DefaultListCellRenderer
842 */
843 public Color getSelectionBackground() {
844 return selectionBackground;
845 }
848 /**
849 * Sets the color used to draw the background of selected items, which
850 * cell renderers can use fill selected cells.
851 * {@code DefaultListCellRenderer} uses this color to fill the background
852 * of items in the selected state, as do the renderers installed by most
853 * {@code ListUI} implementations.
854 * <p>
855 * The default value of this property is defined by the look
856 * and feel implementation.
857 * <p>
858 * This is a JavaBeans bound property.
859 *
860 * @param selectionBackground the {@code Color} to use for the
861 * background of selected cells
862 * @see #getSelectionBackground
863 * @see #setSelectionForeground
864 * @see #setForeground
865 * @see #setBackground
866 * @see #setFont
867 * @see DefaultListCellRenderer
868 * @beaninfo
869 * bound: true
870 * attribute: visualUpdate true
871 * description: The background color of selected cells.
872 */
873 public void setSelectionBackground(Color selectionBackground) {
874 Color oldValue = this.selectionBackground;
875 this.selectionBackground = selectionBackground;
876 firePropertyChange("selectionBackground", oldValue, selectionBackground);
877 }
878
879
880 /**
881 * Returns the value of the {@code visibleRowCount} property. See the
882 * documentation for {@link #setVisibleRowCount} for details on how to
883 * interpret this value.
884 *
885 * @return the value of the {@code visibleRowCount} property.
886 * @see #setVisibleRowCount
887 */
888 public int getVisibleRowCount() {
889 return visibleRowCount;
890 }
891
892 /**
903 * documentation for more details.
904 * <p>
905 * In {@code HORIZONTAL_WRAP} and {@code VERTICAL_WRAP} orientations:<br>
906 * This affects how cells are wrapped. See the documentation of
907 * {@link #setLayoutOrientation} for more details.
908 * <p>
909 * The default value of this property is {@code 8}.
910 * <p>
911 * Calling this method with a negative value results in the property
912 * being set to {@code 0}.
913 * <p>
914 * This is a JavaBeans bound property.
915 *
916 * @param visibleRowCount an integer specifying the preferred number of
917 * rows to display without requiring scrolling
918 * @see #getVisibleRowCount
919 * @see #getPreferredScrollableViewportSize
920 * @see #setLayoutOrientation
921 * @see JComponent#getVisibleRect
922 * @see JViewport
923 * @beaninfo
924 * bound: true
925 * attribute: visualUpdate true
926 * description: The preferred number of rows to display without
927 * requiring scrolling
928 */
929 public void setVisibleRowCount(int visibleRowCount) {
930 int oldValue = this.visibleRowCount;
931 this.visibleRowCount = Math.max(0, visibleRowCount);
932 firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
933 }
934
935
936 /**
937 * Returns the layout orientation property for the list: {@code VERTICAL}
938 * if the layout is a single column of cells, {@code VERTICAL_WRAP} if the
939 * layout is "newspaper style" with the content flowing vertically then
940 * horizontally, or {@code HORIZONTAL_WRAP} if the layout is "newspaper
941 * style" with the content flowing horizontally then vertically.
942 *
943 * @return the value of the {@code layoutOrientation} property
944 * @see #setLayoutOrientation
945 * @since 1.4
946 */
947 public int getLayoutOrientation() {
948 return layoutOrientation;
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;
1012 switch (layoutOrientation) {
1013 case VERTICAL:
1014 case VERTICAL_WRAP:
1015 case HORIZONTAL_WRAP:
1016 this.layoutOrientation = layoutOrientation;
1017 firePropertyChange("layoutOrientation", oldValue, layoutOrientation);
1018 break;
1019 default:
1020 throw new IllegalArgumentException("layoutOrientation must be one of: VERTICAL, HORIZONTAL_WRAP or VERTICAL_WRAP");
1021 }
1022 }
1023
1024
1025 /**
1026 * Returns the smallest list index that is currently visible.
1027 * In a left-to-right {@code componentOrientation}, the first visible
1028 * cell is found closest to the list's upper-left corner. In right-to-left
1029 * orientation, it is found closest to the upper-right corner.
1030 * If nothing is visible or the list is empty, {@code -1} is returned.
1031 * Note that the returned cell may only be partially visible.
1032 *
1033 * @return the index of the first visible cell
1034 * @see #getLastVisibleIndex
1035 * @see JComponent#getVisibleRect
1036 */
1037 public int getFirstVisibleIndex() {
1038 Rectangle r = getVisibleRect();
1039 int first;
1040 if (this.getComponentOrientation().isLeftToRight()) {
1041 first = locationToIndex(r.getLocation());
1042 } else {
1043 first = locationToIndex(new Point((r.x + r.width) - 1, r.y));
1044 }
1045 if (first != -1) {
1046 Rectangle bounds = getCellBounds(first, first);
1047 if (bounds != null) {
1048 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
1049 if (bounds.width == 0 || bounds.height == 0) {
1050 first = -1;
1051 }
1052 }
1053 }
1054 return first;
1055 }
1056
1057
1058 /**
1059 * Returns the largest list index that is currently visible.
1060 * If nothing is visible or the list is empty, {@code -1} is returned.
1061 * Note that the returned cell may only be partially visible.
1062 *
1063 * @return the index of the last visible cell
1064 * @see #getFirstVisibleIndex
1065 * @see JComponent#getVisibleRect
1066 */
1067 public int getLastVisibleIndex() {
1068 boolean leftToRight = this.getComponentOrientation().isLeftToRight();
1069 Rectangle r = getVisibleRect();
1070 Point lastPoint;
1071 if (leftToRight) {
1072 lastPoint = new Point((r.x + r.width) - 1, (r.y + r.height) - 1);
1073 } else {
1074 lastPoint = new Point(r.x, (r.y + r.height) - 1);
1075 }
1076 int location = locationToIndex(lastPoint);
1077
1078 if (location != -1) {
1079 Rectangle bounds = getCellBounds(location, location);
1080
1081 if (bounds != null) {
1082 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
1083 if (bounds.width == 0 || bounds.height == 0) {
1084 // Try the top left(LTR) or top right(RTL) corner, and
1085 // then go across checking each cell for HORIZONTAL_WRAP.
1086 // Try the lower left corner, and then go across checking
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,
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 }
1455
1456 /**
1457 * Returns the next list element whose {@code toString} value
1458 * starts with the given prefix.
1459 *
1460 * @param prefix the string to test for a match
1461 * @param startIndex the index for starting the search
1462 * @param bias the search direction, either
1463 * Position.Bias.Forward or Position.Bias.Backward.
1464 * @return the index of the next list element that
1465 * starts with the prefix; otherwise {@code -1}
1466 * @exception IllegalArgumentException if prefix is {@code null}
1467 * or startIndex is out of bounds
1468 * @since 1.4
1469 */
1470 public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
1471 ListModel<E> model = getModel();
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 *
1843 * Removes a selection listener from the list.
1844 *
1845 * @param listener the {@code ListSelectionListener} to remove
1846 * @see #addListSelectionListener
1847 * @see #getSelectionModel
1848 */
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;
1901 firePropertyChange("selectionModel", oldValue, selectionModel);
1902 }
1903
1904
1905 /**
1911 * <li>{@code ListSelectionModel.SINGLE_SELECTION} -
1912 * Only one list index can be selected at a time. In this mode,
1913 * {@code setSelectionInterval} and {@code addSelectionInterval} are
1914 * equivalent, both replacing the current selection with the index
1915 * represented by the second argument (the "lead").
1916 * <li>{@code ListSelectionModel.SINGLE_INTERVAL_SELECTION} -
1917 * Only one contiguous interval can be selected at a time.
1918 * In this mode, {@code addSelectionInterval} behaves like
1919 * {@code setSelectionInterval} (replacing the current selection},
1920 * unless the given interval is immediately adjacent to or overlaps
1921 * the existing selection, and can be used to grow the selection.
1922 * <li>{@code ListSelectionModel.MULTIPLE_INTERVAL_SELECTION} -
1923 * In this mode, there's no restriction on what can be selected.
1924 * This mode is the default.
1925 * </ul>
1926 *
1927 * @param selectionMode the selection mode
1928 * @see #getSelectionMode
1929 * @throws IllegalArgumentException if the selection mode isn't
1930 * one of those allowed
1931 * @beaninfo
1932 * description: The selection mode.
1933 * enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION
1934 * SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION
1935 * MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1936 */
1937 public void setSelectionMode(int selectionMode) {
1938 getSelectionModel().setSelectionMode(selectionMode);
1939 }
1940
1941 /**
1942 * Returns the current selection mode for the list. This is a cover
1943 * method that delegates to the method of the same name on the
1944 * list's selection model.
1945 *
1946 * @return the current selection mode
1947 * @see #setSelectionMode
1948 */
1949 public int getSelectionMode() {
1950 return getSelectionModel().getSelectionMode();
1951 }
1952
1953
1954 /**
1955 * Returns the anchor selection index. This is a cover method that
1956 * delegates to the method of the same name on the list's selection model.
1957 *
1958 * @return the anchor selection index
1959 * @see ListSelectionModel#getAnchorSelectionIndex
1960 */
1961 public int getAnchorSelectionIndex() {
1962 return getSelectionModel().getAnchorSelectionIndex();
1963 }
1964
1965
1966 /**
1967 * Returns the lead selection index. This is a cover method that
1968 * delegates to the method of the same name on the list's selection model.
1969 *
1970 * @return the lead selection index
1971 * @see ListSelectionModel#getLeadSelectionIndex
1972 * @beaninfo
1973 * description: The lead selection index.
1974 */
1975 public int getLeadSelectionIndex() {
1976 return getSelectionModel().getLeadSelectionIndex();
1977 }
1978
1979
1980 /**
1981 * Returns the smallest selected cell index, or {@code -1} if the selection
1982 * is empty. This is a cover method that delegates to the method of the same
1983 * name on the list's selection model.
1984 *
1985 * @return the smallest selected cell index, or {@code -1}
1986 * @see ListSelectionModel#getMinSelectionIndex
1987 */
1988 public int getMinSelectionIndex() {
1989 return getSelectionModel().getMinSelectionIndex();
1990 }
1991
1992
1993 /**
1994 * Returns the largest selected cell index, or {@code -1} if the selection
1995 * is empty. This is a cover method that delegates to the method of the same
1996 * name on the list's selection model.
1997 *
1998 * @return the largest selected cell index
1999 * @see ListSelectionModel#getMaxSelectionIndex
2000 */
2001 public int getMaxSelectionIndex() {
2002 return getSelectionModel().getMaxSelectionIndex();
2003 }
2004
2005
2006 /**
2007 * Returns {@code true} if the specified index is selected,
2008 * else {@code false}. This is a cover method that delegates to the method
2009 * of the same name on the list's selection model.
2010 *
2011 * @param index index to be queried for selection state
2012 * @return {@code true} if the specified index is selected,
2013 * else {@code false}
2014 * @see ListSelectionModel#isSelectedIndex
2015 * @see #setSelectedIndex
2016 */
2017 public boolean isSelectedIndex(int index) {
2018 return getSelectionModel().isSelectedIndex(index);
2019 }
2020
2021
2022 /**
2023 * Returns {@code true} if nothing is selected, else {@code false}.
2024 * This is a cover method that delegates to the method of the same
2025 * name on the list's selection model.
2026 *
2027 * @return {@code true} if nothing is selected, else {@code false}
2028 * @see ListSelectionModel#isSelectionEmpty
2029 * @see #clearSelection
2030 */
2031 public boolean isSelectionEmpty() {
2032 return getSelectionModel().isSelectionEmpty();
2033 }
2034
2035
2036 /**
2037 * Clears the selection; after calling this method, {@code isSelectionEmpty}
2038 * will return {@code true}. This is a cover method that delegates to the
2039 * method of the same name on the list's selection model.
2040 *
2041 * @see ListSelectionModel#clearSelection
2042 * @see #isSelectionEmpty
2043 */
2044 public void clearSelection() {
2045 getSelectionModel().clearSelection();
2046 }
2047
2048
2049 /**
2050 * Selects the specified interval. Both {@code anchor} and {@code lead}
2185 rvTmp[n++] = i;
2186 }
2187 }
2188 int[] rv = new int[n];
2189 System.arraycopy(rvTmp, 0, rv, 0, n);
2190 return rv;
2191 }
2192
2193
2194 /**
2195 * Selects a single cell. Does nothing if the given index is greater
2196 * than or equal to the model size. This is a convenience method that uses
2197 * {@code setSelectionInterval} on the selection model. Refer to the
2198 * documentation for the selection model class being used for details on
2199 * how values less than {@code 0} are handled.
2200 *
2201 * @param index the index of the cell to select
2202 * @see ListSelectionModel#setSelectionInterval
2203 * @see #isSelectedIndex
2204 * @see #addListSelectionListener
2205 * @beaninfo
2206 * description: The index of the selected cell.
2207 */
2208 public void setSelectedIndex(int index) {
2209 if (index >= getModel().getSize()) {
2210 return;
2211 }
2212 getSelectionModel().setSelectionInterval(index, index);
2213 }
2214
2215
2216 /**
2217 * Changes the selection to be the set of indices specified by the given
2218 * array. Indices greater than or equal to the model size are ignored.
2219 * This is a convenience method that clears the selection and then uses
2220 * {@code addSelectionInterval} on the selection model to add the indices.
2221 * Refer to the documentation of the selection model class being used for
2222 * details on how values less than {@code 0} are handled.
2223 *
2224 * @param indices an array of the indices of the cells to select,
2225 * {@code non-null}
2226 * @see ListSelectionModel#addSelectionInterval
2227 * @see #isSelectedIndex
2235 for (int i : indices) {
2236 if (i < size) {
2237 sm.addSelectionInterval(i, i);
2238 }
2239 }
2240 }
2241
2242
2243 /**
2244 * Returns an array of all the selected values, in increasing order based
2245 * on their indices in the list.
2246 *
2247 * @return the selected values, or an empty array if nothing is selected
2248 * @see #isSelectedIndex
2249 * @see #getModel
2250 * @see #addListSelectionListener
2251 *
2252 * @deprecated As of JDK 1.7, replaced by {@link #getSelectedValuesList()}
2253 */
2254 @Deprecated
2255 public Object[] getSelectedValues() {
2256 ListSelectionModel sm = getSelectionModel();
2257 ListModel<E> dm = getModel();
2258
2259 int iMin = sm.getMinSelectionIndex();
2260 int iMax = sm.getMaxSelectionIndex();
2261
2262 if ((iMin < 0) || (iMax < 0)) {
2263 return new Object[0];
2264 }
2265
2266 Object[] rvTmp = new Object[1+ (iMax - iMin)];
2267 int n = 0;
2268 for(int i = iMin; i <= iMax; i++) {
2269 if (sm.isSelectedIndex(i)) {
2270 rvTmp[n++] = dm.getElementAt(i);
2271 }
2272 }
2273 Object[] rv = new Object[n];
2274 System.arraycopy(rvTmp, 0, rv, 0, n);
2275 return rv;
2276 }
2277
2278 /**
2279 * Returns a list of all the selected items, in increasing order based
2280 * on their indices in the list.
2281 *
2282 * @return the selected items, or an empty list if nothing is selected
2283 * @see #isSelectedIndex
2284 * @see #getModel
2285 * @see #addListSelectionListener
2286 *
2287 * @since 1.7
2288 */
2289 public List<E> getSelectedValuesList() {
2290 ListSelectionModel sm = getSelectionModel();
2291 ListModel<E> dm = getModel();
2292
2293 int iMin = sm.getMinSelectionIndex();
2294 int iMax = sm.getMaxSelectionIndex();
2295
2296 if ((iMin < 0) || (iMax < 0)) {
2297 return Collections.emptyList();
2298 }
2299
2300 List<E> selectedItems = new ArrayList<E>();
2301 for(int i = iMin; i <= iMax; i++) {
2302 if (sm.isSelectedIndex(i)) {
2303 selectedItems.add(dm.getElementAt(i));
2304 }
2305 }
2306 return selectedItems;
2307 }
2308
2321 */
2322 public int getSelectedIndex() {
2323 return getMinSelectionIndex();
2324 }
2325
2326
2327 /**
2328 * Returns the value for the smallest selected cell index;
2329 * <i>the selected value</i> when only a single item is selected in the
2330 * list. When multiple items are selected, it is simply the value for the
2331 * smallest selected index. Returns {@code null} if there is no selection.
2332 * <p>
2333 * This is a convenience method that simply returns the model value for
2334 * {@code getMinSelectionIndex}.
2335 *
2336 * @return the first selected value
2337 * @see #getMinSelectionIndex
2338 * @see #getModel
2339 * @see #addListSelectionListener
2340 */
2341 public E getSelectedValue() {
2342 int i = getMinSelectionIndex();
2343 return (i == -1) ? null : getModel().getElementAt(i);
2344 }
2345
2346
2347 /**
2348 * Selects the specified object from the list.
2349 *
2350 * @param anObject the object to select
2351 * @param shouldScroll {@code true} if the list should scroll to display
2352 * the selected object, if one exists; otherwise {@code false}
2353 */
2354 public void setSelectedValue(Object anObject,boolean shouldScroll) {
2355 if(anObject == null)
2356 setSelectedIndex(-1);
2357 else if(!anObject.equals(getSelectedValue())) {
2358 int i,c;
2359 ListModel<E> dm = getModel();
2360 for(i=0,c=dm.getSize();i<c;i++)
2410 * by {@code visibleRowCount}, if {@code fixedCellHeight} is greater than
2411 * {@code 0}, otherwise it is a hard-coded value of {@code 16} multiplied by
2412 * {@code visibleRowCount}.
2413 * <p>
2414 * If the model isn't empty, the width is the preferred size's width,
2415 * typically the width of the widest list element. The height is the
2416 * {@code fixedCellHeight} multiplied by the {@code visibleRowCount},
2417 * plus the list's vertical insets.
2418 * <p>
2419 * <b>{@code VERTICAL_WRAP} or {@code HORIZONTAL_WRAP}:</b>
2420 * <br>
2421 * This method simply returns the value from {@code getPreferredSize}.
2422 * The list's {@code ListUI} is expected to override {@code getPreferredSize}
2423 * to return an appropriate value.
2424 *
2425 * @return a dimension containing the size of the viewport needed
2426 * to display {@code visibleRowCount} rows
2427 * @see #getPreferredScrollableViewportSize
2428 * @see #setPrototypeCellValue
2429 */
2430 public Dimension getPreferredScrollableViewportSize()
2431 {
2432 if (getLayoutOrientation() != VERTICAL) {
2433 return getPreferredSize();
2434 }
2435 Insets insets = getInsets();
2436 int dx = insets.left + insets.right;
2437 int dy = insets.top + insets.bottom;
2438
2439 int visibleRowCount = getVisibleRowCount();
2440 int fixedCellWidth = getFixedCellWidth();
2441 int fixedCellHeight = getFixedCellHeight();
2442
2443 if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
2444 int width = fixedCellWidth + dx;
2445 int height = (visibleRowCount * fixedCellHeight) + dy;
2446 return new Dimension(width, height);
2447 }
2448 else if (getModel().getSize() > 0) {
2449 int width = getPreferredSize().width;
2747 return inc;
2748 }
2749 return visibleRect.width;
2750 }
2751
2752
2753 /**
2754 * Returns {@code true} if this {@code JList} is displayed in a
2755 * {@code JViewport} and the viewport is wider than the list's
2756 * preferred width, or if the layout orientation is {@code HORIZONTAL_WRAP}
2757 * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2758 * <p>
2759 * If {@code false}, then don't track the viewport's width. This allows
2760 * horizontal scrolling if the {@code JViewport} is itself embedded in a
2761 * {@code JScrollPane}.
2762 *
2763 * @return whether or not an enclosing viewport should force the list's
2764 * width to match its own
2765 * @see Scrollable#getScrollableTracksViewportWidth
2766 */
2767 public boolean getScrollableTracksViewportWidth() {
2768 if (getLayoutOrientation() == HORIZONTAL_WRAP &&
2769 getVisibleRowCount() <= 0) {
2770 return true;
2771 }
2772 Container parent = SwingUtilities.getUnwrappedParent(this);
2773 if (parent instanceof JViewport) {
2774 return parent.getWidth() > getPreferredSize().width;
2775 }
2776 return false;
2777 }
2778
2779 /**
2780 * Returns {@code true} if this {@code JList} is displayed in a
2781 * {@code JViewport} and the viewport is taller than the list's
2782 * preferred height, or if the layout orientation is {@code VERTICAL_WRAP}
2783 * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2784 * <p>
2785 * If {@code false}, then don't track the viewport's height. This allows
2786 * vertical scrolling if the {@code JViewport} is itself embedded in a
2787 * {@code JScrollPane}.
2788 *
2789 * @return whether or not an enclosing viewport should force the list's
2790 * height to match its own
2791 * @see Scrollable#getScrollableTracksViewportHeight
2792 */
2793 public boolean getScrollableTracksViewportHeight() {
2794 if (getLayoutOrientation() == VERTICAL_WRAP &&
2795 getVisibleRowCount() <= 0) {
2796 return true;
2797 }
2798 Container parent = SwingUtilities.getUnwrappedParent(this);
2799 if (parent instanceof JViewport) {
2800 return parent.getHeight() > getPreferredSize().height;
2801 }
2802 return false;
2803 }
2804
2805
2806 /*
2807 * See {@code readObject} and {@code writeObject} in {@code JComponent}
2808 * for more information about serialization in Swing.
2809 */
2810 private void writeObject(ObjectOutputStream s) throws IOException {
2811 s.defaultWriteObject();
2812 if (getUIClassID().equals(uiClassID)) {
2844 ",selectionForeground=" + selectionForegroundString +
2845 ",visibleRowCount=" + visibleRowCount +
2846 ",layoutOrientation=" + layoutOrientation;
2847 }
2848
2849
2850 /**
2851 * --- Accessibility Support ---
2852 */
2853
2854 /**
2855 * Gets the {@code AccessibleContext} associated with this {@code JList}.
2856 * For {@code JList}, the {@code AccessibleContext} takes the form of an
2857 * {@code AccessibleJList}.
2858 * <p>
2859 * A new {@code AccessibleJList} instance is created if necessary.
2860 *
2861 * @return an {@code AccessibleJList} that serves as the
2862 * {@code AccessibleContext} of this {@code JList}
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™
2883 * has been added to the <code>java.beans</code> package.
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package javax.swing;
26
27 import java.awt.*;
28 import java.awt.event.*;
29
30 import java.util.Vector;
31 import java.util.Locale;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.List;
35
36 import java.beans.JavaBean;
37 import java.beans.BeanProperty;
38 import java.beans.PropertyChangeEvent;
39 import java.beans.PropertyChangeListener;
40 import java.beans.Transient;
41
42 import javax.swing.event.*;
43 import javax.accessibility.*;
44 import javax.swing.plaf.*;
45 import javax.swing.text.Position;
46
47 import java.io.ObjectOutputStream;
48 import java.io.IOException;
49 import java.io.Serializable;
50
51 import sun.swing.SwingUtilities2;
52 import sun.swing.SwingUtilities2.Section;
53 import static sun.swing.SwingUtilities2.Section.*;
54
55 /**
56 * A component that displays a list of objects and allows the user to select
57 * one or more items. A separate model, {@code ListModel}, maintains the
58 * contents of the list.
59 * <p>
60 * It's easy to display an array or Vector of objects, using the {@code JList}
61 * constructor that automatically builds a read-only {@code ListModel} instance
62 * for you:
63 * <pre>
64 * {@code
65 * // Create a JList that displays strings from an array
66 *
67 * String[] data = {"one", "two", "three", "four"};
68 * JList<String> myList = new JList<String>(data);
69 *
70 * // Create a JList that displays the superclasses of JList.class, by
71 * // creating it with a Vector populated with this data
72 *
73 * Vector<Class<?>> superClasses = new Vector<Class<?>>();
74 * Class<JList> rootClass = javax.swing.JList.class;
253 * appropriate for short term storage or RMI between applications running
254 * the same version of Swing. As of 1.4, support for long term storage
255 * of all JavaBeans™
256 * has been added to the <code>java.beans</code> package.
257 * Please see {@link java.beans.XMLEncoder}.
258 * <p>
259 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/list.html">How to Use Lists</a>
260 * in <a href="http://docs.oracle.com/javase/tutorial/"><em>The Java Tutorial</em></a>
261 * for further documentation.
262 *
263 * @see ListModel
264 * @see AbstractListModel
265 * @see DefaultListModel
266 * @see ListSelectionModel
267 * @see DefaultListSelectionModel
268 * @see ListCellRenderer
269 * @see DefaultListCellRenderer
270 *
271 * @param <E> the type of the elements of this list
272 *
273 * @author Hans Muller
274 * @since 1.2
275 */
276 @JavaBean(defaultProperty = "UI", description = "A component which allows for the selection of one or more objects from a list.")
277 @SwingContainer(false)
278 @SuppressWarnings("serial") // Same-version serialization only
279 public class JList<E> extends JComponent implements Scrollable, Accessible
280 {
281 /**
282 * @see #getUIClassID
283 * @see #readObject
284 */
285 private static final String uiClassID = "ListUI";
286
287 /**
288 * Indicates a vertical layout of cells, in a single column;
289 * the default layout.
290 * @see #setLayoutOrientation
291 * @since 1.4
292 */
293 public static final int VERTICAL = 0;
294
295 /**
296 * Indicates a "newspaper style" layout with cells flowing vertically
297 * then horizontally.
495 }
496
497
498 /**
499 * Returns the {@code ListUI}, the look and feel object that
500 * renders this component.
501 *
502 * @return the <code>ListUI</code> object that renders this component
503 */
504 public ListUI getUI() {
505 return (ListUI)ui;
506 }
507
508
509 /**
510 * Sets the {@code ListUI}, the look and feel object that
511 * renders this component.
512 *
513 * @param ui the <code>ListUI</code> object
514 * @see UIDefaults#getUI
515 */
516 @BeanProperty(hidden = true, visualUpdate = true, description
517 = "The UI object that implements the Component's LookAndFeel.")
518 public void setUI(ListUI ui) {
519 super.setUI(ui);
520 }
521
522
523 /**
524 * Resets the {@code ListUI} property by setting it to the value provided
525 * by the current look and feel. If the current cell renderer was installed
526 * by the developer (rather than the look and feel itself), this also causes
527 * the cell renderer and its children to be updated, by calling
528 * {@code SwingUtilities.updateComponentTreeUI} on it.
529 *
530 * @see UIManager#getUI
531 * @see SwingUtilities#updateComponentTreeUI
532 */
533 public void updateUI() {
534 setUI((ListUI)UIManager.getUI(this));
535
536 ListCellRenderer<? super E> renderer = getCellRenderer();
537 if (renderer instanceof Component) {
538 SwingUtilities.updateComponentTreeUI((Component)renderer);
539 }
540 }
541
542
543 /**
544 * Returns {@code "ListUI"}, the <code>UIDefaults</code> key used to look
545 * up the name of the {@code javax.swing.plaf.ListUI} class that defines
546 * the look and feel for this component.
547 *
548 * @return the string "ListUI"
549 * @see JComponent#getUIClassID
550 * @see UIDefaults#getUI
551 */
552 @BeanProperty(bound = false)
553 public String getUIClassID() {
554 return uiClassID;
555 }
556
557
558 /* -----private-----
559 * This method is called by setPrototypeCellValue and setCellRenderer
560 * to update the fixedCellWidth and fixedCellHeight properties from the
561 * current value of prototypeCellValue (if it's non null).
562 * <p>
563 * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
564 * generate PropertyChangeEvents for them.
565 *
566 * @see #setPrototypeCellValue
567 * @see #setCellRenderer
568 */
569 private void updateFixedCellSize()
570 {
571 ListCellRenderer<? super E> cr = getCellRenderer();
572 E value = getPrototypeCellValue();
618 * <p>
619 * While all three of the {@code prototypeCellValue},
620 * {@code fixedCellHeight}, and {@code fixedCellWidth} properties may be
621 * modified by this method, {@code PropertyChangeEvent} notifications are
622 * only sent when the {@code prototypeCellValue} property changes.
623 * <p>
624 * To see an example which sets this property, see the
625 * <a href="#prototype_example">class description</a> above.
626 * <p>
627 * The default value of this property is <code>null</code>.
628 * <p>
629 * This is a JavaBeans bound property.
630 *
631 * @param prototypeCellValue the value on which to base
632 * <code>fixedCellWidth</code> and
633 * <code>fixedCellHeight</code>
634 * @see #getPrototypeCellValue
635 * @see #setFixedCellWidth
636 * @see #setFixedCellHeight
637 * @see JComponent#addPropertyChangeListener
638 */
639 @BeanProperty(visualUpdate = true, description
640 = "The cell prototype value, used to compute cell width and height.")
641 public void setPrototypeCellValue(E prototypeCellValue) {
642 E oldValue = this.prototypeCellValue;
643 this.prototypeCellValue = prototypeCellValue;
644
645 /* If the prototypeCellValue has changed and is non-null,
646 * then recompute fixedCellWidth and fixedCellHeight.
647 */
648
649 if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
650 updateFixedCellSize();
651 }
652
653 firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
654 }
655
656
657 /**
658 * Returns the value of the {@code fixedCellWidth} property.
659 *
660 * @return the fixed cell width
661 * @see #setFixedCellWidth
662 */
663 public int getFixedCellWidth() {
664 return fixedCellWidth;
665 }
666
667 /**
668 * Sets a fixed value to be used for the width of every cell in the list.
669 * If {@code width} is -1, cell widths are computed in the {@code ListUI}
670 * by applying <code>getPreferredSize</code> to the cell renderer component
671 * for each list element.
672 * <p>
673 * The default value of this property is {@code -1}.
674 * <p>
675 * This is a JavaBeans bound property.
676 *
677 * @param width the width to be used for all cells in the list
678 * @see #setPrototypeCellValue
679 * @see #setFixedCellWidth
680 * @see JComponent#addPropertyChangeListener
681 */
682 @BeanProperty(visualUpdate = true, description
683 = "Defines a fixed cell width when greater than zero.")
684 public void setFixedCellWidth(int width) {
685 int oldValue = fixedCellWidth;
686 fixedCellWidth = width;
687 firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
688 }
689
690
691 /**
692 * Returns the value of the {@code fixedCellHeight} property.
693 *
694 * @return the fixed cell height
695 * @see #setFixedCellHeight
696 */
697 public int getFixedCellHeight() {
698 return fixedCellHeight;
699 }
700
701 /**
702 * Sets a fixed value to be used for the height of every cell in the list.
703 * If {@code height} is -1, cell heights are computed in the {@code ListUI}
704 * by applying <code>getPreferredSize</code> to the cell renderer component
705 * for each list element.
706 * <p>
707 * The default value of this property is {@code -1}.
708 * <p>
709 * This is a JavaBeans bound property.
710 *
711 * @param height the height to be used for all cells in the list
712 * @see #setPrototypeCellValue
713 * @see #setFixedCellWidth
714 * @see JComponent#addPropertyChangeListener
715 */
716 @BeanProperty(visualUpdate = true, description
717 = "Defines a fixed cell height when greater than zero.")
718 public void setFixedCellHeight(int height) {
719 int oldValue = fixedCellHeight;
720 fixedCellHeight = height;
721 firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
722 }
723
724
725 /**
726 * Returns the object responsible for painting list items.
727 *
728 * @return the value of the {@code cellRenderer} property
729 * @see #setCellRenderer
730 */
731 @Transient
732 public ListCellRenderer<? super E> getCellRenderer() {
733 return cellRenderer;
734 }
735
736 /**
737 * Sets the delegate that is used to paint each cell in the list.
738 * The job of a cell renderer is discussed in detail in the
739 * <a href="#renderer">class level documentation</a>.
740 * <p>
741 * If the {@code prototypeCellValue} property is {@code non-null},
742 * setting the cell renderer also causes the {@code fixedCellWidth} and
743 * {@code fixedCellHeight} properties to be re-calculated. Only one
744 * <code>PropertyChangeEvent</code> is generated however -
745 * for the <code>cellRenderer</code> property.
746 * <p>
747 * The default value of this property is provided by the {@code ListUI}
748 * delegate, i.e. by the look and feel implementation.
749 * <p>
750 * This is a JavaBeans bound property.
751 *
752 * @param cellRenderer the <code>ListCellRenderer</code>
753 * that paints list cells
754 * @see #getCellRenderer
755 */
756 @BeanProperty(visualUpdate = true, description
757 = "The component used to draw the cells.")
758 public void setCellRenderer(ListCellRenderer<? super E> cellRenderer) {
759 ListCellRenderer<? super E> oldValue = this.cellRenderer;
760 this.cellRenderer = cellRenderer;
761
762 /* If the cellRenderer has changed and prototypeCellValue
763 * was set, then recompute fixedCellWidth and fixedCellHeight.
764 */
765 if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
766 updateFixedCellSize();
767 }
768
769 firePropertyChange("cellRenderer", oldValue, cellRenderer);
770 }
771
772
773 /**
774 * Returns the color used to draw the foreground of selected items.
775 * {@code DefaultListCellRenderer} uses this color to draw the foreground
776 * of items in the selected state, as do the renderers installed by most
777 * {@code ListUI} implementations.
788 /**
789 * Sets the color used to draw the foreground of selected items, which
790 * cell renderers can use to render text and graphics.
791 * {@code DefaultListCellRenderer} uses this color to draw the foreground
792 * of items in the selected state, as do the renderers installed by most
793 * {@code ListUI} implementations.
794 * <p>
795 * The default value of this property is defined by the look and feel
796 * implementation.
797 * <p>
798 * This is a JavaBeans bound property.
799 *
800 * @param selectionForeground the {@code Color} to use in the foreground
801 * for selected list items
802 * @see #getSelectionForeground
803 * @see #setSelectionBackground
804 * @see #setForeground
805 * @see #setBackground
806 * @see #setFont
807 * @see DefaultListCellRenderer
808 */
809 @BeanProperty(visualUpdate = true, description
810 = "The foreground color of selected cells.")
811 public void setSelectionForeground(Color selectionForeground) {
812 Color oldValue = this.selectionForeground;
813 this.selectionForeground = selectionForeground;
814 firePropertyChange("selectionForeground", oldValue, selectionForeground);
815 }
816
817
818 /**
819 * Returns the color used to draw the background of selected items.
820 * {@code DefaultListCellRenderer} uses this color to draw the background
821 * of items in the selected state, as do the renderers installed by most
822 * {@code ListUI} implementations.
823 *
824 * @return the color to draw the background of selected items
825 * @see #setSelectionBackground
826 * @see DefaultListCellRenderer
827 */
828 public Color getSelectionBackground() {
829 return selectionBackground;
830 }
833 /**
834 * Sets the color used to draw the background of selected items, which
835 * cell renderers can use fill selected cells.
836 * {@code DefaultListCellRenderer} uses this color to fill the background
837 * of items in the selected state, as do the renderers installed by most
838 * {@code ListUI} implementations.
839 * <p>
840 * The default value of this property is defined by the look
841 * and feel implementation.
842 * <p>
843 * This is a JavaBeans bound property.
844 *
845 * @param selectionBackground the {@code Color} to use for the
846 * background of selected cells
847 * @see #getSelectionBackground
848 * @see #setSelectionForeground
849 * @see #setForeground
850 * @see #setBackground
851 * @see #setFont
852 * @see DefaultListCellRenderer
853 */
854 @BeanProperty(visualUpdate = true, description
855 = "The background color of selected cells.")
856 public void setSelectionBackground(Color selectionBackground) {
857 Color oldValue = this.selectionBackground;
858 this.selectionBackground = selectionBackground;
859 firePropertyChange("selectionBackground", oldValue, selectionBackground);
860 }
861
862
863 /**
864 * Returns the value of the {@code visibleRowCount} property. See the
865 * documentation for {@link #setVisibleRowCount} for details on how to
866 * interpret this value.
867 *
868 * @return the value of the {@code visibleRowCount} property.
869 * @see #setVisibleRowCount
870 */
871 public int getVisibleRowCount() {
872 return visibleRowCount;
873 }
874
875 /**
886 * documentation for more details.
887 * <p>
888 * In {@code HORIZONTAL_WRAP} and {@code VERTICAL_WRAP} orientations:<br>
889 * This affects how cells are wrapped. See the documentation of
890 * {@link #setLayoutOrientation} for more details.
891 * <p>
892 * The default value of this property is {@code 8}.
893 * <p>
894 * Calling this method with a negative value results in the property
895 * being set to {@code 0}.
896 * <p>
897 * This is a JavaBeans bound property.
898 *
899 * @param visibleRowCount an integer specifying the preferred number of
900 * rows to display without requiring scrolling
901 * @see #getVisibleRowCount
902 * @see #getPreferredScrollableViewportSize
903 * @see #setLayoutOrientation
904 * @see JComponent#getVisibleRect
905 * @see JViewport
906 */
907 @BeanProperty(visualUpdate = true, description
908 = "The preferred number of rows to display without requiring scrolling")
909 public void setVisibleRowCount(int visibleRowCount) {
910 int oldValue = this.visibleRowCount;
911 this.visibleRowCount = Math.max(0, visibleRowCount);
912 firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
913 }
914
915
916 /**
917 * Returns the layout orientation property for the list: {@code VERTICAL}
918 * if the layout is a single column of cells, {@code VERTICAL_WRAP} if the
919 * layout is "newspaper style" with the content flowing vertically then
920 * horizontally, or {@code HORIZONTAL_WRAP} if the layout is "newspaper
921 * style" with the content flowing horizontally then vertically.
922 *
923 * @return the value of the {@code layoutOrientation} property
924 * @see #setLayoutOrientation
925 * @since 1.4
926 */
927 public int getLayoutOrientation() {
928 return layoutOrientation;
962 * list; otherwise wrapping is done in such a way as to ensure
963 * {@code visibleRowCount} rows in the list.
964 * <tr><td><code>VERTICAL_WRAP</code>
965 * <td>Cells are layed out vertically, wrapping to a new column as
966 * necessary. If the {@code visibleRowCount} property is less than
967 * or equal to zero, wrapping is determined by the height of the
968 * list; otherwise wrapping is done at {@code visibleRowCount} rows.
969 * </table>
970 * <p>
971 * The default value of this property is <code>VERTICAL</code>.
972 *
973 * @param layoutOrientation the new layout orientation, one of:
974 * {@code VERTICAL}, {@code HORIZONTAL_WRAP} or {@code VERTICAL_WRAP}
975 * @see #getLayoutOrientation
976 * @see #setVisibleRowCount
977 * @see #getScrollableTracksViewportHeight
978 * @see #getScrollableTracksViewportWidth
979 * @throws IllegalArgumentException if {@code layoutOrientation} isn't one of the
980 * allowable values
981 * @since 1.4
982 */
983 @BeanProperty(visualUpdate = true, enumerationValues = {
984 "JList.VERTICAL",
985 "JList.HORIZONTAL_WRAP",
986 "JList.VERTICAL_WRAP"}, description
987 = "Defines the way list cells are layed out.")
988 public void setLayoutOrientation(int layoutOrientation) {
989 int oldValue = this.layoutOrientation;
990 switch (layoutOrientation) {
991 case VERTICAL:
992 case VERTICAL_WRAP:
993 case HORIZONTAL_WRAP:
994 this.layoutOrientation = layoutOrientation;
995 firePropertyChange("layoutOrientation", oldValue, layoutOrientation);
996 break;
997 default:
998 throw new IllegalArgumentException("layoutOrientation must be one of: VERTICAL, HORIZONTAL_WRAP or VERTICAL_WRAP");
999 }
1000 }
1001
1002
1003 /**
1004 * Returns the smallest list index that is currently visible.
1005 * In a left-to-right {@code componentOrientation}, the first visible
1006 * cell is found closest to the list's upper-left corner. In right-to-left
1007 * orientation, it is found closest to the upper-right corner.
1008 * If nothing is visible or the list is empty, {@code -1} is returned.
1009 * Note that the returned cell may only be partially visible.
1010 *
1011 * @return the index of the first visible cell
1012 * @see #getLastVisibleIndex
1013 * @see JComponent#getVisibleRect
1014 */
1015 @BeanProperty(bound = false)
1016 public int getFirstVisibleIndex() {
1017 Rectangle r = getVisibleRect();
1018 int first;
1019 if (this.getComponentOrientation().isLeftToRight()) {
1020 first = locationToIndex(r.getLocation());
1021 } else {
1022 first = locationToIndex(new Point((r.x + r.width) - 1, r.y));
1023 }
1024 if (first != -1) {
1025 Rectangle bounds = getCellBounds(first, first);
1026 if (bounds != null) {
1027 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
1028 if (bounds.width == 0 || bounds.height == 0) {
1029 first = -1;
1030 }
1031 }
1032 }
1033 return first;
1034 }
1035
1036
1037 /**
1038 * Returns the largest list index that is currently visible.
1039 * If nothing is visible or the list is empty, {@code -1} is returned.
1040 * Note that the returned cell may only be partially visible.
1041 *
1042 * @return the index of the last visible cell
1043 * @see #getFirstVisibleIndex
1044 * @see JComponent#getVisibleRect
1045 */
1046 @BeanProperty(bound = false)
1047 public int getLastVisibleIndex() {
1048 boolean leftToRight = this.getComponentOrientation().isLeftToRight();
1049 Rectangle r = getVisibleRect();
1050 Point lastPoint;
1051 if (leftToRight) {
1052 lastPoint = new Point((r.x + r.width) - 1, (r.y + r.height) - 1);
1053 } else {
1054 lastPoint = new Point(r.x, (r.y + r.height) - 1);
1055 }
1056 int location = locationToIndex(lastPoint);
1057
1058 if (location != -1) {
1059 Rectangle bounds = getCellBounds(location, location);
1060
1061 if (bounds != null) {
1062 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
1063 if (bounds.width == 0 || bounds.height == 0) {
1064 // Try the top left(LTR) or top right(RTL) corner, and
1065 // then go across checking each cell for HORIZONTAL_WRAP.
1066 // Try the lower left corner, and then go across checking
1143 * {@code ListUI}. When automatic drag handling is enabled, most look and
1144 * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1145 * drag and drop operation whenever the user presses the mouse button over
1146 * an item and then moves the mouse a few pixels. Setting this property to
1147 * {@code true} can therefore have a subtle effect on how selections behave.
1148 * <p>
1149 * If a look and feel is used that ignores this property, you can still
1150 * begin a drag and drop operation by calling {@code exportAsDrag} on the
1151 * list's {@code TransferHandler}.
1152 *
1153 * @param b whether or not to enable automatic drag handling
1154 * @exception HeadlessException if
1155 * <code>b</code> is <code>true</code> and
1156 * <code>GraphicsEnvironment.isHeadless()</code>
1157 * returns <code>true</code>
1158 * @see java.awt.GraphicsEnvironment#isHeadless
1159 * @see #getDragEnabled
1160 * @see #setTransferHandler
1161 * @see TransferHandler
1162 * @since 1.4
1163 */
1164 @BeanProperty(bound = false, description
1165 = "determines whether automatic drag handling is enabled")
1166 public void setDragEnabled(boolean b) {
1167 if (b && GraphicsEnvironment.isHeadless()) {
1168 throw new HeadlessException();
1169 }
1170 dragEnabled = b;
1171 }
1172
1173 /**
1174 * Returns whether or not automatic drag handling is enabled.
1175 *
1176 * @return the value of the {@code dragEnabled} property
1177 * @see #setDragEnabled
1178 * @since 1.4
1179 */
1180 public boolean getDragEnabled() {
1181 return dragEnabled;
1182 }
1183
1184 /**
1185 * Sets the drop mode for this component. For backward compatibility,
1410 * This method is not meant for querying the drop location
1411 * from a {@code TransferHandler}, as the drop location is only
1412 * set after the {@code TransferHandler}'s <code>canImport</code>
1413 * has returned and has allowed for the location to be shown.
1414 * <p>
1415 * When this property changes, a property change event with
1416 * name "dropLocation" is fired by the component.
1417 * <p>
1418 * By default, responsibility for listening for changes to this property
1419 * and indicating the drop location visually lies with the list's
1420 * {@code ListUI}, which may paint it directly and/or install a cell
1421 * renderer to do so. Developers wishing to implement custom drop location
1422 * painting and/or replace the default cell renderer, may need to honor
1423 * this property.
1424 *
1425 * @return the drop location
1426 * @see #setDropMode
1427 * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1428 * @since 1.6
1429 */
1430 @BeanProperty(bound = false)
1431 public final DropLocation getDropLocation() {
1432 return dropLocation;
1433 }
1434
1435 /**
1436 * Returns the next list element whose {@code toString} value
1437 * starts with the given prefix.
1438 *
1439 * @param prefix the string to test for a match
1440 * @param startIndex the index for starting the search
1441 * @param bias the search direction, either
1442 * Position.Bias.Forward or Position.Bias.Backward.
1443 * @return the index of the next list element that
1444 * starts with the prefix; otherwise {@code -1}
1445 * @exception IllegalArgumentException if prefix is {@code null}
1446 * or startIndex is out of bounds
1447 * @since 1.4
1448 */
1449 public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
1450 ListModel<E> model = getModel();
1626 * list of items
1627 * @see #setModel
1628 */
1629 public ListModel<E> getModel() {
1630 return dataModel;
1631 }
1632
1633 /**
1634 * Sets the model that represents the contents or "value" of the
1635 * list, notifies property change listeners, and then clears the
1636 * list's selection.
1637 * <p>
1638 * This is a JavaBeans bound property.
1639 *
1640 * @param model the <code>ListModel</code> that provides the
1641 * list of items for display
1642 * @exception IllegalArgumentException if <code>model</code> is
1643 * <code>null</code>
1644 * @see #getModel
1645 * @see #clearSelection
1646 */
1647 @BeanProperty(visualUpdate = true, description
1648 = "The object that contains the data to be drawn by this JList.")
1649 public void setModel(ListModel<E> model) {
1650 if (model == null) {
1651 throw new IllegalArgumentException("model must be non null");
1652 }
1653 ListModel<E> oldValue = dataModel;
1654 dataModel = model;
1655 firePropertyChange("model", oldValue, dataModel);
1656 clearSelection();
1657 }
1658
1659
1660 /**
1661 * Constructs a read-only <code>ListModel</code> from an array of items,
1662 * and calls {@code setModel} with this model.
1663 * <p>
1664 * Attempts to pass a {@code null} value to this method results in
1665 * undefined behavior and, most likely, exceptions. The created model
1666 * references the given array directly. Attempts to modify the array
1667 * after invoking this method results in undefined behavior.
1668 *
1820 * Removes a selection listener from the list.
1821 *
1822 * @param listener the {@code ListSelectionListener} to remove
1823 * @see #addListSelectionListener
1824 * @see #getSelectionModel
1825 */
1826 public void removeListSelectionListener(ListSelectionListener listener) {
1827 listenerList.remove(ListSelectionListener.class, listener);
1828 }
1829
1830
1831 /**
1832 * Returns an array of all the {@code ListSelectionListener}s added
1833 * to this {@code JList} by way of {@code addListSelectionListener}.
1834 *
1835 * @return all of the {@code ListSelectionListener}s on this list, or
1836 * an empty array if no listeners have been added
1837 * @see #addListSelectionListener
1838 * @since 1.4
1839 */
1840 @BeanProperty(bound = false)
1841 public ListSelectionListener[] getListSelectionListeners() {
1842 return listenerList.getListeners(ListSelectionListener.class);
1843 }
1844
1845
1846 /**
1847 * Sets the <code>selectionModel</code> for the list to a
1848 * non-<code>null</code> <code>ListSelectionModel</code>
1849 * implementation. The selection model handles the task of making single
1850 * selections, selections of contiguous ranges, and non-contiguous
1851 * selections.
1852 * <p>
1853 * This is a JavaBeans bound property.
1854 *
1855 * @param selectionModel the <code>ListSelectionModel</code> that
1856 * implements the selections
1857 * @exception IllegalArgumentException if <code>selectionModel</code>
1858 * is <code>null</code>
1859 * @see #getSelectionModel
1860 */
1861 @BeanProperty(description
1862 = "The selection model, recording which cells are selected.")
1863 public void setSelectionModel(ListSelectionModel selectionModel) {
1864 if (selectionModel == null) {
1865 throw new IllegalArgumentException("selectionModel must be non null");
1866 }
1867
1868 /* Remove the forwarding ListSelectionListener from the old
1869 * selectionModel, and add it to the new one, if necessary.
1870 */
1871 if (selectionListener != null) {
1872 this.selectionModel.removeListSelectionListener(selectionListener);
1873 selectionModel.addListSelectionListener(selectionListener);
1874 }
1875
1876 ListSelectionModel oldValue = this.selectionModel;
1877 this.selectionModel = selectionModel;
1878 firePropertyChange("selectionModel", oldValue, selectionModel);
1879 }
1880
1881
1882 /**
1888 * <li>{@code ListSelectionModel.SINGLE_SELECTION} -
1889 * Only one list index can be selected at a time. In this mode,
1890 * {@code setSelectionInterval} and {@code addSelectionInterval} are
1891 * equivalent, both replacing the current selection with the index
1892 * represented by the second argument (the "lead").
1893 * <li>{@code ListSelectionModel.SINGLE_INTERVAL_SELECTION} -
1894 * Only one contiguous interval can be selected at a time.
1895 * In this mode, {@code addSelectionInterval} behaves like
1896 * {@code setSelectionInterval} (replacing the current selection},
1897 * unless the given interval is immediately adjacent to or overlaps
1898 * the existing selection, and can be used to grow the selection.
1899 * <li>{@code ListSelectionModel.MULTIPLE_INTERVAL_SELECTION} -
1900 * In this mode, there's no restriction on what can be selected.
1901 * This mode is the default.
1902 * </ul>
1903 *
1904 * @param selectionMode the selection mode
1905 * @see #getSelectionMode
1906 * @throws IllegalArgumentException if the selection mode isn't
1907 * one of those allowed
1908 */
1909 @BeanProperty(bound = false, enumerationValues = {
1910 "ListSelectionModel.SINGLE_SELECTION",
1911 "ListSelectionModel.SINGLE_INTERVAL_SELECTION",
1912 "ListSelectionModel.MULTIPLE_INTERVAL_SELECTION"}, description
1913 = "The selection mode.")
1914 public void setSelectionMode(int selectionMode) {
1915 getSelectionModel().setSelectionMode(selectionMode);
1916 }
1917
1918 /**
1919 * Returns the current selection mode for the list. This is a cover
1920 * method that delegates to the method of the same name on the
1921 * list's selection model.
1922 *
1923 * @return the current selection mode
1924 * @see #setSelectionMode
1925 */
1926 public int getSelectionMode() {
1927 return getSelectionModel().getSelectionMode();
1928 }
1929
1930
1931 /**
1932 * Returns the anchor selection index. This is a cover method that
1933 * delegates to the method of the same name on the list's selection model.
1934 *
1935 * @return the anchor selection index
1936 * @see ListSelectionModel#getAnchorSelectionIndex
1937 */
1938 @BeanProperty(bound = false)
1939 public int getAnchorSelectionIndex() {
1940 return getSelectionModel().getAnchorSelectionIndex();
1941 }
1942
1943
1944 /**
1945 * Returns the lead selection index. This is a cover method that
1946 * delegates to the method of the same name on the list's selection model.
1947 *
1948 * @return the lead selection index
1949 * @see ListSelectionModel#getLeadSelectionIndex
1950 */
1951 @BeanProperty(bound = false, description
1952 = "The lead selection index.")
1953 public int getLeadSelectionIndex() {
1954 return getSelectionModel().getLeadSelectionIndex();
1955 }
1956
1957
1958 /**
1959 * Returns the smallest selected cell index, or {@code -1} if the selection
1960 * is empty. This is a cover method that delegates to the method of the same
1961 * name on the list's selection model.
1962 *
1963 * @return the smallest selected cell index, or {@code -1}
1964 * @see ListSelectionModel#getMinSelectionIndex
1965 */
1966 @BeanProperty(bound = false)
1967 public int getMinSelectionIndex() {
1968 return getSelectionModel().getMinSelectionIndex();
1969 }
1970
1971
1972 /**
1973 * Returns the largest selected cell index, or {@code -1} if the selection
1974 * is empty. This is a cover method that delegates to the method of the same
1975 * name on the list's selection model.
1976 *
1977 * @return the largest selected cell index
1978 * @see ListSelectionModel#getMaxSelectionIndex
1979 */
1980 @BeanProperty(bound = false)
1981 public int getMaxSelectionIndex() {
1982 return getSelectionModel().getMaxSelectionIndex();
1983 }
1984
1985
1986 /**
1987 * Returns {@code true} if the specified index is selected,
1988 * else {@code false}. This is a cover method that delegates to the method
1989 * of the same name on the list's selection model.
1990 *
1991 * @param index index to be queried for selection state
1992 * @return {@code true} if the specified index is selected,
1993 * else {@code false}
1994 * @see ListSelectionModel#isSelectedIndex
1995 * @see #setSelectedIndex
1996 */
1997 public boolean isSelectedIndex(int index) {
1998 return getSelectionModel().isSelectedIndex(index);
1999 }
2000
2001
2002 /**
2003 * Returns {@code true} if nothing is selected, else {@code false}.
2004 * This is a cover method that delegates to the method of the same
2005 * name on the list's selection model.
2006 *
2007 * @return {@code true} if nothing is selected, else {@code false}
2008 * @see ListSelectionModel#isSelectionEmpty
2009 * @see #clearSelection
2010 */
2011 @BeanProperty(bound = false)
2012 public boolean isSelectionEmpty() {
2013 return getSelectionModel().isSelectionEmpty();
2014 }
2015
2016
2017 /**
2018 * Clears the selection; after calling this method, {@code isSelectionEmpty}
2019 * will return {@code true}. This is a cover method that delegates to the
2020 * method of the same name on the list's selection model.
2021 *
2022 * @see ListSelectionModel#clearSelection
2023 * @see #isSelectionEmpty
2024 */
2025 public void clearSelection() {
2026 getSelectionModel().clearSelection();
2027 }
2028
2029
2030 /**
2031 * Selects the specified interval. Both {@code anchor} and {@code lead}
2166 rvTmp[n++] = i;
2167 }
2168 }
2169 int[] rv = new int[n];
2170 System.arraycopy(rvTmp, 0, rv, 0, n);
2171 return rv;
2172 }
2173
2174
2175 /**
2176 * Selects a single cell. Does nothing if the given index is greater
2177 * than or equal to the model size. This is a convenience method that uses
2178 * {@code setSelectionInterval} on the selection model. Refer to the
2179 * documentation for the selection model class being used for details on
2180 * how values less than {@code 0} are handled.
2181 *
2182 * @param index the index of the cell to select
2183 * @see ListSelectionModel#setSelectionInterval
2184 * @see #isSelectedIndex
2185 * @see #addListSelectionListener
2186 */
2187 @BeanProperty(bound = false, description
2188 = "The index of the selected cell.")
2189 public void setSelectedIndex(int index) {
2190 if (index >= getModel().getSize()) {
2191 return;
2192 }
2193 getSelectionModel().setSelectionInterval(index, index);
2194 }
2195
2196
2197 /**
2198 * Changes the selection to be the set of indices specified by the given
2199 * array. Indices greater than or equal to the model size are ignored.
2200 * This is a convenience method that clears the selection and then uses
2201 * {@code addSelectionInterval} on the selection model to add the indices.
2202 * Refer to the documentation of the selection model class being used for
2203 * details on how values less than {@code 0} are handled.
2204 *
2205 * @param indices an array of the indices of the cells to select,
2206 * {@code non-null}
2207 * @see ListSelectionModel#addSelectionInterval
2208 * @see #isSelectedIndex
2216 for (int i : indices) {
2217 if (i < size) {
2218 sm.addSelectionInterval(i, i);
2219 }
2220 }
2221 }
2222
2223
2224 /**
2225 * Returns an array of all the selected values, in increasing order based
2226 * on their indices in the list.
2227 *
2228 * @return the selected values, or an empty array if nothing is selected
2229 * @see #isSelectedIndex
2230 * @see #getModel
2231 * @see #addListSelectionListener
2232 *
2233 * @deprecated As of JDK 1.7, replaced by {@link #getSelectedValuesList()}
2234 */
2235 @Deprecated
2236 @BeanProperty(bound = false)
2237 public Object[] getSelectedValues() {
2238 ListSelectionModel sm = getSelectionModel();
2239 ListModel<E> dm = getModel();
2240
2241 int iMin = sm.getMinSelectionIndex();
2242 int iMax = sm.getMaxSelectionIndex();
2243
2244 if ((iMin < 0) || (iMax < 0)) {
2245 return new Object[0];
2246 }
2247
2248 Object[] rvTmp = new Object[1+ (iMax - iMin)];
2249 int n = 0;
2250 for(int i = iMin; i <= iMax; i++) {
2251 if (sm.isSelectedIndex(i)) {
2252 rvTmp[n++] = dm.getElementAt(i);
2253 }
2254 }
2255 Object[] rv = new Object[n];
2256 System.arraycopy(rvTmp, 0, rv, 0, n);
2257 return rv;
2258 }
2259
2260 /**
2261 * Returns a list of all the selected items, in increasing order based
2262 * on their indices in the list.
2263 *
2264 * @return the selected items, or an empty list if nothing is selected
2265 * @see #isSelectedIndex
2266 * @see #getModel
2267 * @see #addListSelectionListener
2268 *
2269 * @since 1.7
2270 */
2271 @BeanProperty(bound = false)
2272 public List<E> getSelectedValuesList() {
2273 ListSelectionModel sm = getSelectionModel();
2274 ListModel<E> dm = getModel();
2275
2276 int iMin = sm.getMinSelectionIndex();
2277 int iMax = sm.getMaxSelectionIndex();
2278
2279 if ((iMin < 0) || (iMax < 0)) {
2280 return Collections.emptyList();
2281 }
2282
2283 List<E> selectedItems = new ArrayList<E>();
2284 for(int i = iMin; i <= iMax; i++) {
2285 if (sm.isSelectedIndex(i)) {
2286 selectedItems.add(dm.getElementAt(i));
2287 }
2288 }
2289 return selectedItems;
2290 }
2291
2304 */
2305 public int getSelectedIndex() {
2306 return getMinSelectionIndex();
2307 }
2308
2309
2310 /**
2311 * Returns the value for the smallest selected cell index;
2312 * <i>the selected value</i> when only a single item is selected in the
2313 * list. When multiple items are selected, it is simply the value for the
2314 * smallest selected index. Returns {@code null} if there is no selection.
2315 * <p>
2316 * This is a convenience method that simply returns the model value for
2317 * {@code getMinSelectionIndex}.
2318 *
2319 * @return the first selected value
2320 * @see #getMinSelectionIndex
2321 * @see #getModel
2322 * @see #addListSelectionListener
2323 */
2324 @BeanProperty(bound = false)
2325 public E getSelectedValue() {
2326 int i = getMinSelectionIndex();
2327 return (i == -1) ? null : getModel().getElementAt(i);
2328 }
2329
2330
2331 /**
2332 * Selects the specified object from the list.
2333 *
2334 * @param anObject the object to select
2335 * @param shouldScroll {@code true} if the list should scroll to display
2336 * the selected object, if one exists; otherwise {@code false}
2337 */
2338 public void setSelectedValue(Object anObject,boolean shouldScroll) {
2339 if(anObject == null)
2340 setSelectedIndex(-1);
2341 else if(!anObject.equals(getSelectedValue())) {
2342 int i,c;
2343 ListModel<E> dm = getModel();
2344 for(i=0,c=dm.getSize();i<c;i++)
2394 * by {@code visibleRowCount}, if {@code fixedCellHeight} is greater than
2395 * {@code 0}, otherwise it is a hard-coded value of {@code 16} multiplied by
2396 * {@code visibleRowCount}.
2397 * <p>
2398 * If the model isn't empty, the width is the preferred size's width,
2399 * typically the width of the widest list element. The height is the
2400 * {@code fixedCellHeight} multiplied by the {@code visibleRowCount},
2401 * plus the list's vertical insets.
2402 * <p>
2403 * <b>{@code VERTICAL_WRAP} or {@code HORIZONTAL_WRAP}:</b>
2404 * <br>
2405 * This method simply returns the value from {@code getPreferredSize}.
2406 * The list's {@code ListUI} is expected to override {@code getPreferredSize}
2407 * to return an appropriate value.
2408 *
2409 * @return a dimension containing the size of the viewport needed
2410 * to display {@code visibleRowCount} rows
2411 * @see #getPreferredScrollableViewportSize
2412 * @see #setPrototypeCellValue
2413 */
2414 @BeanProperty(bound = false)
2415 public Dimension getPreferredScrollableViewportSize()
2416 {
2417 if (getLayoutOrientation() != VERTICAL) {
2418 return getPreferredSize();
2419 }
2420 Insets insets = getInsets();
2421 int dx = insets.left + insets.right;
2422 int dy = insets.top + insets.bottom;
2423
2424 int visibleRowCount = getVisibleRowCount();
2425 int fixedCellWidth = getFixedCellWidth();
2426 int fixedCellHeight = getFixedCellHeight();
2427
2428 if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
2429 int width = fixedCellWidth + dx;
2430 int height = (visibleRowCount * fixedCellHeight) + dy;
2431 return new Dimension(width, height);
2432 }
2433 else if (getModel().getSize() > 0) {
2434 int width = getPreferredSize().width;
2732 return inc;
2733 }
2734 return visibleRect.width;
2735 }
2736
2737
2738 /**
2739 * Returns {@code true} if this {@code JList} is displayed in a
2740 * {@code JViewport} and the viewport is wider than the list's
2741 * preferred width, or if the layout orientation is {@code HORIZONTAL_WRAP}
2742 * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2743 * <p>
2744 * If {@code false}, then don't track the viewport's width. This allows
2745 * horizontal scrolling if the {@code JViewport} is itself embedded in a
2746 * {@code JScrollPane}.
2747 *
2748 * @return whether or not an enclosing viewport should force the list's
2749 * width to match its own
2750 * @see Scrollable#getScrollableTracksViewportWidth
2751 */
2752 @BeanProperty(bound = false)
2753 public boolean getScrollableTracksViewportWidth() {
2754 if (getLayoutOrientation() == HORIZONTAL_WRAP &&
2755 getVisibleRowCount() <= 0) {
2756 return true;
2757 }
2758 Container parent = SwingUtilities.getUnwrappedParent(this);
2759 if (parent instanceof JViewport) {
2760 return parent.getWidth() > getPreferredSize().width;
2761 }
2762 return false;
2763 }
2764
2765 /**
2766 * Returns {@code true} if this {@code JList} is displayed in a
2767 * {@code JViewport} and the viewport is taller than the list's
2768 * preferred height, or if the layout orientation is {@code VERTICAL_WRAP}
2769 * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2770 * <p>
2771 * If {@code false}, then don't track the viewport's height. This allows
2772 * vertical scrolling if the {@code JViewport} is itself embedded in a
2773 * {@code JScrollPane}.
2774 *
2775 * @return whether or not an enclosing viewport should force the list's
2776 * height to match its own
2777 * @see Scrollable#getScrollableTracksViewportHeight
2778 */
2779 @BeanProperty(bound = false)
2780 public boolean getScrollableTracksViewportHeight() {
2781 if (getLayoutOrientation() == VERTICAL_WRAP &&
2782 getVisibleRowCount() <= 0) {
2783 return true;
2784 }
2785 Container parent = SwingUtilities.getUnwrappedParent(this);
2786 if (parent instanceof JViewport) {
2787 return parent.getHeight() > getPreferredSize().height;
2788 }
2789 return false;
2790 }
2791
2792
2793 /*
2794 * See {@code readObject} and {@code writeObject} in {@code JComponent}
2795 * for more information about serialization in Swing.
2796 */
2797 private void writeObject(ObjectOutputStream s) throws IOException {
2798 s.defaultWriteObject();
2799 if (getUIClassID().equals(uiClassID)) {
2831 ",selectionForeground=" + selectionForegroundString +
2832 ",visibleRowCount=" + visibleRowCount +
2833 ",layoutOrientation=" + layoutOrientation;
2834 }
2835
2836
2837 /**
2838 * --- Accessibility Support ---
2839 */
2840
2841 /**
2842 * Gets the {@code AccessibleContext} associated with this {@code JList}.
2843 * For {@code JList}, the {@code AccessibleContext} takes the form of an
2844 * {@code AccessibleJList}.
2845 * <p>
2846 * A new {@code AccessibleJList} instance is created if necessary.
2847 *
2848 * @return an {@code AccessibleJList} that serves as the
2849 * {@code AccessibleContext} of this {@code JList}
2850 */
2851 @BeanProperty(bound = false)
2852 public AccessibleContext getAccessibleContext() {
2853 if (accessibleContext == null) {
2854 accessibleContext = new AccessibleJList();
2855 }
2856 return accessibleContext;
2857 }
2858
2859 /**
2860 * This class implements accessibility support for the
2861 * {@code JList} class. It provides an implementation of the
2862 * Java Accessibility API appropriate to list user-interface
2863 * elements.
2864 * <p>
2865 * <strong>Warning:</strong>
2866 * Serialized objects of this class will not be compatible with
2867 * future Swing releases. The current serialization support is
2868 * appropriate for short term storage or RMI between applications running
2869 * the same version of Swing. As of 1.4, support for long term storage
2870 * of all JavaBeans™
2871 * has been added to the <code>java.beans</code> package.
|